diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fe2cbe..075b997 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,8 @@ Bug fixes: Preserve line terminators when using `-r/--replace` flag. * [BUG #3108](https://github.com/BurntSushi/ripgrep/issues/3108): Fix a bug where `-q --files-without-match` inverted the exit code. +* [BUG #3131](https://github.com/BurntSushi/ripgrep/issues/3131): + Document inconsistency between `-c/--count` and `--files-with-matches`. * [BUG #3140](https://github.com/BurntSushi/ripgrep/issues/3140): Ensure hyphens in flag names are escaped in the roff text for the man page. * [BUG #3155](https://github.com/BurntSushi/ripgrep/issues/3155): diff --git a/crates/core/flags/defs.rs b/crates/core/flags/defs.rs index c5a7fad..e9b05df 100644 --- a/crates/core/flags/defs.rs +++ b/crates/core/flags/defs.rs @@ -1276,6 +1276,14 @@ is a match. The \flag{with-filename} flag can be used to force printing the file path in this case. If you need a count to be printed regardless of whether there is a match, then use \flag{include-zero}. .sp +Note that it is possible for this flag to have results inconsistent with +the output of \flag{files-with-matches}. Notably, by default, ripgrep tries +to avoid searching files with binary data. With this flag, ripgrep needs to +search the entire content of files, which may include binary data. But with +\flag{files-with-matches}, ripgrep can stop as soon as a match is observed, +which may come well before any binary data. To avoid this inconsistency without +disabling binary detection, use the \flag{binary} flag. +.sp This overrides the \flag{count-matches} flag. Note that when \flag{count} is combined with \flag{only-matching}, then ripgrep behaves as if \flag{count-matches} was given. @@ -2184,6 +2192,14 @@ impl Flag for FilesWithMatches { r" Print only the paths with at least one match and suppress match contents. .sp +Note that it is possible for this flag to have results inconsistent with the +output of \flag{count}. Notably, by default, ripgrep tries to avoid searching +files with binary data. With this flag, ripgrep might stop searching before +the binary data is observed. But with \flag{count}, ripgrep has to search the +entire contents to determine the match count, which means it might see binary +data that causes it to skip searching that file. To avoid this inconsistency +without disabling binary detection, use the \flag{binary} flag. +.sp This overrides \flag{files-without-match}. " } diff --git a/tests/binary.rs b/tests/binary.rs index fd145ce..73639c1 100644 --- a/tests/binary.rs +++ b/tests/binary.rs @@ -429,3 +429,40 @@ hay:1867:\"And yet you say he is not a medical student?\" "; eqnice!(expected, cmd.stdout()); }); + +// See: https://github.com/BurntSushi/ripgrep/issues/3131 +rgtest!( + matching_files_inconsistent_with_count, + |dir: Dir, _cmd: TestCommand| { + let mut file1 = String::new(); + file1.push_str("cat here\n"); + for _ in 0..150_000 { + file1.push_str("padding line\n"); + } + file1.push_str("\x00"); + + dir.create("file1.txt", &file1); + dir.create("file2.txt", "cat here"); + + let got = dir.command().args(&["--sort=path", "-l", "cat"]).stdout(); + eqnice!("file1.txt\nfile2.txt\n", got); + + // This is the inconsistent result that can't really be avoided without + // either making `-l/--files-with-matches` much slower or changing + // what "binary filtering" means. + let got = dir.command().args(&["--sort=path", "-c", "cat"]).stdout(); + eqnice!("file2.txt:1\n", got); + + let got = dir + .command() + .args(&["--sort=path", "-c", "cat", "--binary"]) + .stdout(); + eqnice!("file1.txt:1\nfile2.txt:1\n", got); + + let got = dir + .command() + .args(&["--sort=path", "-c", "cat", "--text"]) + .stdout(); + eqnice!("file1.txt:1\nfile2.txt:1\n", got); + } +); diff --git a/tests/regression.rs b/tests/regression.rs index b3d7fb1..8dd1ba7 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -1545,6 +1545,7 @@ rgtest!( } ); +// See: https://github.com/BurntSushi/ripgrep/issues/3139 rgtest!( r3139_multiline_lookahead_files_with_matches, |dir: Dir, _cmd: TestCommand| {