Skip to content

Commit d5b1aec

Browse files
committed
Finally fix diff names (go-gitea#13136)
Backport go-gitea#13136 it is possible to have an ambiguous line here. 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 go-gitea#12771 and uses these options to fix this. Signed-off-by: Andrew Thornton <[email protected]>
1 parent 09abdb8 commit d5b1aec

File tree

3 files changed

+81
-124
lines changed

3 files changed

+81
-124
lines changed

modules/repofiles/temp_repo.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ func (t *TemporaryUploadRepository) DiffIndex() (*gitdiff.Diff, error) {
278278
var diff *gitdiff.Diff
279279
var finalErr error
280280

281-
if err := git.NewCommand("diff-index", "--cached", "-p", "HEAD").
281+
if err := git.NewCommand("diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD").
282282
RunInDirTimeoutEnvFullPipelineFunc(nil, 30*time.Second, t.basePath, stdoutWriter, stderr, nil, func(ctx context.Context, cancel context.CancelFunc) error {
283283
_ = stdoutWriter.Close()
284284
diff, finalErr = gitdiff.ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdoutReader)

services/gitdiff/gitdiff.go

+59-105
Original file line numberDiff line numberDiff line change
@@ -448,46 +448,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
448448
}
449449
line := linebuf.String()
450450

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+
if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") || len(line) == 0 {
491452
continue
492453
}
493454

@@ -571,10 +532,42 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
571532
break
572533
}
573534

535+
// Note: In case file name is surrounded by double quotes (it happens only in git-shell).
536+
// e.g. diff --git "a/xxx" "b/xxx"
537+
var a string
538+
var b string
539+
540+
rd := strings.NewReader(line[len(cmdDiffHead):])
541+
char, _ := rd.ReadByte()
542+
_ = rd.UnreadByte()
543+
if char == '"' {
544+
fmt.Fscanf(rd, "%q ", &a)
545+
if a[0] == '\\' {
546+
a = a[1:]
547+
}
548+
} else {
549+
fmt.Fscanf(rd, "%s ", &a)
550+
}
551+
char, _ = rd.ReadByte()
552+
_ = rd.UnreadByte()
553+
if char == '"' {
554+
fmt.Fscanf(rd, "%q", &b)
555+
if b[0] == '\\' {
556+
b = b[1:]
557+
}
558+
} else {
559+
fmt.Fscanf(rd, "%s", &b)
560+
}
561+
a = a[2:]
562+
b = b[2:]
563+
574564
curFile = &DiffFile{
575-
Index: len(diff.Files) + 1,
576-
Type: DiffFileChange,
577-
Sections: make([]*DiffSection, 0, 10),
565+
Name: b,
566+
OldName: a,
567+
Index: len(diff.Files) + 1,
568+
Type: DiffFileChange,
569+
Sections: make([]*DiffSection, 0, 10),
570+
IsRenamed: a != b,
578571
}
579572
diff.Files = append(diff.Files, curFile)
580573
curFileLinesCount = 0
@@ -583,7 +576,6 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
583576
curFileLFSPrefix = false
584577

585578
// Check file diff type and is submodule.
586-
loop:
587579
for {
588580
line, err := input.ReadString('\n')
589581
if err != nil {
@@ -594,67 +586,29 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
594586
}
595587
}
596588

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-
}
589+
switch {
590+
case strings.HasPrefix(line, "copy from "):
591+
curFile.IsRenamed = true
592+
curFile.Type = DiffFileCopy
593+
case strings.HasPrefix(line, "copy to "):
594+
curFile.IsRenamed = true
595+
curFile.Type = DiffFileCopy
596+
case strings.HasPrefix(line, "new file"):
597+
curFile.Type = DiffFileAdd
598+
curFile.IsCreated = true
599+
case strings.HasPrefix(line, "deleted"):
600+
curFile.Type = DiffFileDel
601+
curFile.IsDeleted = true
602+
case strings.HasPrefix(line, "index"):
603+
curFile.Type = DiffFileChange
604+
case strings.HasPrefix(line, "similarity index 100%"):
605+
curFile.Type = DiffFileRename
606+
}
607+
if curFile.Type > 0 {
608+
if strings.HasSuffix(line, " 160000\n") {
609+
curFile.IsSubmodule = true
657610
}
611+
break
658612
}
659613
}
660614
}
@@ -723,7 +677,7 @@ func GetDiffRangeWithWhitespaceBehavior(repoPath, beforeCommitID, afterCommitID
723677
parentCommit, _ := commit.Parent(0)
724678
actualBeforeCommitID = parentCommit.ID.String()
725679
}
726-
diffArgs := []string{"diff", "-M"}
680+
diffArgs := []string{"diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M"}
727681
if len(whitespaceBehavior) != 0 {
728682
diffArgs = append(diffArgs, whitespaceBehavior)
729683
}

