1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
/*
* 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
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#![deny(warnings)]
use std::io::{self, Write};
use clap::Parser;
use git2::{Blob, Commit, ObjectType, Repository, Signature, Tag, Tree};
#[derive(Parser)]
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<String>,
}
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<Signature>) {
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::parse();
match run(&args) {
Ok(()) => {}
Err(e) => println!("error: {}", e),
}
}
|