summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/git/diff.go30
-rw-r--r--modules/git/diff_test.go64
-rw-r--r--modules/migrations/gitea_uploader.go22
3 files changed, 94 insertions, 22 deletions
diff --git a/modules/git/diff.go b/modules/git/diff.go
index 6f876e4964..6faad1c3c0 100644
--- a/modules/git/diff.go
+++ b/modules/git/diff.go
@@ -125,30 +125,39 @@ var hunkRegex = regexp.MustCompile(`^@@ -(?P<beginOld>[0-9]+)(,(?P<endOld>[0-9]+
const cmdDiffHead = "diff --git "
-func isHeader(lof string) bool {
- return strings.HasPrefix(lof, cmdDiffHead) || strings.HasPrefix(lof, "---") || strings.HasPrefix(lof, "+++")
+func isHeader(lof string, inHunk bool) bool {
+ return strings.HasPrefix(lof, cmdDiffHead) || (!inHunk && (strings.HasPrefix(lof, "---") || strings.HasPrefix(lof, "+++")))
}
// CutDiffAroundLine cuts a diff of a file in way that only the given line + numberOfLine above it will be shown
// it also recalculates hunks and adds the appropriate headers to the new diff.
// Warning: Only one-file diffs are allowed.
-func CutDiffAroundLine(originalDiff io.Reader, line int64, old bool, numbersOfLine int) string {
+func CutDiffAroundLine(originalDiff io.Reader, line int64, old bool, numbersOfLine int) (string, error) {
if line == 0 || numbersOfLine == 0 {
// no line or num of lines => no diff
- return ""
+ return "", nil
}
+
scanner := bufio.NewScanner(originalDiff)
hunk := make([]string, 0)
+
// begin is the start of the hunk containing searched line
// end is the end of the hunk ...
// currentLine is the line number on the side of the searched line (differentiated by old)
// otherLine is the line number on the opposite side of the searched line (differentiated by old)
var begin, end, currentLine, otherLine int64
var headerLines int
+
+ inHunk := false
+
for scanner.Scan() {
lof := scanner.Text()
// Add header to enable parsing
- if isHeader(lof) {
+
+ if isHeader(lof, inHunk) {
+ if strings.HasPrefix(lof, cmdDiffHead) {
+ inHunk = false
+ }
hunk = append(hunk, lof)
headerLines++
}
@@ -157,6 +166,7 @@ func CutDiffAroundLine(originalDiff io.Reader, line int64, old bool, numbersOfLi
}
// Detect "hunk" with contains commented lof
if strings.HasPrefix(lof, "@@") {
+ inHunk = true
// Already got our hunk. End of hunk detected!
if len(hunk) > headerLines {
break
@@ -213,15 +223,19 @@ func CutDiffAroundLine(originalDiff io.Reader, line int64, old bool, numbersOfLi
}
}
}
+ err := scanner.Err()
+ if err != nil {
+ return "", err
+ }
// No hunk found
if currentLine == 0 {
- return ""
+ return "", nil
}
// headerLines + hunkLine (1) = totalNonCodeLines
if len(hunk)-headerLines-1 <= numbersOfLine {
// No need to cut the hunk => return existing hunk
- return strings.Join(hunk, "\n")
+ return strings.Join(hunk, "\n"), nil
}
var oldBegin, oldNumOfLines, newBegin, newNumOfLines int64
if old {
@@ -256,5 +270,5 @@ func CutDiffAroundLine(originalDiff io.Reader, line int64, old bool, numbersOfLi
// construct the new hunk header
newHunk[headerLines] = fmt.Sprintf("@@ -%d,%d +%d,%d @@",
oldBegin, oldNumOfLines, newBegin, newNumOfLines)
- return strings.Join(newHunk, "\n")
+ return strings.Join(newHunk, "\n"), nil
}
diff --git a/modules/git/diff_test.go b/modules/git/diff_test.go
index 4258abfe50..363ff0b970 100644
--- a/modules/git/diff_test.go
+++ b/modules/git/diff_test.go
@@ -23,8 +23,28 @@ const exampleDiff = `diff --git a/README.md b/README.md
+ cut off
+ cut off`
+const breakingDiff = `diff --git a/aaa.sql b/aaa.sql
+index d8e4c92..19dc8ad 100644
+--- a/aaa.sql
++++ b/aaa.sql
+@@ -1,9 +1,10 @@
+ --some comment
+--- some comment 5
++--some coment 2
++-- some comment 3
+ create or replace procedure test(p1 varchar2)
+ is
+ begin
+---new comment
+ dbms_output.put_line(p1);
++--some other comment
+ end;
+ /
+`
+
func TestCutDiffAroundLine(t *testing.T) {
- result := CutDiffAroundLine(strings.NewReader(exampleDiff), 4, false, 3)
+ result, err := CutDiffAroundLine(strings.NewReader(exampleDiff), 4, false, 3)
+ assert.NoError(t, err)
resultByLine := strings.Split(result, "\n")
assert.Len(t, resultByLine, 7)
// Check if headers got transferred
@@ -37,18 +57,50 @@ func TestCutDiffAroundLine(t *testing.T) {
assert.Equal(t, "+ Build Status", resultByLine[4])
// Must be same result as before since old line 3 == new line 5
- newResult := CutDiffAroundLine(strings.NewReader(exampleDiff), 3, true, 3)
+ newResult, err := CutDiffAroundLine(strings.NewReader(exampleDiff), 3, true, 3)
+ assert.NoError(t, err)
assert.Equal(t, result, newResult, "Must be same result as before since old line 3 == new line 5")
- newResult = CutDiffAroundLine(strings.NewReader(exampleDiff), 6, false, 300)
+ newResult, err = CutDiffAroundLine(strings.NewReader(exampleDiff), 6, false, 300)
+ assert.NoError(t, err)
assert.Equal(t, exampleDiff, newResult)
- emptyResult := CutDiffAroundLine(strings.NewReader(exampleDiff), 6, false, 0)
+ emptyResult, err := CutDiffAroundLine(strings.NewReader(exampleDiff), 6, false, 0)
+ assert.NoError(t, err)
assert.Empty(t, emptyResult)
// Line is out of scope
- emptyResult = CutDiffAroundLine(strings.NewReader(exampleDiff), 434, false, 0)
+ emptyResult, err = CutDiffAroundLine(strings.NewReader(exampleDiff), 434, false, 0)
+ assert.NoError(t, err)
assert.Empty(t, emptyResult)
+
+ // Handle minus diffs properly
+ minusDiff, err := CutDiffAroundLine(strings.NewReader(breakingDiff), 2, false, 4)
+ assert.NoError(t, err)
+
+ expected := `diff --git a/aaa.sql b/aaa.sql
+--- a/aaa.sql
++++ b/aaa.sql
+@@ -1,9 +1,10 @@
+ --some comment
+--- some comment 5
++--some coment 2`
+ assert.Equal(t, expected, minusDiff)
+
+ // Handle minus diffs properly
+ minusDiff, err = CutDiffAroundLine(strings.NewReader(breakingDiff), 3, false, 4)
+ assert.NoError(t, err)
+
+ expected = `diff --git a/aaa.sql b/aaa.sql
+--- a/aaa.sql
++++ b/aaa.sql
+@@ -1,9 +1,10 @@
+ --some comment
+--- some comment 5
++--some coment 2
++-- some comment 3`
+
+ assert.Equal(t, expected, minusDiff)
}
func BenchmarkCutDiffAroundLine(b *testing.B) {
@@ -69,7 +121,7 @@ func ExampleCutDiffAroundLine() {
Docker Pulls
+ cut off
+ cut off`
- result := CutDiffAroundLine(strings.NewReader(diff), 4, false, 3)
+ result, _ := CutDiffAroundLine(strings.NewReader(diff), 4, false, 3)
println(result)
}
diff --git a/modules/migrations/gitea_uploader.go b/modules/migrations/gitea_uploader.go
index 3be49b5c6c..aa1ea4bc09 100644
--- a/modules/migrations/gitea_uploader.go
+++ b/modules/migrations/gitea_uploader.go
@@ -6,7 +6,6 @@
package migrations
import (
- "bytes"
"context"
"fmt"
"io"
@@ -802,13 +801,20 @@ func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error {
}
var patch string
- patchBuf := new(bytes.Buffer)
- if err := git.GetRepoRawDiffForFile(g.gitRepo, pr.MergeBase, headCommitID, git.RawDiffNormal, comment.TreePath, patchBuf); err != nil {
- // We should ignore the error since the commit maybe removed when force push to the pull request
- log.Warn("GetRepoRawDiffForFile failed when migrating [%s, %s, %s, %s]: %v", g.gitRepo.Path, pr.MergeBase, headCommitID, comment.TreePath, err)
- } else {
- patch = git.CutDiffAroundLine(patchBuf, int64((&models.Comment{Line: int64(line + comment.Position - 1)}).UnsignedLine()), line < 0, setting.UI.CodeCommentLines)
- }
+ reader, writer := io.Pipe()
+ defer func() {
+ _ = reader.Close()
+ _ = writer.Close()
+ }()
+ go func() {
+ if err := git.GetRepoRawDiffForFile(g.gitRepo, pr.MergeBase, headCommitID, git.RawDiffNormal, comment.TreePath, writer); err != nil {
+ // We should ignore the error since the commit maybe removed when force push to the pull request
+ log.Warn("GetRepoRawDiffForFile failed when migrating [%s, %s, %s, %s]: %v", g.gitRepo.Path, pr.MergeBase, headCommitID, comment.TreePath, err)
+ }
+ _ = writer.Close()
+ }()
+
+ patch, _ = git.CutDiffAroundLine(reader, int64((&models.Comment{Line: int64(line + comment.Position - 1)}).UnsignedLine()), line < 0, setting.UI.CodeCommentLines)
var c = models.Comment{
Type: models.CommentTypeCode,