ok/jj
1
0
Fork 0
forked from mirrors/jj

gitignore: don't apply patterns to parent directories

If you create a `dir/.gitignore` file with pattern "dir" in it, it'll
currently match the parent directory, making e.g. the `dir/.gitignore`
file itself ignored. That was quite confusing, and it doesn't match
how Git behaves. This patch fixes the bug.
This commit is contained in:
Martin von Zweigbergk 2022-01-12 11:01:14 -08:00
parent 5b84e192fc
commit 8a0afc3016

View file

@ -83,11 +83,10 @@ impl GitIgnoreLine {
is_rooted |= input.contains('/'); is_rooted |= input.contains('/');
let mut regex = String::new(); let mut regex = String::new();
if is_rooted { regex.push('^');
regex.insert_str(0, prefix); regex.push_str(prefix);
regex.insert(0, '^'); if !is_rooted {
} else { regex.push_str("(.*/)?");
regex.insert_str(0, "(^|/)");
} }
let components = input.split('/').collect_vec(); let components = input.split('/').collect_vec();
@ -271,11 +270,19 @@ mod tests {
let file = GitIgnoreFile::empty().chain("dir/", b"foo\n").ok().unwrap(); let file = GitIgnoreFile::empty().chain("dir/", b"foo\n").ok().unwrap();
// I consider it undefined whether a file in a parent directory matches, but // I consider it undefined whether a file in a parent directory matches, but
// let's test it anyway // let's test it anyway
assert!(file.matches_file("foo")); assert!(!file.matches_file("foo"));
assert!(file.matches_file("dir/foo")); assert!(file.matches_file("dir/foo"));
assert!(file.matches_file("dir/subdir/foo")); assert!(file.matches_file("dir/subdir/foo"));
} }
#[test]
fn test_gitignore_pattern_same_as_prefix() {
let file = GitIgnoreFile::empty().chain("dir/", b"dir\n").ok().unwrap();
assert!(file.matches_file("dir/dir"));
// We don't want the "dir" pattern to apply to the parent directory
assert!(!file.matches_file("dir/foo"));
}
#[test] #[test]
fn test_gitignore_rooted_literal() { fn test_gitignore_rooted_literal() {
let file = GitIgnoreFile::empty().chain("", b"/foo\n").ok().unwrap(); let file = GitIgnoreFile::empty().chain("", b"/foo\n").ok().unwrap();