Skip to content

fix(watcher): resolve symlinked .git path before subscribing#27016

Merged
simonklee merged 3 commits into
anomalyco:devfrom
kagura-agent:fix/git-symlink-watcher
May 15, 2026
Merged

fix(watcher): resolve symlinked .git path before subscribing#27016
simonklee merged 3 commits into
anomalyco:devfrom
kagura-agent:fix/git-symlink-watcher

Conversation

@kagura-agent

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #26981

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

When .git is a symlink (common with Android's repo tool), the file watcher fails because inotify_add_watch receives the symlink node rather than the underlying directory. inotify rejects this with "Not a directory".

The fix resolves the .git path with realpath before passing it to @parcel/watcher, so inotify always receives the real directory path. Falls back to the original path if realpath fails (e.g. dangling symlink).

How did you verify your code works?

Reproduced the issue by creating a project with a symlinked .git:

mkdir -p /tmp/test/real-git && cd /tmp/test/real-git
git init && echo hi > README.md && git add . && git commit -m init
mkdir /tmp/test/project && cd /tmp/test/project
ln -s ../real-git/.git .git

Confirmed @parcel/watcher (inotify backend) fails on the symlink path and succeeds on the resolved path:

symlink path: FAIL — inotify_add_watch "Not a directory"
realpath:     OK — subscribes successfully

Also ran bun test test/file/ test/config/ — 242 pass, 0 new failures.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes Linux/inotify failures when .git is a symlink by resolving the git directory to its real (dereferenced) path before subscribing the file watcher, preventing inotify_add_watch from receiving a symlink node.

Changes:

  • Resolve the git dir returned by git rev-parse --git-dir with fs.promises.realpath() before watcher subscription.
  • Fall back to the unresolved path when realpath() fails (e.g., dangling symlink).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/opencode/src/file/watcher.ts Outdated
Comment thread packages/opencode/src/file/watcher.ts
@simonklee

Copy link
Copy Markdown
Member

@kagura-agent both issues identified should be addressed

kagura-agent added a commit to kagura-agent/opencode that referenced this pull request May 12, 2026
…d symlink test

Address review feedback on PR anomalyco#27016:
- Check both pre-realpath (resolved) and post-realpath (vcsDir) against
  cfgIgnores so user configs referencing the symlink path still work.
- Add regression test for symlinked .git directory verifying HEAD change
  events propagate through the resolved real path.
@kagura-agent

Copy link
Copy Markdown
Contributor Author

@simonklee Both issues addressed in commit 7f7f4ad:

  1. Ignore path mismatch: The condition now checks both the original path (resolved) and the realpath (vcsDir) against cfgIgnores, so user configs that reference the symlink path still work correctly.

  2. Symlink regression test: Added a test that creates a real .git directory, moves it to a sibling location, replaces it with a symlink, then verifies the watcher correctly resolves through the symlink and publishes .git/HEAD events from the actual directory. Test is skipped on Windows (no symlink support) and in CI (no native @parcel/watcher binding).

inotify_add_watch fails with 'Not a directory' when the .git path is a
symlink (common with Android's repo tool). Resolve the path with
realpath before passing it to @parcel/watcher so the inotify backend
receives the real directory path.

Fixes anomalyco#26981
…d symlink test

Address review feedback on PR anomalyco#27016:
- Check both pre-realpath (resolved) and post-realpath (vcsDir) against
  cfgIgnores so user configs referencing the symlink path still work.
- Add regression test for symlinked .git directory verifying HEAD change
  events propagate through the resolved real path.
@kagura-agent kagura-agent force-pushed the fix/git-symlink-watcher branch from 8af2709 to a4598bd Compare May 13, 2026 18:16
@kagura-agent

Copy link
Copy Markdown
Contributor Author

Rebased on latest dev to resolve merge conflict. Adapted symlink test to the new it.instance/TestInstance/AppFileSystem test infrastructure.

@simonklee simonklee merged commit 1ac3f09 into anomalyco:dev May 15, 2026
8 checks passed
rustybret pushed a commit to rustybret/opencode that referenced this pull request May 15, 2026
AIALRA-0 pushed a commit to AIALRA-0/opencode-turn-engine that referenced this pull request Jun 10, 2026
AIALRA-0 pushed a commit to AIALRA-0/opencode-turn-engine that referenced this pull request Jun 10, 2026
avion23 pushed a commit to avion23/opencode that referenced this pull request Jun 10, 2026
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.

OpenCode TUI hangs (blank terminal) when .git is a symlink (repo tool / Android repo)

3 participants