History

Finally fix diff names (#13136)

* Finally fix diff names #12771 attempted to fix diff by avoiding the git diff line as it is possible to have an ambiguous line here. #12254 attempted to fix diff by assuming that names would quoted if they needed to be and if one was quoted then both would be. Both of these were wrong. I have now discovered `--src-prefix` and `--dst-prefix` which means that we can set this in such a way to force the git diff to always be unambiguous. Therefore this PR rollsback most of the changes in #12771 and uses these options to fix this. Signed-off-by: Andrew Thornton <art27@cantab.net> * Update services/gitdiff/gitdiff.go * Update services/gitdiff/gitdiff.go * Update modules/repofiles/temp_repo.go * fix test Signed-off-by: Andrew Thornton <art27@cantab.net>

zeripath committed 6 years ago

Commit edfebe61 parent aa73b7b3 files · +81 −124Browse files

Showing the changes to services/gitdiff/gitdiff.go (1 of 3 files). Show all

Unified · Split

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