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
use std::process::Command;
use std::convert::AsRef;
use std::ffi::OsStr;

pub struct Update {
    cmd: Command,
}

pub fn update() -> Update {
    let mut update = Update { cmd: Command::new("git") };
    update.arg("submodule").arg("update");
    update
}

impl Update {
    fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Update {
        self.cmd.arg(arg);
        self
    }

    pub fn init(&mut self) -> &mut Update { self.arg("--init") }
    pub fn rebase(&mut self) -> &mut Update { self.arg("--rebase") }
    pub fn merge(&mut self) -> &mut Update { self.arg("--merge") }
    pub fn checkout(&mut self) -> &mut Update { self.arg("--checkout") }
    pub fn remote(&mut self) -> &mut Update { self.arg("--remote") }
    pub fn no_fetch(&mut self) -> &mut Update { self.arg("--no-fetch") }
    pub fn recursive(&mut self) -> &mut Update { self.arg("--recursive") }
    pub fn force(&mut self) -> &mut Update { self.arg("--force") }

    pub fn run(&mut self) { 
        println!("running: {:?}", self.cmd);
        let status = match self.cmd.status() {
            Ok(status) => status,
            Err(e) => fail(&format!("failed to execute command: {}", e)),
        };

        if !status.success() {
            fail(&format!("command did not execute successfully, got: {}", status));
        }
    }
}

fn fail(msg: &str) -> ! {
    println!("\n\n{}\n\n", msg);
    panic!()
}

#[test]
fn build_update() {
    let mut update = update();
    update.init()
        .recursive();

    assert_eq!(format!("{:?}", update.cmd),
        "\"git\" \"submodule\" \"update\" \"--init\" \"--recursive\"")
}