use std::path::Path;
use std::process::Command;
pub fn changed_since(repo: &Path, since_commit: &str, paths: &[String]) -> Option<bool> {
if paths.is_empty() {
return Some(false);
}
let mut args: Vec<String> = vec![
"rev-list".into(),
format!("{since_commit}..HEAD"),
"--".into(),
];
args.extend(paths.iter().cloned());
let out = Command::new("git")
.args(&args)
.current_dir(repo)
.output()
.ok()?;
if !out.status.success() {
return None; }
Some(!out.stdout.is_empty())
}
#[cfg(test)]
mod tests {
use super::*;
use std::process::Command;
fn two_commit_repo() -> (std::path::PathBuf, String, String) {
use std::sync::atomic::{AtomicU64, Ordering};
static N: AtomicU64 = AtomicU64::new(0);
let p = std::env::temp_dir().join(format!(
"ev-liveness-{}-{}",
std::process::id(),
N.fetch_add(1, Ordering::Relaxed)
));
let _ = std::fs::remove_dir_all(&p);
std::fs::create_dir_all(&p).unwrap();
let git = |args: &[&str]| {
Command::new("git")
.args(args)
.current_dir(&p)
.output()
.unwrap();
};
git(&["init"]);
git(&["config", "user.email", "t@e.st"]);
git(&["config", "user.name", "Tester"]);
std::fs::write(p.join("readme.md"), "a").unwrap();
git(&["add", "."]);
git(&["commit", "-m", "first"]);
let first = String::from_utf8(
Command::new("git")
.args(["rev-parse", "HEAD"])
.current_dir(&p)
.output()
.unwrap()
.stdout,
)
.unwrap()
.trim()
.to_string();
std::fs::write(p.join("pyproject.toml"), "deps=[]").unwrap();
git(&["add", "."]);
git(&["commit", "-m", "second touches pyproject"]);
let second = String::from_utf8(
Command::new("git")
.args(["rev-parse", "HEAD"])
.current_dir(&p)
.output()
.unwrap()
.stdout,
)
.unwrap()
.trim()
.to_string();
(p, first, second)
}
#[test]
fn changed_since_should_be_true_when_a_triggered_path_changed_after_the_commit() {
let (repo, first, _second) = two_commit_repo();
let r = changed_since(&repo, &first, &["pyproject.toml".into()]);
assert_eq!(r, Some(true));
}
#[test]
fn changed_since_should_be_false_when_no_triggered_path_changed_after_the_commit() {
let (repo, _first, second) = two_commit_repo();
let r = changed_since(&repo, &second, &["pyproject.toml".into()]);
assert_eq!(r, Some(false));
}
#[test]
fn changed_since_should_be_none_when_the_commit_is_unknown() {
let (repo, _first, _second) = two_commit_repo();
let r = changed_since(
&repo,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
&["pyproject.toml".into()],
);
assert_eq!(r, None);
}
}