@@ -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