Skip to content
This repository was archived by the owner on Jan 19, 2021. It is now read-only.

Commit d09c7bd

Browse files
committed
Added simple git cat-file sample
1 parent cd84dc1 commit d09c7bd

File tree

6 files changed

+190
-13
lines changed

6 files changed

+190
-13
lines changed

include/cppgit2/object.hpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class object : public libgit2_api {
3939
ref_delta = 7
4040
};
4141

42+
// object tyoe to string
43+
static std::string object_type_to_string(object_type type);
44+
4245
using object_size = git_object_size_t;
4346

4447
// Recursively peel until an object of the specified type is met
@@ -62,16 +65,30 @@ class object : public libgit2_api {
6265
// Get owner repository
6366
class repository owner() const;
6467

65-
git_object *c_ptr() { return c_ptr_; }
68+
// Cast to blob
69+
// Throws git_exception if object is not a blob
70+
class blob as_blob();
6671

67-
const git_object *c_ptr() const { return c_ptr_; }
72+
// Cast to commit
73+
// Throws git_exception if object is not a commit
74+
class commit as_commit();
75+
76+
// Cast to tree
77+
// Throws git_exception if object is not a tree
78+
class tree as_tree();
6879

69-
git_object **c_ptr_ptr() { return &c_ptr_; }
80+
// Cast to tag
81+
// Throws git_exception if object is not a tag
82+
class tag as_tag();
83+
84+
// Access libgit2 C ptr
85+
const git_object *c_ptr() const { return c_ptr_; }
7086

7187
private:
7288
friend class reference;
7389
friend class repository;
7490
friend class revspec;
91+
friend class tag;
7592
ownership owner_;
7693
git_object *c_ptr_;
7794
};

