git-utils: block selected patch filters

This commit is contained in:
Chris Bookholt
2026-07-01 10:21:29 -07:00
parent c21e78bbd6
commit 0b84913ea8
5 changed files with 735 additions and 0 deletions
+108
View File
@@ -0,0 +1,108 @@
use super::*;
use crate::git_config::GitConfigScope;
use pretty_assertions::assert_eq;
use std::collections::BTreeMap;
use std::path::Path;
#[test]
fn selected_filter_policy_allows_unused_and_rejects_selected_at_every_scope() {
let config_dir = tempfile::tempdir().expect("config");
let config = config_dir.path().join("global.gitconfig");
std::fs::write(&config, "").expect("config file");
for scope in [
GitConfigScope::System,
GitConfigScope::Global,
GitConfigScope::Local,
GitConfigScope::Worktree,
GitConfigScope::Command,
] {
for (key, value) in [
("filter.demo.clean", "./clean.sh"),
("filter.lfs.clean", "git-lfs clean -- %f"),
("filter.lfs.smudge", "git-lfs smudge -- %f"),
("filter.lfs.process", "git-lfs filter-process"),
] {
let entries = filter_entries(scope, &config, key, value);
let driver = filter_driver_name(key).expect("driver name");
let selected = BTreeMap::from([(b"file.txt".to_vec(), driver.clone())]);
assert!(
selected_executable_filter(&entries, &selected)
.expect("selected filter policy")
.is_some(),
"{scope:?} {key}"
);
let unused = BTreeMap::from([(b"file.txt".to_vec(), "other".to_string())]);
assert_eq!(
selected_executable_filter(&entries, &unused).expect("unused filter policy"),
None,
"{scope:?} {key}"
);
}
}
}
#[test]
fn selected_filter_policy_allows_effective_empty_value() {
let disabled = filter_entries(
GitConfigScope::Command,
Path::new("command line:"),
"filter.demo.clean",
"",
);
let selected = BTreeMap::from([(b"file.txt".to_vec(), "demo".to_string())]);
assert_eq!(
selected_executable_filter(&disabled, &selected).expect("empty filter policy"),
None
);
}
#[test]
fn filter_attribute_parser_rejects_malformed_or_unexpected_records() {
let paths = vec![b"a.txt".to_vec(), b"b.txt".to_vec()];
let parsed =
parse_filter_attributes(b"a.txt\0filter\0unspecified\0b.txt\0filter\0lfs\0", &paths)
.expect("parse attributes");
assert_eq!(
parsed.get(b"a.txt".as_slice()).map(String::as_str),
Some("unspecified")
);
assert_eq!(
parsed.get(b"b.txt".as_slice()).map(String::as_str),
Some("lfs")
);
for output in [
b"a.txt\0filter\0unspecified".as_slice(),
b"a.txt\0merge\0unspecified\0b.txt\0filter\0lfs\0".as_slice(),
b"a.txt\0filter\0unspecified\0".as_slice(),
b"a.txt\0filter\0unspecified\0a.txt\0filter\0lfs\0".as_slice(),
] {
assert!(
parse_filter_attributes(output, &paths).is_err(),
"{output:?}"
);
}
}
fn filter_entries(
scope: GitConfigScope,
origin: &Path,
key: &str,
value: &str,
) -> BTreeMap<String, GitConfigEntry> {
let origin = if origin == Path::new("command line:") {
"command line:".to_string()
} else {
format!("file:{}", origin.display())
};
BTreeMap::from([(
key.to_string(),
GitConfigEntry {
scope,
origin,
key: key.to_string(),
value: value.to_string(),
},
)])
}