mirror of
https://git.proxmox.com/git/rustc
synced 2025-08-13 03:55:49 +00:00
150 lines
3.9 KiB
Rust
150 lines
3.9 KiB
Rust
/*
|
|
* 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),
|
|
}
|
|
}
|