@@ -3,9 +3,9 @@ import type { Range } from 'vscode';
33import type { Container } from '../../container' ;
44import { relative } from '../../system/-webview/path' ;
55import { filterMap } from '../../system/array' ;
6- import { normalizePath } from '../../system/path' ;
6+ import { joinPaths , normalizePath } from '../../system/path' ;
77import { maybeStopWatch } from '../../system/stopwatch' ;
8- import { getLines } from '../../system/string' ;
8+ import { iterateByDelimiter , iterateByDelimiters } from '../../system/string' ;
99import type { GitCommitLine , GitStashCommit } from '../models/commit' ;
1010import { GitCommit , GitCommitIdentity } from '../models/commit' ;
1111import type { GitFile } from '../models/file' ;
@@ -231,7 +231,7 @@ export function createLogParser<
231231 let fieldCount = 0 ;
232232 let field ;
233233
234- const fields = getLines ( data , options ?. separator ?? '\0' ) ;
234+ const fields = iterateByDelimiters ( data , options ?. separator ?? '\0' ) ;
235235 if ( options ?. skip ) {
236236 for ( let i = 0 ; i < options . skip ; i ++ ) {
237237 field = fields . next ( ) ;
@@ -266,7 +266,7 @@ export function createLogParserSingle(field: string): Parser<string> {
266266 function * parse ( data : string | string [ ] ) : Generator < string > {
267267 let field ;
268268
269- const fields = getLines ( data , '\0' ) ;
269+ const fields = iterateByDelimiters ( data , '\0' ) ;
270270 while ( true ) {
271271 field = fields . next ( ) ;
272272 if ( field . done ) break ;
@@ -295,7 +295,7 @@ export function createLogParserWithFiles<T extends Record<string, unknown>>(
295295 }
296296
297297 function * parse ( data : string | string [ ] ) : Generator < ParsedEntryWithFiles < T > > {
298- const records = getLines ( data , '\0\0\0' ) ;
298+ const records = iterateByDelimiters ( data , '\0\0\0' ) ;
299299
300300 let entry : ParsedEntryWithFiles < T > ;
301301 let files : ParsedEntryFile [ ] ;
@@ -304,7 +304,7 @@ export function createLogParserWithFiles<T extends Record<string, unknown>>(
304304 for ( const record of records ) {
305305 entry = { } as any ;
306306 files = [ ] ;
307- fields = getLines ( record , '\0' ) ;
307+ fields = iterateByDelimiter ( record , '\0' ) ;
308308
309309 if ( fieldMapping != null ) {
310310 // Skip the 2 starting NULs
@@ -353,13 +353,13 @@ export function createLogParserWithFilesAndStats<T extends Record<string, unknow
353353 keys . push ( key ) ;
354354 format += `%x00${ fieldMapping [ key ] } ` ;
355355 }
356- args = [ '-z' , `--format=${ format } ` , '--numstat' ] ;
356+ args = [ '-z' , `--format=${ format } ` , '--numstat' , '--summary' ] ;
357357 } else {
358- args = [ '-z' , '--numstat' ] ;
358+ args = [ '-z' , '--numstat' , '--summary' ] ;
359359 }
360360
361361 function * parse ( data : string | string [ ] ) : Generator < ParsedEntryWithFilesAndStats < T > > {
362- const records = getLines ( data , '\0\0\0' ) ;
362+ const records = iterateByDelimiters ( data , '\0\0\0' , '\n \0\0') ;
363363
364364 let entry : ParsedEntryWithFilesAndStats < T > ;
365365 let files : ParsedEntryFileWithStats [ ] ;
@@ -368,7 +368,7 @@ export function createLogParserWithFilesAndStats<T extends Record<string, unknow
368368 for ( const record of records ) {
369369 entry = { } as unknown as ParsedEntryWithFilesAndStats < T > ;
370370 files = [ ] ;
371- fields = getLines ( record , '\0' ) ;
371+ fields = iterateByDelimiter ( record , '\0' ) ;
372372
373373 if ( fieldMapping != null ) {
374374 // Skip the 2 starting NULs
@@ -385,6 +385,70 @@ export function createLogParserWithFilesAndStats<T extends Record<string, unknow
385385 if ( fieldCount < keys . length ) {
386386 entry [ keys [ fieldCount ++ ] ] = field . value as ParsedEntryWithFilesAndStats < T > [ keyof T ] ;
387387 } else {
388+ if ( ! field . value ) continue ;
389+ if ( ! field . value . includes ( '\t' ) ) {
390+ let match ;
391+ let rename ;
392+ let renamePrefix ;
393+ let renameBefore ;
394+ let renameAfter ;
395+ let renameSuffix ;
396+ let createOrDelete ;
397+ let createOrDeletePath ;
398+
399+ for ( let line of field . value . split ( '\n' ) ) {
400+ line = line . trim ( ) ;
401+ if ( ! line ) continue ;
402+
403+ match =
404+ / ( r e n a m e ) ( .* ?) \{ ? ( [ ^ { ] + ) \s + = > \s + ( [ ^ } ] + ) \} ? ( .* ?) ? (?: \( \d + % \) ) | ( c r e a t e | d e l e t e ) m o d e \d + ( .+ ) / . exec (
405+ line ,
406+ ) ;
407+ if ( match == null ) continue ;
408+
409+ [
410+ ,
411+ rename ,
412+ renamePrefix ,
413+ renameBefore ,
414+ renameAfter ,
415+ renameSuffix ,
416+ createOrDelete ,
417+ createOrDeletePath ,
418+ ] = match ;
419+
420+ let summaryPath ;
421+ let summaryOriginalPath ;
422+ let summaryStatus ;
423+
424+ if ( rename != null ) {
425+ summaryPath = normalizePath ( joinPaths ( renamePrefix , renameAfter , renameSuffix ?? '' ) ) ;
426+ summaryOriginalPath = normalizePath (
427+ joinPaths ( renamePrefix , renameBefore , renameSuffix ?? '' ) ,
428+ ) ;
429+ summaryStatus = 'R' ;
430+ } else {
431+ summaryPath = normalizePath ( createOrDeletePath ) ;
432+ summaryStatus = createOrDelete === 'create' ? 'A' : 'D' ;
433+ }
434+
435+ const file = files . find ( f => f . path === summaryPath ) ;
436+ if ( file == null ) {
437+ debugger ;
438+ continue ;
439+ }
440+
441+ if ( file . status !== summaryStatus ) {
442+ file . status = summaryStatus ;
443+ if ( summaryOriginalPath != null ) {
444+ file . originalPath = summaryOriginalPath ;
445+ }
446+ }
447+ }
448+
449+ break ;
450+ }
451+
388452 let [ additions , deletions , path ] = field . value . split ( '\t' ) ;
389453 additions = additions . trim ( ) ;
390454 deletions = deletions . trim ( ) ;
@@ -409,19 +473,8 @@ export function createLogParserWithFilesAndStats<T extends Record<string, unknow
409473 }
410474 }
411475
412- // Skip binary files which show as - for both additions and deletions
413- if ( additions === '-' && deletions === '-' ) continue ;
414-
415476 const file : ParsedEntryFileWithStats = {
416- status :
417- status ??
418- ( additions === '0' && deletions === '0'
419- ? 'M'
420- : additions === '0'
421- ? 'D'
422- : deletions === '0'
423- ? 'A'
424- : 'M' ) ,
477+ status : status ?? 'M' ,
425478 path : path ,
426479 originalPath : originalPath ,
427480 additions : additions === '-' ? 0 : parseInt ( additions , 10 ) ,
@@ -530,7 +583,7 @@ export function parseGitLog(
530583 let i = 0 ;
531584 let first = true ;
532585
533- const lines = getLines ( `${ data } </f>` ) ;
586+ const lines = iterateByDelimiter ( `${ data } </f>` ) ;
534587 // Skip the first line since it will always be </f>
535588 let next = lines . next ( ) ;
536589 if ( next . done ) return undefined ;
0 commit comments