From 1b137252683ff752aed2ae7b1f4994c16a9b5f63 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Mar 2026 02:04:05 +0000 Subject: [PATCH 1/2] Initial plan From 1a421d8612cda48b4b0a314aad680404af98e682 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Mar 2026 02:16:22 +0000 Subject: [PATCH 2/2] Fix path prefix matching bug in project directory filtering Co-authored-by: ShadowDog007 <3084997+ShadowDog007@users.noreply.github.com> --- src/cli/BaseProjectFilterCommand.ts | 2 +- src/services/RepositoryService.ts | 2 +- test/cli/ListCommand.spec.ts | 21 +++++++++++++++++++++ test/services/RepositoryService.spec.ts | 15 +++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/cli/BaseProjectFilterCommand.ts b/src/cli/BaseProjectFilterCommand.ts index f3738cb..3d6b9f2 100644 --- a/src/cli/BaseProjectFilterCommand.ts +++ b/src/cli/BaseProjectFilterCommand.ts @@ -77,7 +77,7 @@ export abstract class BaseProjectFilterCommand directoryChanges.some(c => c.startsWith(d)))); + || [p.dir, ...p.dependencies].some(d => directoryChanges.some(c => c === d || c.startsWith(d + '/')))); } return projects; } diff --git a/src/services/RepositoryService.ts b/src/services/RepositoryService.ts index 0159729..b314ec1 100644 --- a/src/services/RepositoryService.ts +++ b/src/services/RepositoryService.ts @@ -76,7 +76,7 @@ export class RepositoryServiceImpl implements RepositoryService { const matchingUncommitedChanges = uncommitedChanges .filter(uc => !!paths.find(p => - uc.path.startsWith(p) || p.startsWith(uc.path)) + uc.path === p || uc.path.startsWith(p === '/' ? '/' : p + '/') || p.startsWith(uc.path)) ); if (matchingUncommitedChanges.length) { diff --git a/test/cli/ListCommand.spec.ts b/test/cli/ListCommand.spec.ts index c2d78c4..8baefc3 100644 --- a/test/cli/ListCommand.spec.ts +++ b/test/cli/ListCommand.spec.ts @@ -21,6 +21,7 @@ describe(ListCommand, () => { const project1Dir = 'project1'; const project2Dir = 'project2'; const dependency1Dir = 'dependency1'; + const project1ExtensionsDir = 'project1extensions'; const commits = { initial: { @@ -50,6 +51,13 @@ describe(ListCommand, () => { timestamp: new Date('2023-01-01'), ago: '2 years ago', files: [dependency1Dir], + }, + updateExtensions: { + hash: 'Updated project1extensions dir', + hashShort: 'updtextn', + timestamp: new Date('2023-01-02'), + ago: '2 years ago', + files: [`${project1ExtensionsDir}/file.cs`], } } satisfies Record; @@ -68,6 +76,13 @@ describe(ListCommand, () => { dependencies: [], version: commits.newProject, }; + const project1Extensions: ProjectWithVersion = { + ...projectExamples.project3, + name: 'Project1Extensions', + dir: project1ExtensionsDir, + dependencies: [], + version: commits.updateExtensions, + }; beforeEach(async () => { await resetFs(); @@ -133,6 +148,12 @@ describe(ListCommand, () => { test('when changed in provided, and no project changes, should not list any proejcts', () => testHelper.testParse(['--template', '${{name}}', '--changed-in', commits.unrelated.hash], ['No matching projects'])); + test('when changed in provided, should not match projects with a directory that is a prefix of the changed directory', async () => { + projectService.addProjects(project1Extensions); + repositoryService.addCommitChanges(commits.updateExtensions); + return testHelper.testParse(['--template', '${{name}}', '--changed-in', commits.updateExtensions.hash], ['Project1Extensions']); + }); + test('when changed from provided, should list all project changed since', () => testHelper.testParse(['--template', '${{name}}', '--changed-from', commits.unrelated.hash], ['Project1'])); diff --git a/test/services/RepositoryService.spec.ts b/test/services/RepositoryService.spec.ts index c9f2c3b..9502585 100644 --- a/test/services/RepositoryService.spec.ts +++ b/test/services/RepositoryService.spec.ts @@ -154,6 +154,21 @@ describe(RepositoryServiceImpl, () => { hashShort: PathStatus.Untracked, }); }); + + test('when uncommitted change is in a path with the same prefix but different directory, should use hash', async () => { + // Given + mockSpawnService.addRunOutput(`?? ProjectAExtensions/file.cs`); + mockSpawnService.addRunOutput(`{'hash':'long-hash','hashShort':'short-hash','timestamp':'2024-10-19T00:00:00Z'}`); + + // When + const version = await repositoryService.getLatestPathVersion('/ProjectA'); + + // Verify + expect(version).toMatchObject({ + hash: 'long-hash', + hashShort: 'short-hash', + }); + }); }); describe(RepositoryServiceImpl.prototype.getChanges, () => {