Please tick this box to confirm you have reviewed the above.
What version of ripgrep are you using?
14.1.1
How did you install ripgrep?
Cargo
What operating system are you using ripgrep on?
macOS 26.5
Describe your bug.
ignore::WalkBuilder appears to produce nondeterministic results for a parallel multi-root walk when one root has a scoped ignore rule that should not apply to another root.
What are the steps to reproduce the behavior?
Minimal layout:
.git/
.gitignore
noxfile.py
src/scikit_build_core/build/metadata.py
tests/test_metadata.py
.gitignore:
The source build file should always be included: the ignore rule only matches build/ directories below tests/.
Minimal Rust repro with ignore = "0.4.25":
use std::path::Path;
use std::sync::atomic::{AtomicBool, Ordering};
fn source_build_file_was_seen(root: &Path) -> bool {
let source_build_file = root.join("src/scikit_build_core/build/metadata.py");
let seen = AtomicBool::new(false);
let mut builder = ignore::WalkBuilder::new(root.join("src"));
builder.current_dir(root);
builder.standard_filters(true);
builder.add(root.join("tests"));
builder.add(root.join("noxfile.py"));
builder.threads(12);
builder.build_parallel().run(|| {
Box::new(|entry| {
if let Ok(entry) = entry {
if entry.path() == source_build_file {
seen.store(true, Ordering::Relaxed);
}
}
ignore::WalkState::Continue
})
});
seen.load(Ordering::Relaxed)
}
fn main() {
let root = Path::new(env!("CARGO_MANIFEST_DIR"));
let mut seen = 0;
let mut missing = 0;
for _ in 0..100 {
if source_build_file_was_seen(root) {
seen += 1;
} else {
missing += 1;
}
}
println!("seen={seen} missing={missing}");
}
Observed output on my machine:
The same issue reproduces via ripgrep:
rg --threads 12 --files src tests noxfile.py
Across 100 identical runs, src/scikit_build_core/build/metadata.py was present 59 times and missing 41 times.
Control cases were stable:
rg --threads 1 --files src tests noxfile.py
# source file present 100/100
rg --threads 12 --files src
# source file present 100/100
So this looks specific to the parallel multi-root walk. The expected behavior is that tests/**/build/ never excludes src/scikit_build_core/build/metadata.py, regardless of walk scheduling.
This is causing nondeterminism in ty too: it makes it so some files in the scikit-build-core project are sometimes checked and sometimes ignored by ty. The repro case in this issue is a simplified version of the shape in scikit_build_core.
What is the actual behavior?
Inconsistent output from rg --threads 12 --files src tests noxfile.py.
What is the expected behavior?
Rules should be applied consistently
Please tick this box to confirm you have reviewed the above.
What version of ripgrep are you using?
14.1.1
How did you install ripgrep?
Cargo
What operating system are you using ripgrep on?
macOS 26.5
Describe your bug.
ignore::WalkBuilderappears to produce nondeterministic results for a parallel multi-root walk when one root has a scoped ignore rule that should not apply to another root.What are the steps to reproduce the behavior?
Minimal layout:
.gitignore:The source build file should always be included: the ignore rule only matches
build/directories belowtests/.Minimal Rust repro with
ignore = "0.4.25":Observed output on my machine:
The same issue reproduces via ripgrep:
Across 100 identical runs,
src/scikit_build_core/build/metadata.pywas present 59 times and missing 41 times.Control cases were stable:
So this looks specific to the parallel multi-root walk. The expected behavior is that
tests/**/build/never excludessrc/scikit_build_core/build/metadata.py, regardless of walk scheduling.This is causing nondeterminism in ty too: it makes it so some files in the scikit-build-core project are sometimes checked and sometimes ignored by ty. The repro case in this issue is a simplified version of the shape in scikit_build_core.
What is the actual behavior?
Inconsistent output from
rg --threads 12 --files src tests noxfile.py.What is the expected behavior?
Rules should be applied consistently