diff --git a/gitnexus/src/storage/storage-resolver.ts b/gitnexus/src/storage/storage-resolver.ts index a34c19306..031d8b909 100644 --- a/gitnexus/src/storage/storage-resolver.ts +++ b/gitnexus/src/storage/storage-resolver.ts @@ -9,7 +9,7 @@ import { LEGACY_METADATA_FILE, LBUG_DIRECTORY, } from './storage-constants.js'; -import { resolveSharedStore } from './shared-store.js'; +import { resolveGraphPath, resolveSharedStore } from './shared-store.js'; import { slotNameForCanonicalPath, STORAGE_PATH_ENV, STORAGE_ROOT_ENV } from './storage-slot.js'; export { STORAGE_PATH_ENV, STORAGE_ROOT_ENV }; @@ -387,8 +387,13 @@ const inspectCodeIndexDB = async ( if (lbugRel.startsWith('..') || path.isAbsolute(lbugRel)) { return { present: false }; } + // A shared-store checkout slot (#3352) may read a commit graph instead of + // owning one; `resolveGraphPath` only returns a path inside the same store's + // commit graphs, else the slot's own graph. + const graphPath = resolveGraphPath(resolved); + const target = graphPath === lbugPath ? lbugPath : graphPath; try { - await fsp.access(lbugPath); + await fsp.access(target); return { present: true }; } catch (error) { const code = (error as NodeJS.ErrnoException)?.code; diff --git a/gitnexus/test/integration/shared-store-analyze.test.ts b/gitnexus/test/integration/shared-store-analyze.test.ts index 862e667c7..844505bf4 100644 --- a/gitnexus/test/integration/shared-store-analyze.test.ts +++ b/gitnexus/test/integration/shared-store-analyze.test.ts @@ -107,6 +107,20 @@ describe('shared sibling store analyze (#3352)', () => { } }, 180_000); + it('reports a checkout that reads a commit graph as indexed', async () => { + const { runFullAnalysis } = await import('../../src/core/run-analyze.js'); + await runFullAnalysis(wtA, {}, { onProgress: () => {} }); + await runFullAnalysis(wtB, {}, { onProgress: () => {} }); + const slot = layoutOf(wtB).checkoutSlot; + expect(existsSync(path.join(slot, 'lbug'))).toBe(false); + + const { inspectRegisteredStorage } = await import('../../src/storage/storage-resolver.js'); + const inspection = await inspectRegisteredStorage({ path: wtB, storagePath: slot }); + expect(inspection).toMatchObject({ state: 'owned', hasCodeIndexDB: true }); + const validated = await listRegisteredRepos({ validate: true }); + expect(validated.map((e) => e.path)).toEqual(expect.arrayContaining([wtA, wtB])); + }, 180_000); + it('serves a sibling the same relative file paths from the shared graph', async () => { const { runFullAnalysis } = await import('../../src/core/run-analyze.js'); await runFullAnalysis(wtA, {}, { onProgress: () => {} });