Skip to content

Commit a9cd175

Browse files
authored
fix(db): stop findDbPath walk at cwd when no git ceiling (#1193)
When findRepoRoot() returns null, the walk used to climb to /, which could silently attach to a stale .codegraph/ in an unrelated parent — e.g. /private/tmp/.codegraph/ leaking into every /tmp/foo/ run, or $HOME/.codegraph/ leaking into every scratch dir under $HOME (the "Phase 0 footgun" from the v3.10.1-dev.80 dogfood report, §10.6). Outside a git repo, cwd is now the first (and only) directory we'll check. Users running codegraph in non-git project subdirectories must either cd to the project root, git init, or pass -d/--db.
1 parent af0fb4d commit a9cd175

2 files changed

Lines changed: 35 additions & 0 deletions

File tree

src/db/connection.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,14 @@ export function findDbPath(customPath?: string): string {
292292
debug(`findDbPath: stopped at git ceiling ${ceiling}`);
293293
break;
294294
}
295+
// Outside a git repo, cwd is the first (and only) directory we'll check.
296+
// Walking past it risks attaching to a stale .codegraph/ in an unrelated
297+
// parent — e.g. /private/tmp/.codegraph/ leaking into every /tmp/foo/ run,
298+
// or $HOME/.codegraph/ leaking into every scratch dir under $HOME.
299+
if (!ceiling) {
300+
debug(`findDbPath: no git ceiling, stopping at ${dir}`);
301+
break;
302+
}
295303
const parent = path.dirname(dir);
296304
if (parent === dir) break;
297305
dir = parent;

tests/unit/db.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,33 @@ describe('findDbPath with git ceiling', () => {
350350
fs.rmSync(emptyDir, { recursive: true, force: true });
351351
}
352352
});
353+
354+
it('does not pick up stale parent .codegraph/ when no git repo exists', () => {
355+
// Regression for the Phase 0 footgun (dogfood report 10.6): when no git
356+
// repo wraps cwd, findDbPath used to walk all the way to `/`, latching
357+
// onto stale .codegraph/ from unrelated parents (e.g. /private/tmp/).
358+
const parentDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-stale-parent-'));
359+
fs.mkdirSync(path.join(parentDir, '.codegraph'), { recursive: true });
360+
fs.writeFileSync(path.join(parentDir, '.codegraph', 'graph.db'), '');
361+
const innerDir = path.join(parentDir, 'inner');
362+
fs.mkdirSync(innerDir, { recursive: true });
363+
const origCwd = process.cwd;
364+
process.cwd = () => innerDir;
365+
_resetRepoRootCache();
366+
execFileSyncSpy.mockImplementationOnce(() => {
367+
throw new Error('not a git repo');
368+
});
369+
try {
370+
const result = findDbPath();
371+
// Must NOT return the stale parent's DB.
372+
expect(result).not.toBe(path.join(parentDir, '.codegraph', 'graph.db'));
373+
// Falls back to the default path at cwd.
374+
expect(result).toBe(path.join(innerDir, '.codegraph', 'graph.db'));
375+
} finally {
376+
process.cwd = origCwd;
377+
fs.rmSync(parentDir, { recursive: true, force: true });
378+
}
379+
});
353380
});
354381

355382
describe('openReadonlyOrFail', () => {

0 commit comments

Comments
 (0)