rasslib/
vcs.rs

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
use std::process::{Command,ExitStatus};
use std::io;
use std::result;

#[derive(Debug)]
pub struct GitWrapper {
    repo: String,
    sign: bool,
}

pub type Result<T> = result::Result<T, io::Error>;

/// Version control trait. Note that `add` and `remove` will not commit the 
/// operation. Hence `commit` has to be called separatly.
pub trait VersionControl {
    fn add(&self, file: &str) -> Result<ExitStatus>; 
    fn remove(&self, file: &str) -> Result<ExitStatus>;
    fn commit(&self, message: &str) -> Result<ExitStatus>;
    fn cmd_dispatch(&self, args: Vec<&str>) -> Result<ExitStatus>;
}

impl GitWrapper {
    pub fn new(repo_path: &str) -> GitWrapper {
        let repo_path = String::from(repo_path);
        let output = Command::new("git")
                        .arg("config")
                        .arg("--bool")
                        .arg("--get")
                        .arg("pass.signcommits")
                        .current_dir(&repo_path)
                        .output();

        let sign = match output {
            Ok(output) => {
                match String::from_utf8_lossy(&output.stdout).trim() {
                    "true" | "True" | "TRUE" => true,
                    _ => false
                }
            },
            Err(_) => false
        };

        GitWrapper {
            repo: repo_path,
            sign: sign,
        }
    }
}


impl VersionControl for GitWrapper {
    fn add(&self, file: &str) -> Result<ExitStatus> {
        Command::new("git")
            .arg("add")
            .arg(file)
            .current_dir(&self.repo)
            .status()
    }

    fn commit(&self, message: &str) -> Result<ExitStatus> {
        let mut cmd = Command::new("git");
        cmd.arg("commit")
           .arg("-m")
           .arg(message)
           .current_dir(&self.repo);
        if self.sign {
            cmd.arg("-S");
        }
        cmd.status()
    }

    fn remove(&self, file: &str) -> Result<ExitStatus> {
        let mut cmd = Command::new("git");
        cmd.arg("rm")
           .arg("-qr")
           .arg(file)
           .current_dir(&self.repo);
        cmd.status()
    }

    fn cmd_dispatch(&self, args: Vec<&str>) -> Result<ExitStatus> {
        let mut cmd = Command::new("git");
        cmd.args(args.as_slice())
           .current_dir(&self.repo);
        cmd.status()
    }
}