fix(watcher): realpath-resolve git dirs before subscribing#1126
Conversation
The VCS watcher resolved each `git rev-parse --git-dir/--git-common-dir` path with `path.resolve` only. When `.git` is a symlink (a symlinked git dir, or a worktree reached through a symlinked path such as macOS `/tmp` -> `/private/tmp`), parcel emits events at the canonical realpath, so `shouldPublishVcsWatcherPath` runs `path.relative(symlinkPath, realPath)`, gets a `..` traversal, and drops every HEAD/ref event — branch detection never fires. realpath()-resolve each git dir before subscribing and filtering, with a `.catch` fallback to the unresolved path when realpath fails (dir may be absent). The cfg `watcher.ignore` check now matches either the resolved or the realpath'd dir, and a `subscribedVcsDirs` set preserves the existing single-subscription dedupe across the new realpath step. The test harness `ready()` probe is now symlink-aware (a real `.git` dir resolves to itself, so existing cases are unchanged), and a new symlinked-`.git` regression test asserts HEAD events still publish. Re-implements the fix from upstream anomalyco/opencode #27016 (1ac3f09468), adapted to PawWork's dual git-dir/git-common-dir subscription loop. Thanks to the upstream authors.
|
Warning Review limit reached
More reviews will be available in 16 minutes and 55 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Code Review
This pull request updates the file watcher to canonicalize potentially symlinked VCS directories (such as .git) using realpath. This ensures that file events emitted by Parcel at their real paths are correctly captured instead of being dropped. The test suite is updated to handle symlinked .git directories, and a new test is added to verify this behavior. Feedback on the test suggests using a second tmpdir() with await using to avoid polluting the parent directory and to simplify cleanup by removing the manual try-finally block.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Address Codex review: the native symlinked-.git integration test runs only under the native watcher suite (CI skips it), so a regression of this fix could merge unnoticed. Extract the git-dir resolution (resolve + realpath + watcher.ignore + dedupe) into a pure, exported resolveVcsWatchDirs() and add a CI-runnable unit test that exercises a real symlinked dir, the ignore semantics, and the realpath-failure fallback — no native binding required. Also shrinks the layer's inline subscription loop.
Address gemini-code-assist review: move the symlinked-.git target into a second `await using tmpdir()` instead of writing it to the parent of the repo tmpdir. Auto-cleans the target (no manual try/finally) and avoids parent-directory writes that could fail in sandboxed environments.
Summary
realpath()-resolve each git metadata directory before the VCS file watcher subscribes to and filters its events.
Why
The VCS watcher resolves each
git rev-parse --git-dir/--git-common-dirpath withpath.resolveonly (file/watcher.ts). When.gitis a symlink — a symlinked git dir, or a worktree reached through a symlinked path such as macOS/tmp→/private/tmp—git rev-parsestill reports.git, so we subscribe to the symlink path. parcel emits events at the canonical realpath, soshouldPublishVcsWatcherPathrunspath.relative(symlinkPath, realPath), gets a..traversal, and drops every HEAD/ref event. Branch detection then never fires for those repos.Fix: realpath-resolve each git dir before subscribing/filtering, with a
.catchfallback to the unresolved path when realpath fails (the dir may be absent). Thewatcher.ignoreconfig check now matches either the resolved or the realpath'd dir, and asubscribedVcsDirsset preserves the existing single-subscription dedupe across the new realpath step.Re-implements upstream
anomalyco/opencode#27016 (1ac3f09468), adapted to PawWork's dual git-dir / git-common-dir subscription loop (which diverged from upstream's single-dir shape). Thanks to the upstream authors (Kagura, Simon Klee).Related Issue
No tracked issue; surfaced via the upstream value-mining ledger. Related to previously shelved watcher work (#1016 → #1115).
Human Review Status
Pending
Review Focus
.catch(() => resolvedVcsDir)fallback, and that thecfgIgnorescheck still honors a user-configured.gitignore by either path.subscribedVcsDirsdedupe: two resolved paths can canonicalize to one realpath; we subscribe once.ready()is now symlink-aware. A real.gitdir resolves to itself, so all existing watcher cases are unchanged (verified: 20/20 pass).Risk Notes
Low. Behavior changes only when a git dir is symlinked: previously dropped HEAD/ref events now publish. realpath failure falls back to prior behavior. No signature changes. The new regression test is skipped on Windows (symlink creation needs privileges), matching upstream.
How To Verify
Screenshots or Recordings
N/A — no UI change.
Checklist
bug,enhancement,task,documentation.app,ui,platform,harness,ci.P0,P1,P2,P3.Pending,Approved by @<reviewer>, orNot required: <reason>.