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
483483 }
484484 line := linebuf.String()
485485
486− if strings.HasPrefix(line, "--- ") {
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 {
486+ if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") || len(line) == 0 {
526487 continue
527488 }
528489
@@ -610,10 +571,42 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 81 unmodified lines
610571 break
611572 }
612573
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+
613603 curFile = &DiffFile{
614− Index: len(diff.Files) + 1,
615− Type: DiffFileChange,
616− Sections: make([]*DiffSection, 0, 10),
604+ Name: b,
605+ OldName: a,
606+ Index: len(diff.Files) + 1,
607+ Type: DiffFileChange,
608+ Sections: make([]*DiffSection, 0, 10),
609+ IsRenamed: a != b,
617610 }
618611 diff.Files = append(diff.Files, curFile)
619612 curFileLinesCount = 0
@@ -622,7 +615,6 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 2 unmodified lines
622615 curFileLFSPrefix = false
623616
624617 // Check file diff type and is submodule.
625− loop:
626618 for {
627619 line, err := input.ReadString('\n')
628620 if err != nil {
@@ -633,67 +625,29 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D · 4 unmodified lines
633625 }
634626 }
635627
636− if curFile.Type != DiffFileRename {
637− switch {
638− case strings.HasPrefix(line, "new file"):
639− curFile.Type = DiffFileAdd
640− curFile.IsCreated = true
641− case strings.HasPrefix(line, "deleted"):
642− curFile.Type = DiffFileDel
643− curFile.IsDeleted = true
644− case strings.HasPrefix(line, "index"):
645− curFile.Type = DiffFileChange
646− case strings.HasPrefix(line, "similarity index 100%"):
647− curFile.Type = DiffFileRename
648− }
649− if curFile.Type > 0 && curFile.Type != DiffFileRename {
650− if strings.HasSuffix(line, " 160000\n") {
651− curFile.IsSubmodule = true
652− }
653− break
654− }
655− } else {
656− switch {
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− }
628+ switch {
629+ case strings.HasPrefix(line, "copy from "):
630+ curFile.IsRenamed = true
631+ curFile.Type = DiffFileCopy
632+ case strings.HasPrefix(line, "copy to "):
633+ curFile.IsRenamed = true
634+ curFile.Type = DiffFileCopy
635+ case strings.HasPrefix(line, "new file"):
636+ curFile.Type = DiffFileAdd
637+ curFile.IsCreated = true
638+ case strings.HasPrefix(line, "deleted"):
639+ curFile.Type = DiffFileDel
640+ curFile.IsDeleted = true
641+ case strings.HasPrefix(line, "index"):
642+ curFile.Type = DiffFileChange
643+ case strings.HasPrefix(line, "similarity index 100%"):
644+ curFile.Type = DiffFileRename
645+ }
646+ if curFile.Type > 0 {
647+ if strings.HasSuffix(line, " 160000\n") {
648+ curFile.IsSubmodule = true
696649 }
650+ break
697651 }
698652 }
699653 }
@@ -762,7 +716,7 @@ func GetDiffRangeWithWhitespaceBehavior(repoPath, beforeCommitID, afterCommitID · 62 unmodified lines
762716 parentCommit, _ := commit.Parent(0)
763717 actualBeforeCommitID = parentCommit.ID.String()
764718 }
765− diffArgs := []string{"diff", "-M"}
719+ diffArgs := []string{"diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M"}
766720 if len(whitespaceBehavior) != 0 {
767721 diffArgs = append(diffArgs, whitespaceBehavior)
768722 }