@@ -12,6 +12,10 @@ const diffRegex = /diff --git a\/(.*) b\/(.*)/;
1212const diffRangeRegex = / ^ @ @ - ( \d + ?) , ( \d + ?) \+ ( \d + ?) , ( \d + ?) @ @ / ;
1313
1414export const fileStatusRegex = / ( \S ) \S * \t ( [ ^ \t \n ] + ) (?: \t ( .+ ) ) ? / ;
15+ const fileStatusAndSummaryRegex = / ^ ( \d + ?| - ) \s + ?( \d + ?| - ) \s + ?( .* ) (?: \n \s ( d e l e t e | r e n a m e | c r e a t e ) ) ? / ;
16+ const fileStatusAndSummaryRenamedFileRegex = / ( .+ ) \s = > \s ( .+ ) / ;
17+ const fileStatusAndSummaryRenamedFilePathRegex = / ( .* ?) { ( .+ ?) \s = > \s ( .+ ?) } ( .* ) / ;
18+
1519const logFileSimpleRegex = / ^ < r > ( .* ) \s * (?: (?: d i f f - - g i t a \/ ( .* ) b \/ ( .* ) ) | (?: ( \S ) \S * \t ( [ ^ \t \n ] + ) (?: \t ( .+ ) ) ? ) ) / gm;
1620const logFileSimpleRenamedRegex = / ^ < r > ( \S + ) \s * ( .* ) $ / s;
1721const logFileSimpleRenamedFilesRegex = / ^ ( \S ) \S * \t ( [ ^ \t \n ] + ) (?: \t ( .+ ) ? ) $ / gm;
@@ -37,6 +41,10 @@ interface LogEntry {
3741 files ?: GitFile [ ] ;
3842
3943 status ?: GitFileStatus ;
44+ fileStats ?: {
45+ insertions : number ;
46+ deletions : number ;
47+ } ;
4048
4149 summary ?: string ;
4250
@@ -99,6 +107,7 @@ export class GitLogParser {
99107
100108 let match ;
101109 let renamedFileName ;
110+ let renamedMatch ;
102111
103112 while ( true ) {
104113 next = lines . next ( ) ;
@@ -242,18 +251,64 @@ export class GitLogParser {
242251 break ;
243252 }
244253 else {
245- match = fileStatusRegex . exec ( line ) ;
254+ next = lines . next ( ) ;
255+ match = fileStatusAndSummaryRegex . exec ( `${ line } \n${ next . value } ` ) ;
246256 if ( match != null ) {
247- entry . status = match [ 1 ] as GitFileStatus ;
248- renamedFileName = match [ 3 ] ;
249- if ( renamedFileName !== undefined ) {
250- entry . fileName = renamedFileName ;
251- entry . originalFileName = match [ 2 ] ;
252- }
253- else {
254- entry . fileName = match [ 2 ] ;
257+ entry . fileStats = {
258+ insertions : Number ( match [ 1 ] ) || 0 ,
259+ deletions : Number ( match [ 2 ] ) || 0
260+ } ;
261+
262+ switch ( match [ 4 ] ) {
263+ case undefined :
264+ entry . status = 'M' as GitFileStatus ;
265+ entry . fileName = match [ 3 ] ;
266+ break ;
267+ case 'rename' :
268+ entry . status = 'R' as GitFileStatus ;
269+
270+ renamedFileName = match [ 3 ] ;
271+ renamedMatch = fileStatusAndSummaryRenamedFilePathRegex . exec (
272+ renamedFileName
273+ ) ;
274+ if ( renamedMatch != null ) {
275+ entry . fileName = `${ renamedMatch [ 1 ] } ${ renamedMatch [ 3 ] } ${
276+ renamedMatch [ 4 ]
277+ } `;
278+ entry . originalFileName = `${ renamedMatch [ 1 ] } ${ renamedMatch [ 2 ] } ${
279+ renamedMatch [ 4 ]
280+ } `;
281+ }
282+ else {
283+ renamedMatch = fileStatusAndSummaryRenamedFileRegex . exec (
284+ renamedFileName
285+ ) ;
286+ if ( renamedMatch != null ) {
287+ entry . fileName = renamedMatch [ 2 ] ;
288+ entry . originalFileName = renamedMatch [ 1 ] ;
289+ }
290+ else {
291+ entry . fileName = renamedFileName ;
292+ }
293+ }
294+
295+ break ;
296+ case 'create' :
297+ entry . status = 'A' as GitFileStatus ;
298+ entry . fileName = match [ 3 ] ;
299+ break ;
300+ case 'delete' :
301+ entry . status = 'D' as GitFileStatus ;
302+ entry . fileName = match [ 3 ] ;
303+ break ;
304+ default :
305+ entry . status = 'M' as GitFileStatus ;
306+ entry . fileName = match [ 3 ] ;
307+ break ;
255308 }
256309 }
310+
311+ if ( next . done || next . value === '</f>' ) break ;
257312 }
258313 }
259314 }
@@ -355,6 +410,7 @@ export class GitLogParser {
355410
356411 const originalFileName =
357412 entry . originalFileName || ( relativeFileName !== entry . fileName ? entry . fileName : undefined ) ;
413+
358414 if ( type === GitCommitType . LogFile ) {
359415 entry . files = [
360416 {
@@ -380,6 +436,7 @@ export class GitLogParser {
380436 originalFileName ,
381437 type === GitCommitType . Log ? entry . parentShas ! [ 0 ] : undefined ,
382438 undefined ,
439+ entry . fileStats ,
383440 entry . parentShas ! ,
384441 entry . line
385442 ) ;
0 commit comments