1
use review_harvest::{git::harvest, gpg::load_keys};
2
use std::path::PathBuf;
3

            
4
const HELP: &str = "\
5
harvest
6

            
7
USAGE:
8
  harvest [OPTIONS]
9

            
10
FLAGS:
11
  -h, --help            Prints help information
12

            
13
OPTIONS:
14
  --input PATH          File with a list of git urls
15
  --output-dir PATH     Directory to check out the git repositories in
16
  --gpg-dir PATH        Provide a GPG directory to verify signatures
17
";
18

            
19
#[derive(Debug)]
20
struct Args {
21
    input: PathBuf,
22
    output_dir: PathBuf,
23
    gpg_dir: Option<PathBuf>,
24
}
25

            
26
12
fn parse_path(s: &std::ffi::OsStr) -> Result<std::path::PathBuf, &'static str> {
27
12
    Ok(s.into())
28
12
}
29

            
30
10
fn parse_args() -> Result<Args, pico_args::Error> {
31
10
    let mut pargs = pico_args::Arguments::from_env();
32
10

            
33
10
    // Help has a higher priority and should be handled separately.
34
10
    if pargs.contains(["-h", "--help"]) {
35
2
        print!("{}", HELP);
36
2
        std::process::exit(0);
37
8
    }
38
6
    let args = Args {
39
8
        input: pargs.value_from_os_str("--input", parse_path)?,
40
6
        output_dir: pargs.value_from_os_str("--output-dir", parse_path)?,
41
6
        gpg_dir: pargs.opt_value_from_os_str("--gpg-dir", parse_path)?,
42
    };
43
6
    let remaining_arguments = pargs.finish();
44
6
    if !remaining_arguments.is_empty() {
45
2
        eprintln!("There are unused arguments:");
46
4
        for remaining in remaining_arguments {
47
2
            if let Ok(remaining) = remaining.into_string() {
48
2
                eprintln!("Unused argument: {}", remaining);
49
2
            }
50
        }
51
2
        print!("{}", HELP);
52
2
        std::process::exit(1);
53
4
    }
54
4
    Ok(args)
55
6
}
56

            
57
10
fn main() -> Result<(), Box<dyn std::error::Error>> {
58
10
    let args = match parse_args() {
59
8
        Ok(v) => v,
60
2
        Err(e) => {
61
2
            eprintln!("Error: {}.", e);
62
2
            std::process::exit(1);
63
        }
64
    };
65
8
    let certs = if let Some(gpg_dir) = args.gpg_dir {
66
4
        load_keys(&gpg_dir)?
67
    } else {
68
4
        Vec::new()
69
    };
70
8
    let results = harvest(&args.input, &args.output_dir, &certs);
71
8
    let json = serde_json::to_string_pretty(&results)?;
72
8
    std::fs::write("harvest_output.json", json)?;
73
4
    Ok(())
74
4
}