Commit c6e75e3
authored
fix: prevent findDbPath from escaping git worktree boundary (#457)
* fix: prevent findDbPath from escaping git worktree boundary
findDbPath() walks up from cwd looking for .codegraph/graph.db. In a git
worktree (e.g. .claude/worktrees/agent-xxx/), this crosses the worktree
boundary and finds the main repo's database instead.
Add findRepoRoot() using `git rev-parse --show-toplevel` (which returns
the correct root for both repos and worktrees) and use it as a ceiling
in findDbPath(). The walk-up now stops at the git boundary, so each
worktree resolves to its own database.
* fix: address review — real git ceiling test, debug log, robust non-git test
- Ceiling test now uses `git init` to create a real git repo boundary,
and verifies the outer DB is NOT found (without the ceiling fix it
would be). Added separate test for finding DB within the boundary.
- Non-git test uses a fresh mkdtemp dir instead of os.tmpdir().
- Added debug log when ceiling stops the walk-up.
- Removed unused `origFindRepoRoot` variable.
* test: strengthen findRepoRoot and ceiling tests per review feedback
- Mock execFileSync via vi.mock to verify caching calls exactly once
and cache bypass calls twice (not just comparing return values)
- Mock execFileSync to throw in "not in git repo" test so the null
path is always exercised regardless of host environment
- Rename "does not use cache" test to "bypasses cache" with spy assertion
* Revert "test: strengthen findRepoRoot and ceiling tests per review feedback"
This reverts commit 83efde5.
* Reapply "test: strengthen findRepoRoot and ceiling tests per review feedback"
This reverts commit ccb8bd5.
* fix: address Greptile review — flaky non-git test and misleading import name
- Mock execFileSync to throw in "falls back gracefully when not in a git
repo" test, preventing flakiness when os.tmpdir() is inside a git repo
- Rename realExecFileSync → execFileSyncForSetup with comment explaining
it resolves to the spy due to vi.mock hoisting
* fix: resolve symlinks in findDbPath to fix ceiling check on macOS
On macOS, os.tmpdir() returns /var/folders/... but git rev-parse
returns /private/var/folders/... (resolved symlink). The ceiling
comparison failed because the paths didn't match. Use fs.realpathSync
on cwd to normalize symlinks before comparing against the ceiling.
Impact: 1 functions changed, 1 affected
* style: format connection.js try/catch block
Impact: 1 functions changed, 1 affected
* test: harden findDbPath fallback test to mock execFileSync
The 'returns default path when no DB found' test didn't control the git
ceiling — if tmpDir was inside a git repo, findRepoRoot() would return
a non-null ceiling and the default path would differ from emptyDir.
Mock execFileSync to throw so the cwd fallback is always exercised.
* fix: normalize findRepoRoot paths with realpathSync for cross-platform ceiling
On macOS, os.tmpdir() returns /var/... but git resolves symlinks to
/private/var/..., and on Windows, 8.3 short names (RUNNER~1) differ
from long names (runneradmin). findDbPath normalizes dir via
fs.realpathSync but findRepoRoot only used path.resolve, causing the
ceiling comparison to fail — the walk crossed the worktree boundary.
Fix findRepoRoot to use fs.realpathSync on git output, and resolve
test paths after directory creation so assertions match.
Impact: 1 functions changed, 77 affected
* fix: use stat-based path comparison for ceiling check on Windows
git rev-parse resolves 8.3 short names (RUNNER~1 → runneradmin) but
fs.realpathSync may not, causing the string comparison to fail and the
walk to escape the git ceiling boundary. Replace string equality with
isSameDirectory() that falls back to dev+ino comparison when paths
differ textually but refer to the same directory.
Also fix the test assertion to use findRepoRoot() for the expected
ceiling path instead of the test's worktreeRoot, since git may resolve
paths differently than realpathSync.
Impact: 2 functions changed, 137 affected
* fix: remove test-only _resetRepoRootCache from public barrel export
* fix: tighten test assertions and key repo root cache on cwd
Impact: 2 functions changed, 2 affected
* fix: normalize ceiling path in test to handle Windows 8.3 short names
* fix: normalize ceiling path with realpathSync to handle Windows 8.3 short names
Impact: 1 functions changed, 1 affected
* fix: normalize Windows 8.3 short paths in ceiling boundary test
On Windows CI, fs.realpathSync(process.cwd()) and git rev-parse
--show-toplevel can resolve 8.3 short names (RUNNER~1) differently
than long names (runneradmin). Apply realpathSync to both sides of
the assertion so the comparison is path-equivalent.
* fix: use existence-based assertions for ceiling test to handle Windows 8.3 names1 parent 2bd997a commit c6e75e3
3 files changed
Lines changed: 263 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
1 | 2 | | |
2 | 3 | | |
3 | 4 | | |
4 | | - | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
8 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
9 | 59 | | |
10 | 60 | | |
11 | 61 | | |
| |||
46 | 96 | | |
47 | 97 | | |
48 | 98 | | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
49 | 115 | | |
50 | 116 | | |
51 | 117 | | |
| |||
64 | 130 | | |
65 | 131 | | |
66 | 132 | | |
67 | | - | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
68 | 155 | | |
69 | 156 | | |
70 | 157 | | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
71 | 162 | | |
72 | 163 | | |
73 | 164 | | |
74 | 165 | | |
75 | | - | |
| 166 | + | |
| 167 | + | |
76 | 168 | | |
77 | 169 | | |
78 | 170 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
3 | 10 | | |
4 | 11 | | |
5 | 12 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
5 | 8 | | |
6 | 9 | | |
7 | 10 | | |
8 | 11 | | |
9 | | - | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
10 | 23 | | |
11 | 24 | | |
12 | 25 | | |
| 26 | + | |
13 | 27 | | |
14 | 28 | | |
15 | 29 | | |
| |||
131 | 145 | | |
132 | 146 | | |
133 | 147 | | |
| 148 | + | |
134 | 149 | | |
135 | 150 | | |
136 | 151 | | |
137 | 152 | | |
138 | 153 | | |
| 154 | + | |
139 | 155 | | |
140 | 156 | | |
141 | 157 | | |
142 | 158 | | |
143 | 159 | | |
144 | 160 | | |
145 | 161 | | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
146 | 166 | | |
147 | 167 | | |
148 | | - | |
149 | | - | |
| 168 | + | |
150 | 169 | | |
151 | 170 | | |
| 171 | + | |
152 | 172 | | |
153 | 173 | | |
154 | 174 | | |
| |||
194 | 214 | | |
195 | 215 | | |
196 | 216 | | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
197 | 354 | | |
198 | 355 | | |
199 | 356 | | |
| |||
0 commit comments