services/gitdiff/gitdiff_test.go

+21-18
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ func TestParsePatch_singlefile(t *testing.T) {
5656
tests := []testcase{
5757
{
5858
name: "readme.md2readme.md",
59-
gitdiff: `diff --git "a/README.md" "b/README.md"
60-
--- a/README.md
61-
+++ b/README.md
59+
gitdiff: `diff --git "\\a/README.md" "\\b/README.md"
60+
--- "\\a/README.md"
61+
+++ "\\b/README.md"
6262
@@ -1,3 +1,6 @@
6363
# gitea-github-migrator
6464
+
@@ -68,9 +68,10 @@ func TestParsePatch_singlefile(t *testing.T) {
6868
+ cut off
6969
+ cut off
7070
`,
71-
addition: 4,
72-
deletion: 1,
73-
filename: "README.md",
71+
addition: 4,
72+
deletion: 1,
73+
filename: "README.md",
74+
oldFilename: "README.md",
7475
},
7576
{
7677
name: "A \\ B",
@@ -85,16 +86,17 @@ func TestParsePatch_singlefile(t *testing.T) {
8586
Docker Pulls
8687
+ cut off
8788
+ cut off`,
88-
addition: 4,
89-
deletion: 1,
90-
filename: "A \\ B",
89+
addition: 4,
90+
deletion: 1,
91+
filename: "A \\ B",
92+
oldFilename: "A \\ B",
9193
},
9294
{
9395
name: "really weird filename",
94-
gitdiff: `diff --git a/a b/file b/a a/file b/a b/file b/a a/file
96+
gitdiff: `diff --git "\\a/a b/file b/a a/file" "\\b/a b/file b/a a/file"
9597
index d2186f1..f5c8ed2 100644
96-
--- a/a b/file b/a a/file
97-
+++ b/a b/file b/a a/file
98+
--- "\\a/a b/file b/a a/file"
99+
+++ "\\b/a b/file b/a a/file"
98100
@@ -1,3 +1,2 @@
99101
Create a weird file.
100102
@@ -107,10 +109,10 @@ index d2186f1..f5c8ed2 100644
107109
},
108110
{
109111
name: "delete file with blanks",
110-
gitdiff: `diff --git a/file with blanks b/file with blanks
112+
gitdiff: `diff --git "\\a/file with blanks" "\\b/file with blanks"
111113
deleted file mode 100644
112114
index 898651a..0000000
113-
--- a/file with blanks
115+
--- "\\a/file with blanks"
114116
+++ /dev/null
115117
@@ -1,5 +0,0 @@
116118
-a blank file
@@ -119,9 +121,10 @@ index 898651a..0000000
119121
-
120122
-the 5th line is the last
121123
`,
122-
addition: 0,
123-
deletion: 5,
124-
filename: "file with blanks",
124+
addition: 0,
125+
deletion: 5,
126+
filename: "file with blanks",
127+
oldFilename: "file with blanks",
125128
},
126129
{
127130
name: "rename a—as",
@@ -137,7 +140,7 @@ rename to "a\342\200\224as"
137140
},
138141
{
139142
name: "rename with spaces",
140-
gitdiff: `diff --git a/a b/file b/a a/file b/a b/a a/file b/b file
143+
gitdiff: `diff --git "\\a/a b/file b/a a/file" "\\b/a b/a a/file b/b file"
141144
similarity index 100%
142145
rename from a b/file b/a a/file
143146
rename to a b/a a/file b/b file

0 commit comments

Comments
 (0)