/* * libgit2 "rev-list" example - shows how to transform a rev-spec into a list * of commit ids * * 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 clap::Parser; use git2::{Error, Oid, Repository, Revwalk}; #[derive(Parser)] struct Args { #[structopt(name = "topo-order", long)] /// sort commits in topological order flag_topo_order: bool, #[structopt(name = "date-order", long)] /// sort commits in date order flag_date_order: bool, #[structopt(name = "reverse", long)] /// sort commits in reverse flag_reverse: bool, #[structopt(name = "not")] /// don't show flag_not: Vec, #[structopt(name = "spec", last = true)] arg_spec: Vec, } fn run(args: &Args) -> Result<(), git2::Error> { let repo = Repository::open(".")?; let mut revwalk = repo.revwalk()?; let base = if args.flag_reverse { git2::Sort::REVERSE } else { git2::Sort::NONE }; revwalk.set_sorting( base | if args.flag_topo_order { git2::Sort::TOPOLOGICAL } else if args.flag_date_order { git2::Sort::TIME } else { git2::Sort::NONE }, )?; let specs = args .flag_not .iter() .map(|s| (s, true)) .chain(args.arg_spec.iter().map(|s| (s, false))) .map(|(spec, hide)| { if spec.starts_with('^') { (&spec[1..], !hide) } else { (&spec[..], hide) } }); for (spec, hide) in specs { let id = if spec.contains("..") { let revspec = repo.revparse(spec)?; if revspec.mode().contains(git2::RevparseMode::MERGE_BASE) { return Err(Error::from_str("merge bases not implemented")); } push(&mut revwalk, revspec.from().unwrap().id(), !hide)?; revspec.to().unwrap().id() } else { repo.revparse_single(spec)?.id() }; push(&mut revwalk, id, hide)?; } for id in revwalk { let id = id?; println!("{}", id); } Ok(()) } fn push(revwalk: &mut Revwalk, id: Oid, hide: bool) -> Result<(), Error> { if hide { revwalk.hide(id) } else { revwalk.push(id) } } fn main() { let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), } }