@@ -53,6 +53,7 @@ const (
53
53
DiffFileChange
54
54
DiffFileDel
55
55
DiffFileRename
56
+ DiffFileCopy
56
57
)
57
58
58
59
// DiffLineExpandDirection represents the DiffLineSection expand direction
@@ -447,7 +448,46 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
447
448
}
448
449
line := linebuf .String ()
449
450
450
- if strings .HasPrefix (line , "+++ " ) || strings .HasPrefix (line , "--- " ) || len (line ) == 0 {
451
+ if strings .HasPrefix (line , "--- " ) {
452
+ if line [4 ] == '"' {
453
+ fmt .Sscanf (line [4 :], "%q" , & curFile .OldName )
454
+ } else {
455
+ curFile .OldName = line [4 :]
456
+ if strings .Contains (curFile .OldName , " " ) {
457
+ // Git adds a terminal \t if there is a space in the name
458
+ curFile .OldName = curFile .OldName [:len (curFile .OldName )- 1 ]
459
+ }
460
+ }
461
+ if curFile .OldName [0 :2 ] == "a/" {
462
+ curFile .OldName = curFile .OldName [2 :]
463
+ }
464
+ continue
465
+ } else if strings .HasPrefix (line , "+++ " ) {
466
+ if line [4 ] == '"' {
467
+ fmt .Sscanf (line [4 :], "%q" , & curFile .Name )
468
+ } else {
469
+ curFile .Name = line [4 :]
470
+ if strings .Contains (curFile .Name , " " ) {
471
+ // Git adds a terminal \t if there is a space in the name
472
+ curFile .Name = curFile .Name [:len (curFile .Name )- 1 ]
473
+ }
474
+ }
475
+ if curFile .Name [0 :2 ] == "b/" {
476
+ curFile .Name = curFile .Name [2 :]
477
+ }
478
+ curFile .IsRenamed = (curFile .Name != curFile .OldName ) && ! (curFile .IsCreated || curFile .IsDeleted )
479
+ if curFile .IsDeleted {
480
+ curFile .Name = curFile .OldName
481
+ curFile .OldName = ""
482
+ } else if curFile .IsCreated {
483
+ curFile .OldName = ""
484
+ }
485
+ continue
486
+ } else if len (line ) == 0 {
487
+ continue
488
+ }
489
+
490
+ if strings .HasPrefix (line , "+++" ) || strings .HasPrefix (line , "---" ) || len (line ) == 0 {
451
491
continue
452
492
}
453
493
@@ -531,36 +571,10 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
531
571
break
532
572
}
533
573
534
- // Note: In case file name is surrounded by double quotes (it happens only in git-shell).
535
- // e.g. diff --git "a/xxx" "b/xxx"
536
- var a string
537
- var b string
538
-
539
- rd := strings .NewReader (line [len (cmdDiffHead ):])
540
- char , _ := rd .ReadByte ()
541
- _ = rd .UnreadByte ()
542
- if char == '"' {
543
- fmt .Fscanf (rd , "%q " , & a )
544
- } else {
545
- fmt .Fscanf (rd , "%s " , & a )
546
- }
547
- char , _ = rd .ReadByte ()
548
- _ = rd .UnreadByte ()
549
- if char == '"' {
550
- fmt .Fscanf (rd , "%q" , & b )
551
- } else {
552
- fmt .Fscanf (rd , "%s" , & b )
553
- }
554
- a = a [2 :]
555
- b = b [2 :]
556
-
557
574
curFile = & DiffFile {
558
- Name : b ,
559
- OldName : a ,
560
- Index : len (diff .Files ) + 1 ,
561
- Type : DiffFileChange ,
562
- Sections : make ([]* DiffSection , 0 , 10 ),
563
- IsRenamed : a != b ,
575
+ Index : len (diff .Files ) + 1 ,
576
+ Type : DiffFileChange ,
577
+ Sections : make ([]* DiffSection , 0 , 10 ),
564
578
}
565
579
diff .Files = append (diff .Files , curFile )
566
580
curFileLinesCount = 0
@@ -569,6 +583,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
569
583
curFileLFSPrefix = false
570
584
571
585
// Check file diff type and is submodule.
586
+ loop:
572
587
for {
573
588
line , err := input .ReadString ('\n' )
574
589
if err != nil {
@@ -579,23 +594,67 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
579
594
}
580
595
}
581
596
582
- switch {
583
- case strings .HasPrefix (line , "new file" ):
584
- curFile .Type = DiffFileAdd
585
- curFile .IsCreated = true
586
- case strings .HasPrefix (line , "deleted" ):
587
- curFile .Type = DiffFileDel
588
- curFile .IsDeleted = true
589
- case strings .HasPrefix (line , "index" ):
590
- curFile .Type = DiffFileChange
591
- case strings .HasPrefix (line , "similarity index 100%" ):
592
- curFile .Type = DiffFileRename
593
- }
594
- if curFile .Type > 0 {
595
- if strings .HasSuffix (line , " 160000\n " ) {
596
- curFile .IsSubmodule = true
597
+ if curFile .Type != DiffFileRename {
598
+ switch {
599
+ case strings .HasPrefix (line , "new file" ):
600
+ curFile .Type = DiffFileAdd
601
+ curFile .IsCreated = true
602
+ case strings .HasPrefix (line , "deleted" ):
603
+ curFile .Type = DiffFileDel
604
+ curFile .IsDeleted = true
605
+ case strings .HasPrefix (line , "index" ):
606
+ curFile .Type = DiffFileChange
607
+ case strings .HasPrefix (line , "similarity index 100%" ):
608
+ curFile .Type = DiffFileRename
609
+ }
610
+ if curFile .Type > 0 && curFile .Type != DiffFileRename {
611
+ if strings .HasSuffix (line , " 160000\n " ) {
612
+ curFile .IsSubmodule = true
613
+ }
614
+ break
615
+ }
616
+ } else {
617
+ switch {
618
+ case strings .HasPrefix (line , "rename from " ):
619
+ if line [12 ] == '"' {
620
+ fmt .Sscanf (line [12 :], "%q" , & curFile .OldName )
621
+ } else {
622
+ curFile .OldName = line [12 :]
623
+ curFile .OldName = curFile .OldName [:len (curFile .OldName )- 1 ]
624
+ }
625
+ case strings .HasPrefix (line , "rename to " ):
626
+ if line [10 ] == '"' {
627
+ fmt .Sscanf (line [10 :], "%q" , & curFile .Name )
628
+ } else {
629
+ curFile .Name = line [10 :]
630
+ curFile .Name = curFile .Name [:len (curFile .Name )- 1 ]
631
+ }
632
+ curFile .IsRenamed = true
633
+ break loop
634
+ case strings .HasPrefix (line , "copy from " ):
635
+ if line [10 ] == '"' {
636
+ fmt .Sscanf (line [10 :], "%q" , & curFile .OldName )
637
+ } else {
638
+ curFile .OldName = line [10 :]
639
+ curFile .OldName = curFile .OldName [:len (curFile .OldName )- 1 ]
640
+ }
641
+ case strings .HasPrefix (line , "copy to " ):
642
+ if line [8 ] == '"' {
643
+ fmt .Sscanf (line [8 :], "%q" , & curFile .Name )
644
+ } else {
645
+ curFile .Name = line [8 :]
646
+ curFile .Name = curFile .Name [:len (curFile .Name )- 1 ]
647
+ }
648
+ curFile .IsRenamed = true
649
+ curFile .Type = DiffFileCopy
650
+ break loop
651
+ default :
652
+ if strings .HasSuffix (line , " 160000\n " ) {
653
+ curFile .IsSubmodule = true
654
+ } else {
655
+ break loop
656
+ }
597
657
}
598
- break
599
658
}
600
659
}
601
660
}
0 commit comments