use super::list_files;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
fn unique_tmp(label: &str) -> PathBuf {
let dir = std::env::temp_dir().join(format!(
"fs-walk-test-{}-{}",
label,
std::process::id()
));
let _ = fs::remove_dir_all(&dir);
fs::create_dir_all(&dir).expect("create tmp dir");
dir
}
fn run_git(dir: &PathBuf, args: &[&str]) {
let git_bin = if std::path::Path::new("/usr/bin/git").exists() {
"/usr/bin/git"
} else {
"git"
};
let status = Command::new(git_bin)
.args(args)
.current_dir(dir)
.status()
.expect("git command failed to spawn");
assert!(
status.success(),
"git {:?} failed in {:?}",
args,
dir
);
}
#[test]
fn list_files_includes_force_added_gitignored_file() {
let dir = unique_tmp("bug3-tracked-ignored");
run_git(&dir, &["init", "-q"]);
run_git(&dir, &["config", "user.email", "t@t"]);
run_git(&dir, &["config", "user.name", "t"]);
fs::write(dir.join(".gitignore"), "*.ignored\n").expect("write .gitignore");
fs::write(dir.join("tracked.ignored"), "secret content")
.expect("write tracked.ignored");
fs::write(dir.join("normal.txt"), "normal content").expect("write normal.txt");
run_git(&dir, &["add", "-f", ".gitignore", "tracked.ignored", "normal.txt"]);
run_git(
&dir,
&["commit", "-q", "-m", "initial", ".gitignore", "tracked.ignored", "normal.txt"],
);
let files = list_files(dir.to_str().expect("dir utf8")).expect("list_files");
let basenames: Vec<String> = files
.iter()
.filter_map(|p| {
std::path::Path::new(p)
.file_name()
.and_then(|n| n.to_str())
.map(|s| s.to_string())
})
.collect();
assert!(
basenames.iter().any(|b| b == "normal.txt"),
"normal tracked file must be listed; got {:?}",
basenames
);
assert!(
basenames.iter().any(|b| b == "tracked.ignored"),
"BUG 3: force-added gitignored file must be listed; got {:?}",
basenames
);
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn list_files_excludes_submodule_gitlink_entries() {
let dir = unique_tmp("gix-mode-filter");
run_git(&dir, &["init", "-q"]);
run_git(&dir, &["config", "user.email", "t@t"]);
run_git(&dir, &["config", "user.name", "t"]);
fs::write(dir.join("real.txt"), "ordinary").expect("write real.txt");
run_git(&dir, &["add", "-f", "real.txt"]);
run_git(
&dir,
&[
"update-index",
"--add",
"--cacheinfo",
"160000,0000000000000000000000000000000000000001,vendor/sub",
],
);
run_git(
&dir,
&["commit", "-q", "-m", "initial", "real.txt"],
);
let files = list_files(dir.to_str().expect("dir utf8")).expect("list_files");
let normalized: Vec<String> = files
.iter()
.map(|p| p.trim_start_matches("./").to_string())
.collect();
assert!(
normalized.iter().any(|p| p.ends_with("real.txt")),
"regular tracked file must still be listed; got {:?}",
normalized
);
assert!(
!normalized.iter().any(|p| p.ends_with("vendor/sub")),
"submodule gitlink (Mode::COMMIT) must NOT be listed; got {:?}",
normalized
);
let _ = fs::remove_dir_all(&dir);
}
fn write_config(dir: &Path, contents: &str) {
let git_dir = dir.join(".git");
fs::create_dir_all(&git_dir).expect("create .git");
fs::write(git_dir.join("config"), contents).expect("write .git/config");
}
#[test]
fn detect_sha256_in_standard_config_shape() {
let dir = unique_tmp("detect-sha256-standard");
write_config(
&dir,
"[extensions]\n\tobjectformat = sha256\n[core]\n\tbare = false\n",
);
assert_eq!(super::detect_index_hash_kind(&dir), gix_hash::Kind::Sha256);
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn detect_sha1_when_extensions_absent() {
let dir = unique_tmp("detect-sha1-default");
write_config(&dir, "[core]\n\tbare = false\n[user]\n\temail = t@t\n");
assert_eq!(super::detect_index_hash_kind(&dir), gix_hash::Kind::Sha1);
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn detect_sha1_when_config_missing() {
let dir = unique_tmp("detect-sha1-noconfig");
assert_eq!(super::detect_index_hash_kind(&dir), gix_hash::Kind::Sha1);
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn detect_sha256_with_comments_and_irregular_whitespace() {
let dir = unique_tmp("detect-sha256-comments");
write_config(
&dir,
"# comment line\n[Extensions]\n ObjectFormat= sha256 ; trailing\n[core]\n",
);
assert_eq!(super::detect_index_hash_kind(&dir), gix_hash::Kind::Sha256);
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn detect_sha1_when_objectformat_is_outside_extensions_section() {
let dir = unique_tmp("detect-sha1-wrong-section");
write_config(
&dir,
"[core]\n\tobjectformat = sha256\n",
);
assert_eq!(super::detect_index_hash_kind(&dir), gix_hash::Kind::Sha1);
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn detect_sha256_with_extensions_subsection() {
let dir = unique_tmp("detect-sha256-subsection");
write_config(
&dir,
"[extensions \"weird\"]\n\tobjectformat = sha256\n",
);
assert_eq!(super::detect_index_hash_kind(&dir), gix_hash::Kind::Sha256);
let _ = fs::remove_dir_all(&dir);
}
#[test]
fn list_files_handles_sha256_repo_force_added_gitignored() {
let dir = unique_tmp("sha256-force-added");
run_git(&dir, &["init", "--object-format=sha256", "-q"]);
run_git(&dir, &["config", "user.email", "t@t"]);
run_git(&dir, &["config", "user.name", "t"]);
fs::write(dir.join(".gitignore"), "*.ignored\n").expect("write .gitignore");
fs::write(dir.join("tracked.ignored"), "secret content")
.expect("write tracked.ignored");
fs::write(dir.join("normal.txt"), "normal content").expect("write normal.txt");
run_git(&dir, &["add", "-f", ".gitignore", "tracked.ignored", "normal.txt"]);
run_git(
&dir,
&["commit", "-q", "-m", "initial", ".gitignore", "tracked.ignored", "normal.txt"],
);
let files = list_files(dir.to_str().expect("dir utf8")).expect("list_files");
let basenames: Vec<String> = files
.iter()
.filter_map(|p| {
std::path::Path::new(p)
.file_name()
.and_then(|n| n.to_str())
.map(|s| s.to_string())
})
.collect();
assert!(
basenames.iter().any(|b| b == "normal.txt"),
"sha256 repo: normal tracked file must be listed; got {:?}",
basenames
);
assert!(
basenames.iter().any(|b| b == "tracked.ignored"),
"sha256 repo: force-added gitignored file must be listed via \
gix-index path; got {:?}",
basenames
);
let _ = fs::remove_dir_all(&dir);
}