include/cppgit2/remote.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,9 @@ class remote : public libgit2_api {
229229
void stop();
230230

231231
// Update the tips to the new state
232-
void update_tips(const callbacks &remote_callbacks, bool update_fetchhead,
233-
fetch::options::autotag download_tags, const std::string &reflog_message);
232+
void update_tips(const callbacks &remote_callbacks, bool update_fetchhead,
233+
fetch::options::autotag download_tags,
234+
const std::string &reflog_message);
234235

235236
// Create a packfile and send it to the server
236237
//

samples/cat_file.cpp

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#include <cppgit2/repository.hpp>
2+
#include <cstdio>
3+
#include <iomanip>
4+
#include <iostream>
5+
using namespace cppgit2;
6+
7+
void print_signature(const std::string &header, const signature &sig) {
8+
char sign;
9+
auto offset = sig.offset();
10+
if (offset < 0) {
11+
sign = '-';
12+
offset = -offset;
13+
} else {
14+
sign = '+';
15+
}
16+
17+
auto hours = offset / 60;
18+
auto minutes = offset % 60;
19+
20+
std::cout << header << " "
21+
<< sig.name() << " "
22+
<< "<" << sig.email() << "> "
23+
<< sig.time() << " "
24+
<< sign;
25+
std::cout << std::setw(2) << hours << minutes << std::endl;
26+
}
27+
28+
// Printing out a blob is simple, get the contents and print
29+
void show_blob(const blob &blob) {
30+
std::fwrite(blob.raw_contents(), blob.raw_size(), 1, stdout);
31+
}
32+
33+
// Show each entry with its type, id and attributes
34+
void show_tree(const tree &tree) {
35+
size_t count = tree.size();
36+
for (size_t i = 0; i < tree.size(); ++i) {
37+
auto entry = tree.lookup_entry_by_index(i);
38+
39+
std::cout << std::oct << std::setw(6) << static_cast<git_filemode_t>(entry.filemode());
40+
std::cout << " " << object::object_type_to_string(entry.type())
41+
<< " " << tree.id().to_hex_string()
42+
<< "\t" << entry.filename() << std::endl;
43+
}
44+
}
45+
46+
// Commits and tags have a few interesting fields in their header.
47+
void show_commit(const commit &commit) {
48+
std::cout << "tree " << commit.id().to_hex_string() << std::endl;
49+
50+
for (size_t i = 0; i < commit.parent_count(); ++i)
51+
std::cout << "parent " << commit.parent_id(i).to_hex_string() << std::endl;
52+
53+
print_signature("author", commit.author());
54+
print_signature("committer", commit.committer());
55+
56+
auto message = commit.message();
57+
if (!message.empty())
58+
std::cout << "\n" << message << std::endl;
59+
}
60+
61+
void show_tag(const tag &tag) {
62+
std::cout << "object " << tag.id().to_hex_string() << std::endl;
63+
std::cout << "type " << object::object_type_to_string(tag.target_type()) << std::endl;
64+
std::cout << "tag " << tag.name() << std::endl;
65+
print_signature("tagger", tag.tagger());
66+
67+
auto tag_message = tag.message();
68+
if (!tag_message.empty())
69+
std::cout << "\n" << tag_message << std::endl;
70+
}
71+
72+
int main(int argc, char **argv) {
73+
if (argc == 3) {
74+
auto repo_path = repository::discover_path(".");
75+
auto repo = repository::open(repo_path);
76+
77+
enum class actions { size, type, pretty };
78+
actions action;
79+
80+
if (strncmp(argv[1], "-s", 2) == 0) {
81+
action = actions::size;
82+
} else if (strncmp(argv[1], "-t", 2) == 0) {
83+
action = actions::type;
84+
} else if (strncmp(argv[1], "-p", 2) == 0) {
85+
action = actions::pretty;
86+
}
87+
88+
auto revision_str = argv[2];
89+
auto object = repo.revparse_to_object(revision_str);
90+
91+
switch(action) {
92+
case actions::type:
93+
std::cout << object::object_type_to_string(object.type()) << std::endl;
94+
break;
95+
case actions::size:
96+
std::cout << repo.odb().read(object.id()).size() << std::endl;
97+
break;
98+
case actions::pretty:
99+
switch(object.type()) {
100+
case object::object_type::blob:
101+
show_blob(object.as_blob());
102+
break;
103+
case object::object_type::commit:
104+
show_commit(object.as_commit());
105+
break;
106+
case object::object_type::tree:
107+
show_tree(object.as_tree());
108+
break;
109+
case object::object_type::tag:
110+
show_tag(object.as_tag());
111+
break;
112+
default:
113+
std::cout << "unknown " << revision_str << std::endl;
114+
break;
115+
}
116+
break;
117+
}
118+
119+
} else {
120+
std::cout << "Usage: ./executable (-s | -t | -p) <object>\n";
121+
}
122+
}

src/object.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ object object::copy() const {
2929
return result;
3030
}
3131

32+
std::string object::object_type_to_string(object_type type) {
33+
auto ret = git_object_type2string(static_cast<git_object_t>(type));
34+
return ret ? std::string(ret) : "";
35+
}
36+
3237
object object::peel_until(object_type target_type) {
3338
object result;
3439
if (git_object_peel(&result.c_ptr_, c_ptr_,
@@ -61,4 +66,32 @@ repository object::owner() const {
6166
return repository(git_object_owner(c_ptr_));
6267
}
6368

69+
blob object::as_blob() {
70+
if (type() == object::object_type::blob)
71+
return blob((git_blob *)c_ptr_);
72+
else
73+
throw git_exception("object is not a blob");
74+
}
75+
76+
commit object::as_commit() {
77+
if (type() == object::object_type::commit)
78+
return commit((git_commit *)c_ptr_);
79+
else
80+
throw git_exception("object is not a commit");
81+
}
82+
83+
tree object::as_tree() {
84+
if (type() == object::object_type::tree)
85+
return tree((git_tree *)c_ptr_);
86+
else
87+
throw git_exception("object is not a tree");
88+
}
89+
90+
tag object::as_tag() {
91+
if (type() == object::object_type::tag)
92+
return tag((git_tag *)c_ptr_);
93+
else
94+
throw git_exception("object is not a tag");
95+
}
96+
6497
} // namespace cppgit2

src/remote.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ bool remote::is_valid_name(const std::string &name) {
100100
}
101101

102102
std::vector<remote::head> remote::reference_advertisement_list() {
103-
const git_remote_head * head_ptr = nullptr;
104-
const git_remote_head ** head_ptr_ptr = &head_ptr;
103+
const git_remote_head *head_ptr = nullptr;
104+
const git_remote_head **head_ptr_ptr = &head_ptr;
105105
size_t size = 0;
106106
if (git_remote_ls(&head_ptr_ptr, &size, c_ptr_))
107107
throw git_exception();
@@ -156,10 +156,14 @@ void remote::stop() {
156156
throw git_exception();
157157
}
158158

159-
void remote::update_tips(const callbacks &remote_callbacks, bool update_fetchhead,
160-
fetch::options::autotag download_tags, const std::string &reflog_message) {
161-
if (git_remote_update_tips(c_ptr_, remote_callbacks.c_ptr(), update_fetchhead,
162-
static_cast<git_remote_autotag_option_t>(download_tags), reflog_message.c_str()))
159+
void remote::update_tips(const callbacks &remote_callbacks,
160+
bool update_fetchhead,
161+
fetch::options::autotag download_tags,
162+
const std::string &reflog_message) {
163+
if (git_remote_update_tips(
164+
c_ptr_, remote_callbacks.c_ptr(), update_fetchhead,
165+
static_cast<git_remote_autotag_option_t>(download_tags),
166+
reflog_message.c_str()))
163167
throw git_exception();
164168
}
165169

src/tag.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ std::string tag::name() const {
3737

3838
object tag::peel() const {
3939
object result;
40-
if (git_tag_peel(result.c_ptr_ptr(), c_ptr_))
40+
if (git_tag_peel(&result.c_ptr_, c_ptr_))
4141
throw git_exception();
4242
return result;
4343
}
@@ -46,7 +46,7 @@ signature tag::tagger() const { return signature(git_tag_tagger(c_ptr_)); }
4646

4747
object tag::target() const {
4848
object result;
49-
if (git_tag_target(result.c_ptr_ptr(), c_ptr_))
49+
if (git_tag_target(&result.c_ptr_, c_ptr_))
5050
throw git_exception();
5151
return result;
5252
}

0 commit comments

Comments
 (0)