fix: checkpoint nested-repo detection handles .git files and avoids symlink follow #11344
+179
−72
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Related GitHub Issue
Closes: #11340
Description
This PR attempts to address Issue #11340. Feedback and guidance are welcome.
Replaces the ripgrep-based
getNestedGitRepository()with a recursivefs.readdir-based directory walk (findNestedGitEntry()) that fixes three correctness issues:False negatives (submodule/worktree .git files): The old approach searched only for
**/.git/HEAD, which misses submodules and worktrees that use a.gitfile (containinggitdir: ...) instead of a.gitdirectory. The new approach checks for any.gitentry -- directory or file.False positives via symlink follow: The old approach used ripgrep's
--followflag which traversed symlinks outside the workspace boundary. The new approach usesfs.readdirwithwithFileTypes(lstat semantics), so symbolic links are never followed.Brittle path matching: The old approach relied on
includes(".git/HEAD")andstartsWith(".git/")string matching. The new approach uses theDirent.nameproperty to check for.gitentries directly, and usesisRootflag to skip the root-level.git.Key design decisions:
.gitdirectories andnode_modulesduring traversal for performanceexecuteRipgrepdependency from the checkpoint serviceTest Procedure
.gitpointer file detection: Creates a directory with a.gitfile containinggitdir: ...(simulating a submodule) and verifies it is detected as a nested repo.gitrepo, and verifies the symlink is not followedRun tests with:
Pre-Submission Checklist
Documentation Updates
Additional Notes
The new implementation walks the directory tree using Node's built-in
fs.readdirwith{ withFileTypes: true }. This usesreaddir(3)which returnsDT_LNKfor symlinks, soDirent.isSymbolicLink()correctly identifies them without following. This makes the implementation both simpler and more correct than the previous ripgrep-based approach.Important
Replaces ripgrep-based nested git detection with a recursive directory walk in
ShadowCheckpointService.ts, improving accuracy and handling submodules, worktrees, and symlinks correctly.getNestedGitRepository()withfindNestedGitEntry()inShadowCheckpointService.tsto detect.gitdirectories and files, handling submodules and worktrees.fs.readdirwithwithFileTypes..gitdirectories andnode_modulesfor performance..gitfile detection, symlink non-traversal, and stray.gitfile handling inShadowCheckpointService.spec.ts..gitfiles and correct behavior with symlinks.executeRipgrepdependency fromShadowCheckpointService.ts.This description was created by
for c042beb. You can customize this summary. It will automatically update as commits are pushed.