Fix handling of absolute patterns in parent gitignore files.

If a gitignore file in a *parent* directory is used, then it must be
matched relative to the directory it's in. ripgrep wasn't actually
adhering to this rule. Consider an example:

  .gitignore
  src
    llvm
      foo

Where `.gitignore` contains `/llvm/` and `foo` contains `test`. When
running `rg test` at the top-level directory, `foo` is correctly searched.
If you `cd` into `src` and re-run the same search, `foo` is ignored because
the `/llvm/` pattern is interpreted with respect to the current working
directory, which is wrong. The problem is that the path of `llvm` is
`./llvm`, which makes it look like it should match.

We fix this by rebuilding the directory path of each file when traversing
gitignores in parent directories. This does come with a small performance
hit.

Fixes #25.
This commit is contained in:
Andrew Gallant
2016-09-24 18:40:50 -04:00
parent 56fe93d343
commit 346bad7dfc
2 changed files with 66 additions and 19 deletions

View File

@@ -609,6 +609,22 @@ clean!(regression_16, "xyz", ".", |wd: WorkDir, mut cmd: Command| {
wd.assert_err(&mut cmd);
});
// See: https://github.com/BurntSushi/ripgrep/issues/25
clean!(regression_25, "test", ".", |wd: WorkDir, mut cmd: Command| {
wd.create(".gitignore", "/llvm/");
wd.create_dir("src/llvm");
wd.create("src/llvm/foo", "test");
let lines: String = wd.stdout(&mut cmd);
let expected = "src/llvm/foo:test\n";
assert_eq!(lines, expected);
cmd.current_dir(wd.path().join("src"));
let lines: String = wd.stdout(&mut cmd);
let expected = "llvm/foo:test\n";
assert_eq!(lines, expected);
});
// See: https://github.com/BurntSushi/ripgrep/issues/49
clean!(regression_49, "xyz", ".", |wd: WorkDir, mut cmd: Command| {
wd.create(".gitignore", "foo/bar");