use std::fs;
use crate::diff::changed_since;
use super::support::{GitRepo, run_in};
#[tokio::test]
async fn three_dot_does_not_include_base_changes_added_after_the_fork() {
let repo = GitRepo::init().await;
let root = repo.root();
fs::write(root.join("seed.rs"), "common\n").expect("write");
run_in(root, &["add", "."]).await;
repo.commit_all("seed").await;
repo.create_branch("feature").await;
repo.checkout("feature").await;
fs::write(root.join("on_branch.rs"), "").expect("write");
run_in(root, &["add", "on_branch.rs"]).await;
repo.commit_all("feature change").await;
repo.checkout("main").await;
fs::write(root.join("new_on_main.rs"), "").expect("write");
run_in(root, &["add", "new_on_main.rs"]).await;
repo.commit_all("main change after fork").await;
repo.checkout("feature").await;
let changed = changed_since(root, "main").await.expect("changed_since");
let names: Vec<String> = changed
.iter()
.map(|p| p.to_string_lossy().into_owned())
.collect();
assert!(
names.iter().any(|n| n == "on_branch.rs"),
"the feature-branch change should appear: {names:?}"
);
assert!(
!names.iter().any(|n| n == "new_on_main.rs"),
"a file added to main AFTER the fork must NOT appear in feature's diff: {names:?}"
);
}
#[tokio::test]
async fn returns_an_error_when_the_ref_does_not_exist() {
let repo = GitRepo::init().await;
let root = repo.root();
let err = changed_since(root, "does/not/exist")
.await
.expect_err("non-existent ref must error");
let display = err.to_string();
assert!(
display.contains("git") || display.contains("exit"),
"expected a git error, got {display:?}"
);
}
#[tokio::test]
async fn three_dot_excludes_base_modifications_that_two_dot_would_report() {
let repo = GitRepo::init().await;
let root = repo.root();
fs::write(root.join("shared.rs"), "v1\n").expect("write");
run_in(root, &["add", "."]).await;
repo.commit_all("seed").await;
repo.create_branch("feature").await;
repo.checkout("feature").await;
fs::write(root.join("on_branch.rs"), "").expect("write");
run_in(root, &["add", "on_branch.rs"]).await;
repo.commit_all("feature change").await;
repo.checkout("main").await;
fs::write(root.join("shared.rs"), "v2\n").expect("write");
run_in(root, &["add", "shared.rs"]).await;
repo.commit_all("base modifies a shared file after the fork")
.await;
repo.checkout("feature").await;
let changed = changed_since(root, "main").await.expect("changed_since");
let names: Vec<String> = changed
.iter()
.map(|p| p.to_string_lossy().into_owned())
.collect();
assert!(
names.iter().any(|n| n.ends_with("on_branch.rs")),
"the branch's own change must be reported, got {names:?}"
);
assert!(
!names.iter().any(|n| n.ends_with("shared.rs")),
"shared.rs was modified on the base, not by this branch - a two-dot \
diff reports it as M and the ACMR filter keeps it. got {names:?}"
);
}