diff --git a/packages/core/src/config/projectRegistry.test.ts b/packages/core/src/config/projectRegistry.test.ts index 84d266b278..d3201133a6 100644 --- a/packages/core/src/config/projectRegistry.test.ts +++ b/packages/core/src/config/projectRegistry.test.ts @@ -435,4 +435,20 @@ describe('ProjectRegistry', () => { expect(data.projects[normalizePath(projectPath)]).toBe('my-project'); expect(Object.values(data.projects)).not.toContain('../../etc/passwd'); }); + + it('resolves symlinks to the same short ID', async () => { + const registry = new ProjectRegistry(registryPath); + await registry.initialize(); + + const realDir = path.join(tempDir, 'real-project'); + fs.mkdirSync(realDir); + + const symlinkDir = path.join(tempDir, 'symlink-project'); + fs.symlinkSync(realDir, symlinkDir, 'dir'); + + const id1 = await registry.getShortId(realDir); + const id2 = await registry.getShortId(symlinkDir); + + expect(id1).toBe(id2); + }); }); diff --git a/packages/core/src/config/projectRegistry.ts b/packages/core/src/config/projectRegistry.ts index 88c49ac3af..b50ee61cc2 100644 --- a/packages/core/src/config/projectRegistry.ts +++ b/packages/core/src/config/projectRegistry.ts @@ -12,6 +12,7 @@ import { lock } from 'proper-lockfile'; import { z } from 'zod'; import { debugLogger } from '../utils/debugLogger.js'; import { isNodeError } from '../utils/errors.js'; +import { resolveToRealPath } from '../utils/paths.js'; export interface RegistryData { projects: Record; @@ -93,7 +94,7 @@ export class ProjectRegistry { } private normalizePath(projectPath: string): string { - let resolved = path.resolve(projectPath); + let resolved = resolveToRealPath(projectPath); if (os.platform() === 'win32') { resolved = resolved.toLowerCase(); }