use super::*;
fn git(dir: &Path, args: &[&str]) {
let output = crate::git_backend::git_command()
.arg("-C")
.arg(dir)
.args(["-c", "user.name=Test", "-c", "user.email=test@example.com", "-c", "protocol.file.allow=always"])
.args(args)
.output()
.expect("git runs");
assert!(output.status.success(), "git {args:?}: {}", String::from_utf8_lossy(&output.stderr));
}
fn write(dir: &Path, rel: &str, text: &str) {
let p = dir.join(rel);
std::fs::create_dir_all(p.parent().expect("a parent")).expect("mkdir");
std::fs::write(p, text).expect("a file");
}
fn fleet() -> (tempfile::TempDir, PathBuf) {
let scratch = tempfile::tempdir().expect("a scratch directory");
let base = crate::platform::canonicalize(scratch.path()).expect("resolves");
let lib = base.join("lib-origin");
std::fs::create_dir_all(&lib).expect("mkdir");
git(&lib, &["init", "--quiet", "-b", "main"]);
write(&lib, "Cargo.toml", "[package]\nname = \"lib\"\n");
write(&lib, "src/lib.rs", "pub fn f() {}\n");
git(&lib, &["add", "-A"]);
git(&lib, &["commit", "--quiet", "-m", "lib"]);
let top = base.join("top");
std::fs::create_dir_all(&top).expect("mkdir");
git(&top, &["init", "--quiet", "-b", "main"]);
write(&top, ".gitignore", "target/\n");
write(&top, "wsb/Cargo.toml", "[workspace]\nmembers = [\"daemon\"]\n");
write(&top, "wsb/src/lib.rs", "pub fn g() {}\n");
write(&top, "wsb/daemon/Cargo.toml", "[package]\nname = \"daemon\"\n");
write(&top, "wsb/daemon/src/main.rs", "fn main() {}\n");
write(&top, "docs/tool.py", "def tool():\n pass\n");
write(&top, "target/stray/Cargo.toml", "[package]\nname = \"stray\"\n");
git(&top, &["add", "-A"]);
git(&top, &["submodule", "--quiet", "add", lib.to_str().expect("utf-8"), "lib"]);
git(&top, &["commit", "--quiet", "-m", "top"]);
write(&top, "scratch/Cargo.toml", "[package]\nname = \"scratch\"\n");
let exclude = top.join(".git/info/exclude");
let mut excluded = std::fs::read_to_string(&exclude).unwrap_or_default();
excluded.push_str("scratch/\n");
std::fs::write(&exclude, excluded).expect("an exclude");
(scratch, top)
}
#[test]
fn test20080_files_are_analyzed_at_their_repository_or_cargo_workspace() {
let (_scratch, top) = fleet();
let fleet = Fleet::discover(&top).expect("the fleet");
assert_eq!(fleet.repositories(), [top.clone(), top.join("lib")]);
let root = |rel: &str| fleet.analysis_root(&top.join(rel)).expect("a root");
assert_eq!(root("wsb/src/lib.rs"), AnalysisRoot { dir: top.join("wsb"), exclude: vec![] });
assert_eq!(
root("wsb/daemon/src/main.rs"),
AnalysisRoot { dir: top.join("wsb"), exclude: vec![] },
"a crate inside a Cargo workspace is that workspace's"
);
assert_eq!(
root("docs/tool.py"),
AnalysisRoot { dir: top.clone(), exclude: vec!["wsb/**".to_owned()] },
"the repository's own analysis leaves out its Cargo workspace, and nothing ignored"
);
assert_eq!(root("lib/src/lib.rs"), AnalysisRoot { dir: top.join("lib"), exclude: vec![] });
let mut all = vec![
AnalysisRoot { dir: top.clone(), exclude: vec!["wsb/**".to_owned()] },
AnalysisRoot { dir: top.join("lib"), exclude: vec![] },
AnalysisRoot { dir: top.join("wsb"), exclude: vec![] },
];
all.sort();
assert_eq!(fleet.analysis_roots(None).expect("the roots"), all);
assert_eq!(
fleet.analysis_roots(Some(&top.join("lib"))).expect("one repository's roots"),
vec![AnalysisRoot { dir: top.join("lib"), exclude: vec![] }]
);
}