77import { simpleGit , SimpleGit } from 'simple-git' ;
88import * as path from 'node:path' ;
99import { ResourceDescriptor } from '../models/types.js' ;
10- import { parseArtifactPath } from '../lib/resource-path.js' ;
10+ import { parseArtifactChangePath } from '../lib/resource-path.js' ;
1111import { logger } from '../lib/logger.js' ;
1212
1313export interface GitDiffResult {
@@ -61,7 +61,7 @@ export async function computeGitDiff(
6161 // Get diff between parent and current commit
6262 // If no parent, diff against empty tree (shows all files as added)
6363 const diffTarget = hasParent ? parentCommit : '4b825dc642cb6eb9a060e54bf8d69288fbee4904' ; // Git empty tree SHA
64- const diffOutput = await git . diff ( [ '--name-status' , diffTarget , commitId ] ) ;
64+ const diffOutput = await git . diff ( [ '--name-status' , '--relative' , diffTarget , commitId ] ) ;
6565
6666 return parseDiffOutput ( diffOutput , sourceDir ) ;
6767 } catch ( error ) {
@@ -105,12 +105,7 @@ function parseDiffOutput(diffOutput: string, sourceDir: string): GitDiffResult {
105105 continue ;
106106 }
107107
108- // Convert relative path to absolute for parsing
109- const absolutePath = path . isAbsolute ( filePath )
110- ? filePath
111- : path . join ( sourceDir , filePath ) ;
112-
113- const descriptor = parseArtifactPath ( sourceDir , absolutePath ) ;
108+ const descriptor = parseDescriptorFromDiffPath ( sourceDir , filePath ) ;
114109 if ( ! descriptor ) {
115110 continue ;
116111 }
@@ -119,30 +114,16 @@ function parseDiffOutput(diffOutput: string, sourceDir: string): GitDiffResult {
119114 const key = descriptorKey ( descriptor ) ;
120115
121116 if ( status === 'D' ) {
122- // Deleted file
123- if ( ! seenDeleted . has ( key ) ) {
124- deletedDescriptors . push ( descriptor ) ;
125- seenDeleted . add ( key ) ;
126- }
117+ addUniqueDescriptor ( deletedDescriptors , seenDeleted , descriptor , key ) ;
127118 } else if ( status === 'M' || status === 'A' || status === 'R' || status === 'C' ) {
128- // Modified, added, renamed, or copied file
129- if ( ! seenChanged . has ( key ) ) {
130- changedDescriptors . push ( descriptor ) ;
131- seenChanged . add ( key ) ;
132- }
119+ addUniqueDescriptor ( changedDescriptors , seenChanged , descriptor , key ) ;
133120
134121 // For renames, also parse the new path (in parts[2])
135- if ( status === 'R' && parts [ 2 ] ) {
136- const newPath = path . isAbsolute ( parts [ 2 ] )
137- ? parts [ 2 ]
138- : path . join ( sourceDir , parts [ 2 ] ) ;
139- const newDescriptor = parseArtifactPath ( sourceDir , newPath ) ;
122+ if ( status === 'R' && parts . length > 2 && parts [ 2 ] ) {
123+ const newDescriptor = parseDescriptorFromDiffPath ( sourceDir , parts [ 2 ] ) ;
140124 if ( newDescriptor ) {
141125 const newKey = descriptorKey ( newDescriptor ) ;
142- if ( ! seenChanged . has ( newKey ) ) {
143- changedDescriptors . push ( newDescriptor ) ;
144- seenChanged . add ( newKey ) ;
145- }
126+ addUniqueDescriptor ( changedDescriptors , seenChanged , newDescriptor , newKey ) ;
146127 }
147128 }
148129 }
@@ -161,3 +142,28 @@ function parseDiffOutput(diffOutput: string, sourceDir: string): GitDiffResult {
161142function descriptorKey ( descriptor : ResourceDescriptor ) : string {
162143 return [ descriptor . type , ...descriptor . nameParts , descriptor . workspace ?? '' ] . join ( '::' ) ;
163144}
145+
146+ function addUniqueDescriptor (
147+ target : ResourceDescriptor [ ] ,
148+ seen : Set < string > ,
149+ descriptor : ResourceDescriptor ,
150+ key : string
151+ ) : void {
152+ if ( seen . has ( key ) ) {
153+ return ;
154+ }
155+
156+ target . push ( descriptor ) ;
157+ seen . add ( key ) ;
158+ }
159+
160+ function parseDescriptorFromDiffPath (
161+ sourceDir : string ,
162+ diffPath : string
163+ ) : ResourceDescriptor | undefined {
164+ const absolutePath = path . isAbsolute ( diffPath )
165+ ? diffPath
166+ : path . join ( sourceDir , diffPath ) ;
167+
168+ return parseArtifactChangePath ( sourceDir , absolutePath ) ;
169+ }
0 commit comments