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

Commit 46e4c6f

Browse files
authored
Update README.md
1 parent 429bc68 commit 46e4c6f

File tree

1 file changed

+182
-0
lines changed

1 file changed

+182
-0
lines changed

README.md

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,188 @@ $ ./build/samples/print_tags ext/libgit2
437437
...
438438
```
439439

440+
### Inspect Repository Objects (`git cat-file`)
441+
442+
Here's a ~125 line simplified implementation of `git cat-file` with `cppgit2`
443+
444+
```cpp
445+
#include <cppgit2/repository.hpp>
446+
#include <cstdio>
447+
#include <iomanip>
448+
#include <iostream>
449+
using namespace cppgit2;
450+
451+
void print_signature(const std::string &header, const signature &sig) {
452+
char sign;
453+
auto offset = sig.offset();
454+
if (offset < 0) {
455+
sign = '-';
456+
offset = -offset;
457+
} else {
458+
sign = '+';
459+
}
460+
461+
auto hours = offset / 60;
462+
auto minutes = offset % 60;
463+
464+
std::cout << header << " "
465+
<< sig.name() << " "
466+
<< "<" << sig.email() << "> "
467+
<< sig.time() << " "
468+
<< sign;
469+
std::cout << std::setfill('0') << std::setw(2) << hours;
470+
std::cout << std::setfill('0') << std::setw(2) << minutes << std::endl;
471+
}
472+
473+
// Printing out a blob is simple, get the contents and print
474+
void show_blob(const blob &blob) {
475+
std::fwrite(blob.raw_contents(), blob.raw_size(), 1, stdout);
476+
}
477+
478+
// Show each entry with its type, id and attributes
479+
void show_tree(const tree &tree) {
480+
size_t count = tree.size();
481+
for (size_t i = 0; i < tree.size(); ++i) {
482+
auto entry = tree.lookup_entry_by_index(i);
483+
484+
std::cout << std::setfill('0') <<
485+
std::oct << std::setw(6) << static_cast<git_filemode_t>(entry.filemode());
486+
std::cout << " " << object::object_type_to_string(entry.type())
487+
<< " " << entry.id().to_hex_string()
488+
<< "\t" << entry.filename() << std::endl;
489+
}
490+
}
491+
492+
// Commits and tags have a few interesting fields in their header.
493+
void show_commit(const commit &commit) {
494+
std::cout << "tree " << commit.tree_id().to_hex_string() << std::endl;
495+
496+
for (size_t i = 0; i < commit.parent_count(); ++i)
497+
std::cout << "parent " << commit.parent_id(i).to_hex_string() << std::endl;
498+
499+
print_signature("author", commit.author());
500+
print_signature("committer", commit.committer());
501+
502+
auto message = commit.message();
503+
if (!message.empty())
504+
std::cout << "\n" << message << std::endl;
505+
}
506+
507+
void show_tag(const tag &tag) {
508+
std::cout << "object " << tag.id().to_hex_string() << std::endl;
509+
std::cout << "type " << object::object_type_to_string(tag.target_type()) << std::endl;
510+
std::cout << "tag " << tag.name() << std::endl;
511+
print_signature("tagger", tag.tagger());
512+
513+
auto tag_message = tag.message();
514+
if (!tag_message.empty())
515+
std::cout << "\n" << tag_message << std::endl;
516+
}
517+
518+
int main(int argc, char **argv) {
519+
if (argc == 3) {
520+
auto repo_path = repository::discover_path(".");
521+
auto repo = repository::open(repo_path);
522+
523+
enum class actions { size, type, pretty };
524+
actions action;
525+
526+
if (strncmp(argv[1], "-s", 2) == 0) {
527+
action = actions::size;
528+
} else if (strncmp(argv[1], "-t", 2) == 0) {
529+
action = actions::type;
530+
} else if (strncmp(argv[1], "-p", 2) == 0) {
531+
action = actions::pretty;
532+
}
533+
534+
auto revision_str = argv[2];
535+
auto object = repo.revparse_to_object(revision_str);
536+
537+
switch(action) {
538+
case actions::type:
539+
std::cout << object::object_type_to_string(object.type()) << std::endl;
540+
break;
541+
case actions::size:
542+
std::cout << repo.odb().read(object.id()).size() << std::endl;
543+
break;
544+
case actions::pretty:
545+
switch(object.type()) {
546+
case object::object_type::blob:
547+
show_blob(object.as_blob());
548+
break;
549+
case object::object_type::commit:
550+
show_commit(object.as_commit());
551+
break;
552+
case object::object_type::tree:
553+
show_tree(object.as_tree());
554+
break;
555+
case object::object_type::tag:
556+
show_tag(object.as_tag());
557+
break;
558+
default:
559+
std::cout << "unknown " << revision_str << std::endl;
560+
break;
561+
}
562+
break;
563+
}
564+
565+
} else {
566+
std::cout << "Usage: ./executable (-s | -t | -p) <object>\n";
567+
}
568+
}
569+
```
570+
571+
Running this sample on one of the `libgit2` commits yields the following:
572+
573+
```bash
574+
$ ./cat_file -p 01a8340662749943f3917505dc8ca65006495bec
575+
tree 83d9bef2675178eeb3aa61d17e5c8b0f7b0ec1de
576+
parent 76b49caf6a208e44d19c84caa6d42389f0de6194
577+
author Patrick Steinhardt <ps@pks.im> 1582035643 +0100
578+
committer Patrick Steinhardt <ps@pks.im> 1582040632 +0100
579+
580+
azure: docker: fix ARM builds by replacing gosu(1)
581+
582+
Our nightly builds are currently failing due to our ARM-based jobs.
583+
These jobs crash immediately when entering the Docker container with a
584+
exception thrown by Go's language runtime. As we're able to successfully
585+
builds the Docker images in previous steps, it's unlikely to be a bug in
586+
Docker itself. Instead, this exception is thrown by gosu(1), which is a
587+
Go-based utility to drop privileges and run by our entrypoint.
588+
589+
Fix the issue by dropping gosu(1) in favor of sudo(1).
590+
591+
$ ./cat_file -p 83d9bef2675178eeb3aa61d17e5c8b0f7b0ec1de
592+
100644 blob fd8430bc864cfcd5f10e5590f8a447e01b942bfe .HEADER
593+
100644 blob 34c5e9234ec18c69a16828dbc9633a95f0253fe9 .editorconfig
594+
100644 blob 176a458f94e0ea5272ce67c36bf30b6be9caf623 .gitattributes
595+
040000 tree e8bfe5af39579a7e4898bb23f3a76a72c368cee6 .github
596+
100644 blob dec3dca06c8fdc1dd7d426bb148b7f99355eaaed .gitignore
597+
100644 blob 0b16a7e1f1a368d5ca42d580ba2256d1faecddb8 .mailmap
598+
100644 blob 784bab3ee7da6133af679cae7527c4fe4a99b949 AUTHORS
599+
100644 blob 8765a97b5b120259dd59262865ce166f382c0f9e CMakeLists.txt
600+
100644 blob c0f61fb9158945f7b41abfd640630c914b2eb8d9 COPYING
601+
100644 blob 9dafffec02ef8d9cf8b97f547444f989ddbfa298 README.md
602+
100644 blob f98eebf505a37f756e0ad9d7cc4744397368c436 SECURITY.md
603+
100644 blob bf733273b8cd8b601aaee9a5c10d099a7f6a87e2 api.docurium
604+
100644 blob 2b593dd2cc2c2c252548c7fae4d469c11dd08430 azure-pipelines.yml
605+
040000 tree d9aba7f7d7e9651c176df311dd0489e89266b2b4 azure-pipelines
606+
040000 tree 64e8fd349c9c1dd20f810c22c4e62fe52aab5f18 cmake
607+
040000 tree 5c640a5abe072362ca4bbcf66ef66617c0be0466 deps
608+
040000 tree c84b6d0def9b4b790ece70c7ee68aa3fdf6caa85 docs
609+
040000 tree f852bee8c6bcc3e456f19aff773079eb30abf747 examples
610+
040000 tree 37aaf5d4a9fb0d89d2716236c49474030e36dc93 fuzzers
611+
100644 blob 905bdd24fa23c4d1a03e400a2ae8ecc639769da3 git.git-authors
612+
040000 tree 7fdd111f708aad900604883ce1c161daf64ebb2d include
613+
100644 blob d33f31c303663dbdbb4baed08ec3cd6c83116367 package.json
614+
040000 tree 97afcc9b6e4ca91001aadf8a3414d043f22918cf script
615+
040000 tree a08bd8a57d619b736ad2c300614b36ead8d0a333 src
616+
040000 tree dcf5925f8bbda8062ef26ca427c5110868a7f041 tests
617+
618+
$ ./cat_file -s 8765a97b5b120259dd59262865ce166f382c0f9e
619+
11957
620+
```
621+
440622
## Design Notes
441623

442624
### Interoperability with `libgit2`

0 commit comments

Comments
 (0)