Skip to content

fix: watcher honours walker ignore rules in ripgrep builds (#915) - #916

Open
gustav-fff wants to merge 1 commit into
mainfrom
triage-bot/issue-915
Open

gustav-fff wants to merge 1 commit into
mainfrom
triage-bot/issue-915

Conversation

@gustav-fff

@gustav-fff gustav-fff commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #915

Root cause

Ripgrep walker returns ignore_rules: None (crates/fff-core/src/walk/ripgrep.rs:85, ripgrep WalkIgnoreRules was uninhabited in walk/mod.rs:31). So IgnoreFilter::is_ignored (crates/fff-core/src/watcher/background_watcher.rs:957) falls back to libgit2 is_path_ignored, which does not read .ignore files (local or parent dirs). Watcher and walker classify paths differently. zlob builds unaffected.

Fix

Ripgrep walker moves its WalkBuilder into WalkIgnoreRules. On first watcher query it builds ignore::IncrementalIgnore (WalkBuilder::build_matchers), ripgrep's own single-path matcher with walk-identical precedence. IgnoreFilter::is_ignored now takes is_dir so dir-only patterns match; zlob path ignores it, behaviour unchanged.

@dmtrKovalenko two things to look at:

  • ignore bumped 0.4.22 -> 0.4.33 (first with build_matchers). Lock: ignore 0.4.25->0.4.33, regex-automata 0.4.14->0.4.18.
  • Non-git roots on ripgrep builds: watcher now applies walker rules (hidden filter, non_git_repo_overrides, .ignore) instead of the is_non_code_directory substring heuristic. Same as walker, but it is a behaviour change.

Matcher is behind a parking_lot::Mutex (matched needs &mut for its per-dir cache). Held for one matched call, never nested with the picker lock.

Steps to reproduce

On origin/main (d978416), default features (ripgrep). Append the two tests from #915 (dot_ignore_negation_keeps_gitignored_dir_live, dot_ignore_exclusion_is_kept_by_watcher, now in crates/fff-core/src/watcher/rescan_tests.rs on this branch) to the same file on main, then:

cargo test -p fff-search --lib dot_ignore

Expected: 2 passed. Actual on main:

test watch::rescan_tests::dot_ignore_negation_keeps_gitignored_dir_live ... FAILED
test watch::rescan_tests::dot_ignore_exclusion_is_kept_by_watcher ... FAILED
watcher must index it like the walker
watcher must skip it like the walker

Real watcher (macOS FSEvents) setup: .gitignore=projects/, .ignore=!projects/\nscratch/, projects/a/.gitignore=target/, watch: true. After scan, create projects/a/src/added.rs, append to projects/a/src/main.rs, create root_added.rs. Grep after 5s on main:

[("ADDED_MARKER", 0), ("EDIT_MARKER", 0), ("ROOT_MARKER", 1)]

Expected: all 1, while projects/a/target/new.o and scratch/new.txt stay out.

How verified

  • cargo test -p fff-search --lib: 218 passed (ripgrep), incl. 2 new tests. surfaces_reusable_ignore_rules now runs on both backends.
  • make test-rust (zlob, CI config): all passed.
  • cargo test --workspace --exclude fff-nvim --exclude fff-python (ripgrep): all passed.
  • cargo clippy --workspace --no-default-features --features zlob -- -D warnings and cargo clippy -p fff-search -p fff-c -- -D warnings: clean.
  • Real-watcher e2e above (throwaway test, not committed): main fails as shown, branch passes in ~2.6s, nested target/ and scratch/ stay out.
  • Perf, 5000 tracked Chromium paths: libgit2 open + is_path_ignored 3.06s; IncrementalIgnore cold 260ms, warm 5.4ms. Initial scan pays nothing (matcher built lazily); index_new_directory walks do not build it at all.
  • 10 of those 5000 paths showed the same bug: node_modules/ from a parent-dir .ignore above the Chromium root. The walker skips them, libgit2 said not ignored, the new matcher agrees with the walker.

Automated triage via Gustav. Honk-Honk 🪿

Summary by CodeRabbit

  • Bug Fixes
    • Ignore rules are now applied more consistently when files and directories are checked, including during filesystem watcher updates and indexing of newly created directories.
    • Nested exclusions and .ignore negation rules are better respected, helping prevent excluded files from being indexed while allowing explicitly unignored directories to remain active.

Ripgrep builds returned no walker ignore rules, so the watcher fell back
to libgit2 is_path_ignored, which knows nothing about .ignore files
(local or in parent dirs). Live updates drifted from what a rescan
produces: creates/edits under a .ignore re-included dir were dropped,
and files under a .ignore excluded dir got indexed.

The ripgrep walker now hands its WalkBuilder to WalkIgnoreRules, which
lazily builds ignore::IncrementalIgnore from it on first watcher query.
Same config, same precedence as the walk. Requires ignore >= 0.4.33.

Closes #915

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b9024ddd-4702-4e92-9aae-bb301ff651c4
📥 Commits

Reviewing files that changed from the base of the PR and between d978416 and b42cd07.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • Cargo.toml
  • crates/fff-core/src/walk/mod.rs
  • crates/fff-core/src/walk/ripgrep.rs
  • crates/fff-core/src/watcher/background_watcher.rs
  • crates/fff-core/src/watcher/rescan_tests.rs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

The ripgrep walker now provides reusable ignore rules to the background watcher. The watcher passes each path’s directory status when applying those rules. Tests cover .ignore negation and exclusion.

Changes: Watcher ignore-rule consistency

Layer / File(s) Summary
Build reusable ripgrep ignore rules
Cargo.toml, crates/fff-core/src/walk/mod.rs, crates/fff-core/src/walk/ripgrep.rs
The ignore dependency moves to version 0.4.33. WalkIgnoreRules stores the ripgrep builder and lazily initializes a matcher. The ripgrep walker returns these rules in WalkOutput.
Apply rules in the watcher
crates/fff-core/src/watcher/background_watcher.rs, crates/fff-core/src/watcher/rescan_tests.rs
The watcher passes file or directory status to ignore checks. Regression tests cover .ignore negation and exclusion, including nested .gitignore rules.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Suggested reviewers: dmtrkovalenko

Fixed issue severity: <fixed_issue_severity>Medium</fixed_issue_severity>

Merge Risk: ⚪ Minimal · up to b42cd

The watcher ignore-rule change is mergeable after normal checks. No actionable failure was established.

Pre-merge checks · Passed 4 · Failed 1

Failed Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 4 files. (1 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks (4 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: making the watcher honor walker ignore rules in ripgrep builds.
Linked Issues check Passed The changes satisfy #915. Ripgrep now preserves the walk builder in WalkIgnoreRules and lazily creates ignore::IncrementalIgnore. The watcher passes directory status to matcher queries. The new te…
Out of Scope Changes check Passed The changes stay within #915. The ignore dependency update supports build_matchers. The watcher changes, backend handling, and regression tests directly implement walker-consistent ignore behavior…
Full details: Docstring Coverage

Explanation

Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 4 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: [fff-core watcher] With default ripgrep feature, live updates ignore .ignore files the initial walk honours

1 participant