/* * libgit2 "cat-file" example - shows how to print data from the ODB * * Written by the libgit2 contributors * * To the extent possible under law, the author(s) have dedicated all copyright * and related and neighboring rights to this software to the public domain * worldwide. This software is distributed without any warranty. * * You should have received a copy of the CC0 Public Domain Dedication along * with this software. If not, see * . */ #![deny(warnings)] use std::io::{self, Write}; use git2::{Blob, Commit, ObjectType, Repository, Signature, Tag, Tree}; use structopt::StructOpt; #[derive(StructOpt)] struct Args { #[structopt(name = "object")] arg_object: String, #[structopt(short = "t")] /// show the object type flag_t: bool, #[structopt(short = "s")] /// show the object size flag_s: bool, #[structopt(short = "e")] /// suppress all output flag_e: bool, #[structopt(short = "p")] /// pretty print the contents of the object flag_p: bool, #[structopt(name = "quiet", short, long)] /// suppress output flag_q: bool, #[structopt(name = "verbose", short, long)] flag_v: bool, #[structopt(name = "dir", long = "git-dir")] /// use the specified directory as the base directory flag_git_dir: Option, } fn run(args: &Args) -> Result<(), git2::Error> { let path = args.flag_git_dir.as_ref().map(|s| &s[..]).unwrap_or("."); let repo = Repository::open(path)?; let obj = repo.revparse_single(&args.arg_object)?; if args.flag_v && !args.flag_q { println!("{} {}\n--", obj.kind().unwrap().str(), obj.id()); } if args.flag_t { println!("{}", obj.kind().unwrap().str()); } else if args.flag_s || args.flag_e { /* ... */ } else if args.flag_p { match obj.kind() { Some(ObjectType::Blob) => { show_blob(obj.as_blob().unwrap()); } Some(ObjectType::Commit) => { show_commit(obj.as_commit().unwrap()); } Some(ObjectType::Tag) => { show_tag(obj.as_tag().unwrap()); } Some(ObjectType::Tree) => { show_tree(obj.as_tree().unwrap()); } Some(ObjectType::Any) | None => println!("unknown {}", obj.id()), } } Ok(()) } fn show_blob(blob: &Blob) { io::stdout().write_all(blob.content()).unwrap(); } fn show_commit(commit: &Commit) { println!("tree {}", commit.tree_id()); for parent in commit.parent_ids() { println!("parent {}", parent); } show_sig("author", Some(commit.author())); show_sig("committer", Some(commit.committer())); if let Some(msg) = commit.message() { println!("\n{}", msg); } } fn show_tag(tag: &Tag) { println!("object {}", tag.target_id()); println!("type {}", tag.target_type().unwrap().str()); println!("tag {}", tag.name().unwrap()); show_sig("tagger", tag.tagger()); if let Some(msg) = tag.message() { println!("\n{}", msg); } } fn show_tree(tree: &Tree) { for entry in tree.iter() { println!( "{:06o} {} {}\t{}", entry.filemode(), entry.kind().unwrap().str(), entry.id(), entry.name().unwrap() ); } } fn show_sig(header: &str, sig: Option) { let sig = match sig { Some(s) => s, None => return, }; let offset = sig.when().offset_minutes(); let (sign, offset) = if offset < 0 { ('-', -offset) } else { ('+', offset) }; let (hours, minutes) = (offset / 60, offset % 60); println!( "{} {} {} {}{:02}{:02}", header, sig, sig.when().seconds(), sign, hours, minutes ); } fn main() { let args = Args::from_args(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), } }