@@ -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
@@ -481,7 +482,46 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
481
482
}
482
483
line := linebuf .String ()
483
484
484
- if strings .HasPrefix (line , "+++ " ) || strings .HasPrefix (line , "--- " ) || len (line ) == 0 {
485
+ if strings .HasPrefix (line , "--- " ) {
486
+ if line [4 ] == '"' {
487
+ fmt .Sscanf (line [4 :], "%q" , & curFile .OldName )
488
+ } else {
489
+ curFile .OldName = line [4 :]
490
+ if strings .Contains (curFile .OldName , " " ) {
491
+ // Git adds a terminal \t if there is a space in the name
492
+ curFile .OldName = curFile .OldName [:len (curFile .OldName )- 1 ]
493
+ }
494
+ }
495
+ if curFile .OldName [0 :2 ] == "a/" {
496
+ curFile .OldName = curFile .OldName [2 :]
497
+ }
498
+ continue
499
+ } else if strings .HasPrefix (line , "+++ " ) {
500
+ if line [4 ] == '"' {
501
+ fmt .Sscanf (line [4 :], "%q" , & curFile .Name )
502
+ } else {
503
+ curFile .Name = line [4 :]
504
+ if strings .Contains (curFile .Name , " " ) {
505
+ // Git adds a terminal \t if there is a space in the name
506
+ curFile .Name = curFile .Name [:len (curFile .Name )- 1 ]
507
+ }
508
+ }
509
+ if curFile .Name [0 :2 ] == "b/" {
510
+ curFile .Name = curFile .Name [2 :]
511
+ }
512
+ curFile .IsRenamed = (curFile .Name != curFile .OldName ) && ! (curFile .IsCreated || curFile .IsDeleted )
513
+ if curFile .IsDeleted {
514
+ curFile .Name = curFile .OldName
515
+ curFile .OldName = ""
516
+ } else if curFile .IsCreated {
517
+ curFile .OldName = ""
518
+ }
519
+ continue
520
+ } else if len (line ) == 0 {
521
+ continue
522
+ }
523
+
524
+ if strings .HasPrefix (line , "+++" ) || strings .HasPrefix (line , "---" ) || len (line ) == 0 {
485
525
continue
486
526
}
487
527
@@ -569,36 +609,10 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
569
609
break
570
610
}
571
611
572
- // Note: In case file name is surrounded by double quotes (it happens only in git-shell).
573
- // e.g. diff --git "a/xxx" "b/xxx"
574
- var a string
575
- var b string
576
-
577
- rd := strings .NewReader (line [len (cmdDiffHead ):])
578
- char , _ := rd .ReadByte ()
579
- _ = rd .UnreadByte ()
580
- if char == '"' {
581
- fmt .Fscanf (rd , "%q " , & a )
582
- } else {
583
- fmt .Fscanf (rd , "%s " , & a )
584
- }
585
- char , _ = rd .ReadByte ()
586
- _ = rd .UnreadByte ()
587
- if char == '"' {
588
- fmt .Fscanf (rd , "%q" , & b )
589
- } else {
590
- fmt .Fscanf (rd , "%s" , & b )
591
- }
592
- a = a [2 :]
593
- b = b [2 :]
594
-
595
612
curFile = & DiffFile {
596
- Name : b ,
597
- OldName : a ,
598
- Index : len (diff .Files ) + 1 ,
599
- Type : DiffFileChange ,
600
- Sections : make ([]* DiffSection , 0 , 10 ),
601
- IsRenamed : a != b ,
613
+ Index : len (diff .Files ) + 1 ,
614
+ Type : DiffFileChange ,
615
+ Sections : make ([]* DiffSection , 0 , 10 ),
602
616
}
603
617
diff .Files = append (diff .Files , curFile )
604
618
curFileLinesCount = 0
@@ -607,6 +621,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
607
621
curFileLFSPrefix = false
608
622
609
623
// Check file diff type and is submodule.
624
+ loop:
610
625
for {
611
626
line , err := input .ReadString ('\n' )
612
627
if err != nil {
@@ -617,23 +632,67 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
617
632
}
618
633
}
619
634
620
- switch {
621
- case strings .HasPrefix (line , "new file" ):
622
- curFile .Type = DiffFileAdd
623
- curFile .IsCreated = true
624
- case strings .HasPrefix (line , "deleted" ):
625
- curFile .Type = DiffFileDel
626
- curFile .IsDeleted = true
627
- case strings .HasPrefix (line , "index" ):
628
- curFile .Type = DiffFileChange
629
- case strings .HasPrefix (line , "similarity index 100%" ):
630
- curFile .Type = DiffFileRename
631
- }
632
- if curFile .Type > 0 {
633
- if strings .HasSuffix (line , " 160000\n " ) {
634
- curFile .IsSubmodule = true
635
+ if curFile .Type != DiffFileRename {
636
+ switch {
637
+ case strings .HasPrefix (line , "new file" ):
638
+ curFile .Type = DiffFileAdd
639
+ curFile .IsCreated = true
640
+ case strings .HasPrefix (line , "deleted" ):
641
+ curFile .Type = DiffFileDel
642
+ curFile .IsDeleted = true
643
+ case strings .HasPrefix (line , "index" ):
644
+ curFile .Type = DiffFileChange
645
+ case strings .HasPrefix (line , "similarity index 100%" ):
646
+ curFile .Type = DiffFileRename
647
+ }
648
+ if curFile .Type > 0 && curFile .Type != DiffFileRename {
649
+ if strings .HasSuffix (line , " 160000\n " ) {
650
+ curFile .IsSubmodule = true
651
+ }
652
+ break
653
+ }
654
+ } else {
655
+ switch {
656
+ case strings .HasPrefix (line , "rename from " ):
657
+ if line [12 ] == '"' {
658
+ fmt .Sscanf (line [12 :], "%q" , & curFile .OldName )
659
+ } else {
660
+ curFile .OldName = line [12 :]
661
+ curFile .OldName = curFile .OldName [:len (curFile .OldName )- 1 ]
662
+ }
663
+ case strings .HasPrefix (line , "rename to " ):
664
+ if line [10 ] == '"' {
665
+ fmt .Sscanf (line [10 :], "%q" , & curFile .Name )
666
+ } else {
667
+ curFile .Name = line [10 :]
668
+ curFile .Name = curFile .Name [:len (curFile .Name )- 1 ]
669
+ }
670
+ curFile .IsRenamed = true
671
+ break loop
672
+ case strings .HasPrefix (line , "copy from " ):
673
+ if line [10 ] == '"' {
674
+ fmt .Sscanf (line [10 :], "%q" , & curFile .OldName )
675
+ } else {
676
+ curFile .OldName = line [10 :]
677
+ curFile .OldName = curFile .OldName [:len (curFile .OldName )- 1 ]
678
+ }
679
+ case strings .HasPrefix (line , "copy to " ):
680
+ if line [8 ] == '"' {
681
+ fmt .Sscanf (line [8 :], "%q" , & curFile .Name )
682
+ } else {
683
+ curFile .Name = line [8 :]
684
+ curFile .Name = curFile .Name [:len (curFile .Name )- 1 ]
685
+ }
686
+ curFile .IsRenamed = true
687
+ curFile .Type = DiffFileCopy
688
+ break loop
689
+ default :
690
+ if strings .HasSuffix (line , " 160000\n " ) {
691
+ curFile .IsSubmodule = true
692
+ } else {
693
+ break loop
694
+ }
635
695
}
636
- break
637
696
}
638
697
}
639
698
}
0 commit comments