diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 538f613b04588..4ccc0b68feafb 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -571,24 +571,60 @@ 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 + beg := len(cmdDiffHead) + rd := strings.NewReader(line) + _, err := rd.Seek(int64(beg), 0) + if err != nil { + return nil, fmt.Errorf("Seek: %v", err) + } - rd := strings.NewReader(line[len(cmdDiffHead):]) 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) }