From fff068a17d09ca09a27757194a79ddd4e1362854 Mon Sep 17 00:00:00 2001 From: Folke Ashberg Date: Tue, 8 Sep 2020 20:06:29 +0200 Subject: [PATCH 1/2] Addresses diff-issue with blanks in pathname #12768 --- services/gitdiff/gitdiff.go | 44 ++++++++++++-- services/gitdiff/gitdiff_test.go | 101 +++++++++++++++++++++++++++++-- 2 files changed, 133 insertions(+), 12 deletions(-) diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 538f613b04588..c986f0d14b02f 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -571,24 +571,56 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D // Note: In case file name is surrounded by double quotes (it happens only in git-shell). // e.g. diff --git "a/xxx" "b/xxx" + // but maybe not a and b are quoted + + // FIXME: if first filename is not quoted and contains ' b/' + // Will NOT WORK: diff --git a/path b/filename b/path b/filename + // Will WORK: diff --git "a/path b/filename" "b/path b/filename" + + var middle int var a string var b string - - rd := strings.NewReader(line[len(cmdDiffHead):]) + beg := len(cmdDiffHead) + rd := strings.NewReader(line) + rd.Seek(int64(beg), 0) char, _ := rd.ReadByte() _ = rd.UnreadByte() - if char == '"' { + + hasQuote := char == '"' + if hasQuote { + lenBefore := rd.Len() fmt.Fscanf(rd, "%q ", &a) + middle = beg + lenBefore - rd.Len() - 1 } else { - fmt.Fscanf(rd, "%s ", &a) + middle = strings.Index(line, " \"b/") + if middle >= 0 { + // b is quoted + _, err := rd.Seek(int64(middle+1), 0) + if err != nil { + return nil, fmt.Errorf("Seek: %v", err) + } + } else { + // b is not quoted + middle = strings.Index(line, " b/") + _, err := rd.Seek(int64(middle), 0) + if err != nil { + return nil, fmt.Errorf("Seek: %v", err) + } + } + a = line[beg:middle] } + char, _ = rd.ReadByte() _ = rd.UnreadByte() - if char == '"' { + hasQuote = char == '"' + if hasQuote { fmt.Fscanf(rd, "%q", &b) } else { - fmt.Fscanf(rd, "%s", &b) + // read to end + b = line[middle+1:] } + + // strip a/ and b/ a = a[2:] b = b[2:] diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index 9826ece2dc5c9..74390d44fa76f 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -78,7 +78,7 @@ func TestDiffToHTML(t *testing.T) { } func TestParsePatch(t *testing.T) { - var diff = `diff --git "a/README.md" "b/README.md" + var diff1 = `diff --git "a/README.md" "b/README.md" --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ @@ -89,9 +89,18 @@ func TestParsePatch(t *testing.T) { Docker Pulls + cut off + cut off` - result, err := ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff)) + result, err := ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff1)) if err != nil { - t.Errorf("ParsePatch failed: %s", err) + t.Errorf("ParsePatch failed [1]: %s", err) + } + if result.NumFiles != 1 { + t.Errorf("ParsePatch failed [1]: Num Files != 1") + } + if result.Files[0].OldName != "README.md" { + t.Errorf("ParsePatch failed [1]: OldName Wrong") + } + if result.Files[0].Name != "README.md" { + t.Errorf("ParsePatch failed [1]: Name Wrong") } println(result) @@ -108,7 +117,16 @@ func TestParsePatch(t *testing.T) { + cut off` result, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2)) if err != nil { - t.Errorf("ParsePatch failed: %s", err) + t.Errorf("ParsePatch failed [2]: %s", err) + } + if result.NumFiles != 1 { + t.Errorf("ParsePatch failed [2]: Num Files != 1") + } + if result.Files[0].OldName != "A \\ B" { + t.Errorf("ParsePatch failed [2]: OldName Wrong") + } + if result.Files[0].Name != "A \\ B" { + t.Errorf("ParsePatch failed [2]: Name Wrong") } println(result) @@ -125,7 +143,69 @@ func TestParsePatch(t *testing.T) { + cut off` result, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2a)) if err != nil { - t.Errorf("ParsePatch failed: %s", err) + t.Errorf("ParsePatch failed [2a]: %s", err) + } + if result.NumFiles != 1 { + t.Errorf("ParsePatch failed [2a]: Num Files != 1") + } + if result.Files[0].OldName != "A \\ B" { + t.Errorf("ParsePatch failed [2a]: OldName Wrong") + } + if result.Files[0].Name != "A/B" { + t.Errorf("ParsePatch failed [2a]: Name Wrong") + } + println(result) + + var diff2b = `diff --git a/A B "b/A \\ B" +--- a/A B ++++ "b/A \\ B" +@@ -1,3 +1,6 @@ + # gitea-github-migrator ++ ++ Build Status +- Latest Release + Docker Pulls ++ cut off ++ cut off` + result, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2b)) + if err != nil { + t.Errorf("ParsePatch failed [2b]: %s", err) + } + if result.NumFiles != 1 { + t.Errorf("ParsePatch failed [2b]: Num Files != 1") + } + if result.Files[0].OldName != "A B" { + t.Errorf("ParsePatch failed [2b]: OldName Wrong") + } + if result.Files[0].Name != "A \\ B" { + t.Errorf("ParsePatch failed [2b]: Name Wrong") + } + println(result) + + // test with blank in filename + var diff2c = `diff --git a/file x b/file x +--- "a/file x" ++++ b/file x +@@ -1,3 +1,6 @@ + # gitea-github-migrator ++ ++ Build Status +- Latest Release + Docker Pulls ++ cut off ++ cut off` + result, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2c)) + if err != nil { + t.Errorf("ParsePatch failed [2c]: %s", err) + } + if result.NumFiles != 1 { + t.Errorf("ParsePatch failed [2c]: Num Files != 1") + } + if result.Files[0].OldName != "file x" { + t.Errorf("ParsePatch failed [2c]: OldName Wrong") + } + if result.Files[0].Name != "file x" { + t.Errorf("ParsePatch failed [2c]: Name Wrong") } println(result) @@ -142,7 +222,16 @@ func TestParsePatch(t *testing.T) { + cut off` result, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff3)) if err != nil { - t.Errorf("ParsePatch failed: %s", err) + t.Errorf("ParsePatch failed [3]: %s", err) + } + if result.NumFiles != 1 { + t.Errorf("ParsePatch failed [3]: Num Files != 1") + } + if result.Files[0].OldName != "README.md" { + t.Errorf("ParsePatch failed [3]: OldName Wrong") + } + if result.Files[0].Name != "README.md" { + t.Errorf("ParsePatch failed [3]: Name Wrong") } println(result) } From e1bc563a9f3925cc5c6c59ec46ed276668bf5fd5 Mon Sep 17 00:00:00 2001 From: Folke Ashberg Date: Tue, 8 Sep 2020 22:43:58 +0200 Subject: [PATCH 2/2] Linting --- services/gitdiff/gitdiff.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index c986f0d14b02f..4ccc0b68feafb 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -582,7 +582,11 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D var b string beg := len(cmdDiffHead) rd := strings.NewReader(line) - rd.Seek(int64(beg), 0) + _, err := rd.Seek(int64(beg), 0) + if err != nil { + return nil, fmt.Errorf("Seek: %v", err) + } + char, _ := rd.ReadByte() _ = rd.UnreadByte()