use std::path::Path; use std::process::{Command, ExitStatus}; use std::io::Result; trait HadSuccess { fn success(self) -> bool; } impl HadSuccess for Result { fn success(self) -> bool { self.map_or(false, |status| status.success()) } } impl HadSuccess for &mut Command { fn success(self) -> bool { self.status().success() } } macro_rules! git { () => { Command::new("git").current_dir(Path::new("repo")) }; ([], $arg:expr) => { git!().arg($arg) }; ([], $arg:expr, $($args:expr),+) => { git!([], $($args),+).arg($arg) }; ([$first:expr $(, $rest:expr)*], $($reversed:expr),*) => { git!([$($rest),*], $first $(, $reversed)*) }; ($($args:expr),+) => { git!([$($args),+],) }; } fn check_or_set_config(key: &str, value: &str) -> bool { if let Ok(status) = git!("config", "--local", "--get", key).status() { if status.success() { true } else if status.code().unwrap_or(2) == 1 { git!("config", "--local", key, value).success() } else { false } } else { false } } fn check_config() -> bool { check_or_set_config("user.name", "Mutzi") && check_or_set_config("user.email", "root@mattv.de") } fn clone_repo() -> bool { println!("Cloning repo..."); if !Path::new("repo").exists() { std::fs::create_dir("repo").unwrap(); } git!("clone", "gitea@gitea.mattv.de:root/dotfiles.git", ".").success() && check_config() } pub fn pull_repo() { println!("Pulling repo..."); git!("pull").success(); } pub fn push_repo() -> bool { println!("Pushing repo..."); git!("push").success() } pub fn open_repo() -> bool { Path::new("repo/.git").exists() || clone_repo() } pub fn is_clean() -> bool { if let Ok(output) = git!("status", "--porcelain").output() { if output.status.success() { output.stdout.is_empty() } else { println!("Failed to get status:\n{}", String::from_utf8(output.stderr).unwrap()); false } } else { println!("Failed to get status"); false } } pub fn commit_changes(msg: &str) -> bool { git!("add", ".").success() && git!("commit", "-m", msg).success() } pub fn diff() { git!("diff").success(); }