use crate::error::git_error::ConfigStatusCheckError;
use crate::util::colored_print::print_warning;
use std::process::Command;
fn run_git(args: &[&str]) -> Result<String, ConfigStatusCheckError> {
let output = Command::new("git")
.args(args)
.output()
.map_err(|e| ConfigStatusCheckError::GitError(e.to_string()))?;
Ok(String::from_utf8_lossy(&output.stdout).to_string())
}
fn get_git_status(path: &str) -> Result<(char, char), ConfigStatusCheckError> {
let out = run_git(&["status", "--porcelain"])?;
for line in out.lines() {
if line.len() < 3 {
continue;
}
let x = line
.chars()
.next()
.ok_or_else(|| ConfigStatusCheckError::InvalidGitStatusOutput(line.to_string()))?;
let y = line
.chars()
.nth(1)
.ok_or_else(|| ConfigStatusCheckError::InvalidGitStatusOutput(line.to_string()))?;
let file = &line[3..];
if file == path {
return Ok((x, y));
}
}
Ok((' ', ' ')) }
pub fn check_config_status(config: &str) -> Result<(), ConfigStatusCheckError> {
if !std::path::Path::new(config).exists() {
return Err(ConfigStatusCheckError::ConfigNotExist(config.to_string()));
}
let (x, y) = get_git_status(config)?;
if x == '?' && y == '?' {
print_warning(&format!(
"warning: configuration file '{}' exists but is not tracked by git. \
It is recommended to add it to version control.",
config
));
return Ok(());
}
if y == 'M' {
return Err(ConfigStatusCheckError::ConfigNotCommitted {
file: config.to_string(),
});
}
Ok(())
}
#[cfg(test)]
mod tests {
use crate::constant::COMMIT_MSG_RULE_FILE_NAME;
use crate::validator::git_status::check_config_status;
#[test]
fn test_check_config_status() {
let file = COMMIT_MSG_RULE_FILE_NAME;
println!("{:?}", check_config_status(file));
}
}