summaryrefslogtreecommitdiffstats
path: root/src/main.rs
blob: 20fd5ea699cc4e9c71291520e6b85f5f2c370e02 (plain)
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#[macro_use]
extern crate clap;

#[macro_use]
extern crate slog;

use clap::ArgAction;
use clap_complete::{generate, Shell};
use slog::Drain;
use std::io;

fn main() {
    let args = command!()
        .about("Automatically absorb staged changes into your current branch")
        .arg(
            clap::Arg::new("base")
                .help("Use this commit as the base of the absorb stack")
                .short('b')
                .long("base"),
        )
        .arg(
            clap::Arg::new("dry-run")
                .help("Don't make any actual changes")
                .short('n')
                .long("dry-run")
                .action(ArgAction::SetTrue),
        )
        .arg(
            clap::Arg::new("force")
                .help("Skip safety checks")
                .short('f')
                .long("force")
                .action(ArgAction::SetTrue),
        )
        .arg(
            clap::Arg::new("verbose")
                .help("Display more output")
                .short('v')
                .long("verbose")
                .action(ArgAction::SetTrue),
        )
        .arg(
            clap::Arg::new("and-rebase")
                .help("Run rebase if successful")
                .short('r')
                .long("and-rebase")
                .action(ArgAction::SetTrue),
        )
        .arg(
            clap::Arg::new("gen-completions")
                .help("Generate completions")
                .long("gen-completions")
                .value_parser(["bash", "fish", "zsh", "powershell", "elvish"]),
        )
        .arg(
            clap::Arg::new("whole-file")
                .help("Match the change against the complete file   ")
                .short('w')
                .long("whole-file")
                .action(ArgAction::SetTrue),
        )
        .arg(
            clap::Arg::new("one-fixup-per-commit")
                .help("Only generate one fixup per commit")
                .short('F')
                .long("one-fixup-per-commit")
                .action(ArgAction::SetTrue),
        );
    let mut args_clone = args.clone();
    let args = args.get_matches();

    if let Some(shell) = args.get_one::<String>("gen-completions") {
        let app_name = "git-absorb";
        match shell.as_str() {
            "bash" => {
                generate(Shell::Bash, &mut args_clone, app_name, &mut io::stdout());
            }
            "fish" => {
                generate(Shell::Fish, &mut args_clone, app_name, &mut io::stdout());
            }
            "zsh" => {
                generate(Shell::Zsh, &mut args_clone, app_name, &mut io::stdout());
            }
            "powershell" => {
                generate(
                    Shell::PowerShell,
                    &mut args_clone,
                    app_name,
                    &mut io::stdout(),
                );
            }
            "elvish" => {
                generate(Shell::Elvish, &mut args_clone, app_name, &mut io::stdout());
            }
            _ => unreachable!(),
        }
        return;
    }

    let decorator = slog_term::TermDecorator::new().build();
    let drain = slog_term::FullFormat::new(decorator).build().fuse();
    let drain = slog_async::Async::new(drain).build().fuse();
    let drain = slog::LevelFilter::new(
        drain,
        if args.get_flag("verbose") {
            slog::Level::Debug
        } else {
            slog::Level::Info
        },
    )
    .fuse();
    let mut logger = slog::Logger::root(drain, o!());
    if args.get_flag("verbose") {
        logger = logger.new(o!(
            "module" => slog::FnValue(|record| record.module()),
            "line" => slog::FnValue(|record| record.line()),
        ));
    }

    if let Err(e) = git_absorb::run(&mut git_absorb::Config {
        dry_run: args.get_flag("dry-run"),
        force: args.get_flag("force"),
        base: args.get_one::<String>("base").map(|s| s.as_str()),
        and_rebase: args.get_flag("and-rebase"),
        whole_file: args.get_flag("whole-file"),
        one_fixup_per_commit: args.get_flag("one-fixup-per-commit"),
        logger: &logger,
    }) {
        crit!(logger, "absorb failed"; "err" => e.to_string());
        // wait for async logger to finish writing messages
        drop(logger);
        ::std::process::exit(1);
    }
}