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
mod files;
mod status;
use std::{env::current_dir as cwd, path::PathBuf, process::Command};
#[derive(Debug, PartialEq)]
pub enum Op {
Status(bool), Number(PathBuf), }
pub struct Opts {
pub op: Op,
pub cwd: PathBuf,
}
impl Opts {
pub fn cache_file(&self) -> Option<PathBuf> {
let mut t = Command::new("git");
t.args(["rev-parse", "--git-dir"]).current_dir(&self.cwd);
let output = t.output().ok()?;
let t = String::from_utf8_lossy(&output.stdout);
Some(PathBuf::from(t.trim_end()).join("gitnu.txt"))
}
}
pub fn parse(args: Vec<String>) -> (Vec<String>, Opts) {
let (mut res, mut iter, p) = (Vec::new(), args.iter(), |a: &str| a.into());
let mut o = Opts { cwd: cwd().unwrap_or(p(".")), op: Op::Number(p("git")) };
iter.next();
while let Some(arg) = iter.next() {
match arg.as_str() {
"status" => o.op = Op::Status(true),
"--short" | "-s" | "--porcelain" => match o.op {
Op::Status(_) => o.op = Op::Status(false),
_ => (),
},
"-c" | "-C" => {
match iter.next() {
Some(v) => match arg.as_str() {
"-c" => o.op = Op::Number(PathBuf::from(v)),
_ => o.cwd = PathBuf::from(v),
},
_ => (),
}
continue;
}
_ => (),
}
res.push(arg.to_string());
}
(res, o)
}
pub fn core(args: Vec<String>) -> (Vec<PathBuf>, Opts) {
let (args, opts) = parse(args);
(files::load(args, &opts), opts)
}
pub fn run(args: Vec<PathBuf>, opts: Opts) -> Option<()> {
match opts.op {
Op::Status(_) => status::run(args, opts),
Op::Number(cmd) => {
let mut cmd = Command::new(cmd);
cmd.args(args).spawn().ok()?.wait().map(|_| ()).ok()
}
}
}
#[cfg(test)]
mod tests;