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
|
/*
* 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
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#![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 <spec>
flag_not: Vec<String>,
#[structopt(name = "spec", last = true)]
arg_spec: Vec<String>,
}
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),
}
}
|