summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--modules/git/diff.go260
-rw-r--r--modules/git/diff_test.go82
-rw-r--r--modules/migrations/gitea.go16
-rw-r--r--routers/repo/commit.go4
-rw-r--r--services/gitdiff/gitdiff.go240
-rw-r--r--services/gitdiff/gitdiff_test.go70
-rw-r--r--services/pull/review.go5
7 files changed, 356 insertions, 321 deletions
diff --git a/modules/git/diff.go b/modules/git/diff.go
new file mode 100644
index 0000000000..6f876e4964
--- /dev/null
+++ b/modules/git/diff.go
@@ -0,0 +1,260 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package git
+
+import (
+ "bufio"
+ "bytes"
+ "context"
+ "fmt"
+ "io"
+ "os/exec"
+ "regexp"
+ "strconv"
+ "strings"
+
+ "code.gitea.io/gitea/modules/process"
+)
+
+// RawDiffType type of a raw diff.
+type RawDiffType string
+
+// RawDiffType possible values.
+const (
+ RawDiffNormal RawDiffType = "diff"
+ RawDiffPatch RawDiffType = "patch"
+)
+
+// GetRawDiff dumps diff results of repository in given commit ID to io.Writer.
+func GetRawDiff(repoPath, commitID string, diffType RawDiffType, writer io.Writer) error {
+ return GetRawDiffForFile(repoPath, "", commitID, diffType, "", writer)
+}
+
+// GetRawDiffForFile dumps diff results of file in given commit ID to io.Writer.
+func GetRawDiffForFile(repoPath, startCommit, endCommit string, diffType RawDiffType, file string, writer io.Writer) error {
+ repo, err := OpenRepository(repoPath)
+ if err != nil {
+ return fmt.Errorf("OpenRepository: %v", err)
+ }
+ defer repo.Close()
+
+ return GetRepoRawDiffForFile(repo, startCommit, endCommit, diffType, file, writer)
+}
+
+// GetRepoRawDiffForFile dumps diff results of file in given commit ID to io.Writer according given repository
+func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diffType RawDiffType, file string, writer io.Writer) error {
+ commit, err := repo.GetCommit(endCommit)
+ if err != nil {
+ return fmt.Errorf("GetCommit: %v", err)
+ }
+ fileArgs := make([]string, 0)
+ if len(file) > 0 {
+ fileArgs = append(fileArgs, "--", file)
+ }
+ // FIXME: graceful: These commands should have a timeout
+ ctx, cancel := context.WithCancel(DefaultContext)
+ defer cancel()
+
+ var cmd *exec.Cmd
+ switch diffType {
+ case RawDiffNormal:
+ if len(startCommit) != 0 {
+ cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"diff", "-M", startCommit, endCommit}, fileArgs...)...)
+ } else if commit.ParentCount() == 0 {
+ cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"show", endCommit}, fileArgs...)...)
+ } else {
+ c, _ := commit.Parent(0)
+ cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"diff", "-M", c.ID.String(), endCommit}, fileArgs...)...)
+ }
+ case RawDiffPatch:
+ if len(startCommit) != 0 {
+ query := fmt.Sprintf("%s...%s", endCommit, startCommit)
+ cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"format-patch", "--no-signature", "--stdout", "--root", query}, fileArgs...)...)
+ } else if commit.ParentCount() == 0 {
+ cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"format-patch", "--no-signature", "--stdout", "--root", endCommit}, fileArgs...)...)
+ } else {
+ c, _ := commit.Parent(0)
+ query := fmt.Sprintf("%s...%s", endCommit, c.ID.String())
+ cmd = exec.CommandContext(ctx, GitExecutable, append([]string{"format-patch", "--no-signature", "--stdout", query}, fileArgs...)...)
+ }
+ default:
+ return fmt.Errorf("invalid diffType: %s", diffType)
+ }
+
+ stderr := new(bytes.Buffer)
+
+ cmd.Dir = repo.Path
+ cmd.Stdout = writer
+ cmd.Stderr = stderr
+ pid := process.GetManager().Add(fmt.Sprintf("GetRawDiffForFile: [repo_path: %s]", repo.Path), cancel)
+ defer process.GetManager().Remove(pid)
+
+ if err = cmd.Run(); err != nil {
+ return fmt.Errorf("Run: %v - %s", err, stderr)
+ }
+ return nil
+}
+
+// ParseDiffHunkString parse the diffhunk content and return
+func ParseDiffHunkString(diffhunk string) (leftLine, leftHunk, rightLine, righHunk int) {
+ ss := strings.Split(diffhunk, "@@")
+ ranges := strings.Split(ss[1][1:], " ")
+ leftRange := strings.Split(ranges[0], ",")
+ leftLine, _ = strconv.Atoi(leftRange[0][1:])
+ if len(leftRange) > 1 {
+ leftHunk, _ = strconv.Atoi(leftRange[1])
+ }
+ if len(ranges) > 1 {
+ rightRange := strings.Split(ranges[1], ",")
+ rightLine, _ = strconv.Atoi(rightRange[0])
+ if len(rightRange) > 1 {
+ righHunk, _ = strconv.Atoi(rightRange[1])
+ }
+ } else {
+ log("Parse line number failed: %v", diffhunk)
+ rightLine = leftLine
+ righHunk = leftHunk
+ }
+ return
+}
+
+// Example: @@ -1,8 +1,9 @@ => [..., 1, 8, 1, 9]
+var hunkRegex = regexp.MustCompile(`^@@ -(?P<beginOld>[0-9]+)(,(?P<endOld>[0-9]+))? \+(?P<beginNew>[0-9]+)(,(?P<endNew>[0-9]+))? @@`)
+
+const cmdDiffHead = "diff --git "
+
+func isHeader(lof string) bool {
+ return strings.HasPrefix(lof, cmdDiffHead) || 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 {
+ if line == 0 || numbersOfLine == 0 {
+ // no line or num of lines => no diff
+ return ""
+ }
+ 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
+ for scanner.Scan() {
+ lof := scanner.Text()
+ // Add header to enable parsing
+ if isHeader(lof) {
+ hunk = append(hunk, lof)
+ headerLines++
+ }
+ if currentLine > line {
+ break
+ }
+ // Detect "hunk" with contains commented lof
+ if strings.HasPrefix(lof, "@@") {
+ // Already got our hunk. End of hunk detected!
+ if len(hunk) > headerLines {
+ break
+ }
+ // A map with named groups of our regex to recognize them later more easily
+ submatches := hunkRegex.FindStringSubmatch(lof)
+ groups := make(map[string]string)
+ for i, name := range hunkRegex.SubexpNames() {
+ if i != 0 && name != "" {
+ groups[name] = submatches[i]
+ }
+ }
+ if old {
+ begin, _ = strconv.ParseInt(groups["beginOld"], 10, 64)
+ end, _ = strconv.ParseInt(groups["endOld"], 10, 64)
+ // init otherLine with begin of opposite side
+ otherLine, _ = strconv.ParseInt(groups["beginNew"], 10, 64)
+ } else {
+ begin, _ = strconv.ParseInt(groups["beginNew"], 10, 64)
+ if groups["endNew"] != "" {
+ end, _ = strconv.ParseInt(groups["endNew"], 10, 64)
+ } else {
+ end = 0
+ }
+ // init otherLine with begin of opposite side
+ otherLine, _ = strconv.ParseInt(groups["beginOld"], 10, 64)
+ }
+ end += begin // end is for real only the number of lines in hunk
+ // lof is between begin and end
+ if begin <= line && end >= line {
+ hunk = append(hunk, lof)
+ currentLine = begin
+ continue
+ }
+ } else if len(hunk) > headerLines {
+ hunk = append(hunk, lof)
+ // Count lines in context
+ switch lof[0] {
+ case '+':
+ if !old {
+ currentLine++
+ } else {
+ otherLine++
+ }
+ case '-':
+ if old {
+ currentLine++
+ } else {
+ otherLine++
+ }
+ default:
+ currentLine++
+ otherLine++
+ }
+ }
+ }
+
+ // No hunk found
+ if currentLine == 0 {
+ return ""
+ }
+ // headerLines + hunkLine (1) = totalNonCodeLines
+ if len(hunk)-headerLines-1 <= numbersOfLine {
+ // No need to cut the hunk => return existing hunk
+ return strings.Join(hunk, "\n")
+ }
+ var oldBegin, oldNumOfLines, newBegin, newNumOfLines int64
+ if old {
+ oldBegin = currentLine
+ newBegin = otherLine
+ } else {
+ oldBegin = otherLine
+ newBegin = currentLine
+ }
+ // headers + hunk header
+ newHunk := make([]string, headerLines)
+ // transfer existing headers
+ copy(newHunk, hunk[:headerLines])
+ // transfer last n lines
+ newHunk = append(newHunk, hunk[len(hunk)-numbersOfLine-1:]...)
+ // calculate newBegin, ... by counting lines
+ for i := len(hunk) - 1; i >= len(hunk)-numbersOfLine; i-- {
+ switch hunk[i][0] {
+ case '+':
+ newBegin--
+ newNumOfLines++
+ case '-':
+ oldBegin--
+ oldNumOfLines++
+ default:
+ oldBegin--
+ newBegin--
+ newNumOfLines++
+ oldNumOfLines++
+ }
+ }
+ // construct the new hunk header
+ newHunk[headerLines] = fmt.Sprintf("@@ -%d,%d +%d,%d @@",
+ oldBegin, oldNumOfLines, newBegin, newNumOfLines)
+ return strings.Join(newHunk, "\n")
+}
diff --git a/modules/git/diff_test.go b/modules/git/diff_test.go
new file mode 100644
index 0000000000..4258abfe50
--- /dev/null
+++ b/modules/git/diff_test.go
@@ -0,0 +1,82 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package git
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+const exampleDiff = `diff --git a/README.md b/README.md
+--- a/README.md
++++ b/README.md
+@@ -1,3 +1,6 @@
+ # gitea-github-migrator
++
++ Build Status
+- Latest Release
+ Docker Pulls
++ cut off
++ cut off`
+
+func TestCutDiffAroundLine(t *testing.T) {
+ result := CutDiffAroundLine(strings.NewReader(exampleDiff), 4, false, 3)
+ resultByLine := strings.Split(result, "\n")
+ assert.Len(t, resultByLine, 7)
+ // Check if headers got transferred
+ assert.Equal(t, "diff --git a/README.md b/README.md", resultByLine[0])
+ assert.Equal(t, "--- a/README.md", resultByLine[1])
+ assert.Equal(t, "+++ b/README.md", resultByLine[2])
+ // Check if hunk header is calculated correctly
+ assert.Equal(t, "@@ -2,2 +3,2 @@", resultByLine[3])
+ // Check if line got transferred
+ 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)
+ 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)
+ assert.Equal(t, exampleDiff, newResult)
+
+ emptyResult := CutDiffAroundLine(strings.NewReader(exampleDiff), 6, false, 0)
+ assert.Empty(t, emptyResult)
+
+ // Line is out of scope
+ emptyResult = CutDiffAroundLine(strings.NewReader(exampleDiff), 434, false, 0)
+ assert.Empty(t, emptyResult)
+}
+
+func BenchmarkCutDiffAroundLine(b *testing.B) {
+ for n := 0; n < b.N; n++ {
+ CutDiffAroundLine(strings.NewReader(exampleDiff), 3, true, 3)
+ }
+}
+
+func ExampleCutDiffAroundLine() {
+ const diff = `diff --git a/README.md b/README.md
+--- a/README.md
++++ b/README.md
+@@ -1,3 +1,6 @@
+ # gitea-github-migrator
++
++ Build Status
+- Latest Release
+ Docker Pulls
++ cut off
++ cut off`
+ result := CutDiffAroundLine(strings.NewReader(diff), 4, false, 3)
+ println(result)
+}
+
+func TestParseDiffHunkString(t *testing.T) {
+ leftLine, leftHunk, rightLine, rightHunk := ParseDiffHunkString("@@ -19,3 +19,5 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER")
+ assert.EqualValues(t, 19, leftLine)
+ assert.EqualValues(t, 3, leftHunk)
+ assert.EqualValues(t, 19, rightLine)
+ assert.EqualValues(t, 5, rightHunk)
+}
diff --git a/modules/migrations/gitea.go b/modules/migrations/gitea.go
index 96d47dc527..a087cafe9d 100644
--- a/modules/migrations/gitea.go
+++ b/modules/migrations/gitea.go
@@ -28,7 +28,6 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
- "code.gitea.io/gitea/services/gitdiff"
gouuid "github.com/satori/go.uuid"
)
@@ -783,19 +782,22 @@ func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error {
}
for _, comment := range review.Comments {
+ _, _, line, _ := git.ParseDiffHunkString(comment.DiffHunk)
+
headCommitID, err := g.gitRepo.GetRefCommitID(pr.GetGitRefName())
if err != nil {
return fmt.Errorf("GetRefCommitID[%s]: %v", pr.GetGitRefName(), err)
}
+
+ var patch string
patchBuf := new(bytes.Buffer)
- if err := gitdiff.GetRawDiffForFile(g.gitRepo.Path, pr.MergeBase, headCommitID, gitdiff.RawDiffNormal, comment.TreePath, patchBuf); err != nil {
- return fmt.Errorf("GetRawDiffForLine[%s, %s, %s, %s]: %v", g.gitRepo.Path, pr.MergeBase, headCommitID, comment.TreePath, err)
+ 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)
}
- _, _, line, _ := gitdiff.ParseDiffHunkString(comment.DiffHunk)
-
- patch := gitdiff.CutDiffAroundLine(patchBuf, int64((&models.Comment{Line: int64(line + comment.Position - 1)}).UnsignedLine()), line < 0, setting.UI.CodeCommentLines)
-
var c = models.Comment{
Type: models.CommentTypeCode,
PosterID: comment.PosterID,
diff --git a/routers/repo/commit.go b/routers/repo/commit.go
index 2e6cd76bb3..b2fa2790bc 100644
--- a/routers/repo/commit.go
+++ b/routers/repo/commit.go
@@ -292,10 +292,10 @@ func Diff(ctx *context.Context) {
// RawDiff dumps diff results of repository in given commit ID to io.Writer
func RawDiff(ctx *context.Context) {
- if err := gitdiff.GetRawDiff(
+ if err := git.GetRawDiff(
models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name),
ctx.Params(":sha"),
- gitdiff.RawDiffType(ctx.Params(":ext")),
+ git.RawDiffType(ctx.Params(":ext")),
ctx.Resp,
); err != nil {
ctx.ServerError("GetRawDiff", err)
diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go
index 6632f2d94e..6867f8e0a4 100644
--- a/services/gitdiff/gitdiff.go
+++ b/services/gitdiff/gitdiff.go
@@ -17,7 +17,6 @@ import (
"net/url"
"os"
"os/exec"
- "regexp"
"sort"
"strconv"
"strings"
@@ -31,7 +30,6 @@ import (
"code.gitea.io/gitea/modules/setting"
"github.com/sergi/go-diff/diffmatchpatch"
- "github.com/unknwon/com"
stdcharset "golang.org/x/net/html/charset"
"golang.org/x/text/transform"
)
@@ -149,31 +147,8 @@ func (d *DiffLine) GetExpandDirection() DiffLineExpandDirection {
return DiffLineExpandSingle
}
-// ParseDiffHunkString parse the diffhunk content and return
-func ParseDiffHunkString(diffhunk string) (leftLine, leftHunk, rightLine, righHunk int) {
- ss := strings.Split(diffhunk, "@@")
- ranges := strings.Split(ss[1][1:], " ")
- leftRange := strings.Split(ranges[0], ",")
- leftLine, _ = com.StrTo(leftRange[0][1:]).Int()
- if len(leftRange) > 1 {
- leftHunk, _ = com.StrTo(leftRange[1]).Int()
- }
- if len(ranges) > 1 {
- rightRange := strings.Split(ranges[1], ",")
- rightLine, _ = com.StrTo(rightRange[0]).Int()
- if len(rightRange) > 1 {
- righHunk, _ = com.StrTo(rightRange[1]).Int()
- }
- } else {
- log.Warn("Parse line number failed: %v", diffhunk)
- rightLine = leftLine
- righHunk = leftHunk
- }
- return
-}
-
func getDiffLineSectionInfo(treePath, line string, lastLeftIdx, lastRightIdx int) *DiffLineSectionInfo {
- leftLine, leftHunk, rightLine, righHunk := ParseDiffHunkString(line)
+ leftLine, leftHunk, rightLine, righHunk := git.ParseDiffHunkString(line)
return &DiffLineSectionInfo{
Path: treePath,
@@ -428,143 +403,6 @@ func (diff *Diff) NumFiles() int {
return len(diff.Files)
}
-// Example: @@ -1,8 +1,9 @@ => [..., 1, 8, 1, 9]
-var hunkRegex = regexp.MustCompile(`^@@ -(?P<beginOld>[0-9]+)(,(?P<endOld>[0-9]+))? \+(?P<beginNew>[0-9]+)(,(?P<endNew>[0-9]+))? @@`)
-
-func isHeader(lof string) bool {
- return strings.HasPrefix(lof, cmdDiffHead) || 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 {
- if line == 0 || numbersOfLine == 0 {
- // no line or num of lines => no diff
- return ""
- }
- 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
- for scanner.Scan() {
- lof := scanner.Text()
- // Add header to enable parsing
- if isHeader(lof) {
- hunk = append(hunk, lof)
- headerLines++
- }
- if currentLine > line {
- break
- }
- // Detect "hunk" with contains commented lof
- if strings.HasPrefix(lof, "@@") {
- // Already got our hunk. End of hunk detected!
- if len(hunk) > headerLines {
- break
- }
- // A map with named groups of our regex to recognize them later more easily
- submatches := hunkRegex.FindStringSubmatch(lof)
- groups := make(map[string]string)
- for i, name := range hunkRegex.SubexpNames() {
- if i != 0 && name != "" {
- groups[name] = submatches[i]
- }
- }
- if old {
- begin = com.StrTo(groups["beginOld"]).MustInt64()
- end = com.StrTo(groups["endOld"]).MustInt64()
- // init otherLine with begin of opposite side
- otherLine = com.StrTo(groups["beginNew"]).MustInt64()
- } else {
- begin = com.StrTo(groups["beginNew"]).MustInt64()
- if groups["endNew"] != "" {
- end = com.StrTo(groups["endNew"]).MustInt64()
- } else {
- end = 0
- }
- // init otherLine with begin of opposite side
- otherLine = com.StrTo(groups["beginOld"]).MustInt64()
- }
- end += begin // end is for real only the number of lines in hunk
- // lof is between begin and end
- if begin <= line && end >= line {
- hunk = append(hunk, lof)
- currentLine = begin
- continue
- }
- } else if len(hunk) > headerLines {
- hunk = append(hunk, lof)
- // Count lines in context
- switch lof[0] {
- case '+':
- if !old {
- currentLine++
- } else {
- otherLine++
- }
- case '-':
- if old {
- currentLine++
- } else {
- otherLine++
- }
- default:
- currentLine++
- otherLine++
- }
- }
- }
-
- // No hunk found
- if currentLine == 0 {
- return ""
- }
- // headerLines + hunkLine (1) = totalNonCodeLines
- if len(hunk)-headerLines-1 <= numbersOfLine {
- // No need to cut the hunk => return existing hunk
- return strings.Join(hunk, "\n")
- }
- var oldBegin, oldNumOfLines, newBegin, newNumOfLines int64
- if old {
- oldBegin = currentLine
- newBegin = otherLine
- } else {
- oldBegin = otherLine
- newBegin = currentLine
- }
- // headers + hunk header
- newHunk := make([]string, headerLines)
- // transfer existing headers
- copy(newHunk, hunk[:headerLines])
- // transfer last n lines
- newHunk = append(newHunk, hunk[len(hunk)-numbersOfLine-1:]...)
- // calculate newBegin, ... by counting lines
- for i := len(hunk) - 1; i >= len(hunk)-numbersOfLine; i-- {
- switch hunk[i][0] {
- case '+':
- newBegin--
- newNumOfLines++
- case '-':
- oldBegin--
- oldNumOfLines++
- default:
- oldBegin--
- newBegin--
- newNumOfLines++
- oldNumOfLines++
- }
- }
- // construct the new hunk header
- newHunk[headerLines] = fmt.Sprintf("@@ -%d,%d +%d,%d @@",
- oldBegin, oldNumOfLines, newBegin, newNumOfLines)
- return strings.Join(newHunk, "\n")
-}
-
const cmdDiffHead = "diff --git "
// ParsePatch builds a Diff object from a io.Reader and some
@@ -881,82 +719,6 @@ func GetDiffRangeWithWhitespaceBehavior(repoPath, beforeCommitID, afterCommitID
return diff, nil
}
-// RawDiffType type of a raw diff.
-type RawDiffType string
-
-// RawDiffType possible values.
-const (
- RawDiffNormal RawDiffType = "diff"
- RawDiffPatch RawDiffType = "patch"
-)
-
-// GetRawDiff dumps diff results of repository in given commit ID to io.Writer.
-// TODO: move this function to gogits/git-module
-func GetRawDiff(repoPath, commitID string, diffType RawDiffType, writer io.Writer) error {
- return GetRawDiffForFile(repoPath, "", commitID, diffType, "", writer)
-}
-
-// GetRawDiffForFile dumps diff results of file in given commit ID to io.Writer.
-// TODO: move this function to gogits/git-module
-func GetRawDiffForFile(repoPath, startCommit, endCommit string, diffType RawDiffType, file string, writer io.Writer) error {
- repo, err := git.OpenRepository(repoPath)
- if err != nil {
- return fmt.Errorf("OpenRepository: %v", err)
- }
- defer repo.Close()
-
- commit, err := repo.GetCommit(endCommit)
- if err != nil {
- return fmt.Errorf("GetCommit: %v", err)
- }
- fileArgs := make([]string, 0)
- if len(file) > 0 {
- fileArgs = append(fileArgs, "--", file)
- }
- // FIXME: graceful: These commands should have a timeout
- ctx, cancel := context.WithCancel(git.DefaultContext)
- defer cancel()
-
- var cmd *exec.Cmd
- switch diffType {
- case RawDiffNormal:
- if len(startCommit) != 0 {
- cmd = exec.CommandContext(ctx, git.GitExecutable, append([]string{"diff", "-M", startCommit, endCommit}, fileArgs...)...)
- } else if commit.ParentCount() == 0 {
- cmd = exec.CommandContext(ctx, git.GitExecutable, append([]string{"show", endCommit}, fileArgs...)...)
- } else {
- c, _ := commit.Parent(0)
- cmd = exec.CommandContext(ctx, git.GitExecutable, append([]string{"diff", "-M", c.ID.String(), endCommit}, fileArgs...)...)
- }
- case RawDiffPatch:
- if len(startCommit) != 0 {
- query := fmt.Sprintf("%s...%s", endCommit, startCommit)
- cmd = exec.CommandContext(ctx, git.GitExecutable, append([]string{"format-patch", "--no-signature", "--stdout", "--root", query}, fileArgs...)...)
- } else if commit.ParentCount() == 0 {
- cmd = exec.CommandContext(ctx, git.GitExecutable, append([]string{"format-patch", "--no-signature", "--stdout", "--root", endCommit}, fileArgs...)...)
- } else {
- c, _ := commit.Parent(0)
- query := fmt.Sprintf("%s...%s", endCommit, c.ID.String())
- cmd = exec.CommandContext(ctx, git.GitExecutable, append([]string{"format-patch", "--no-signature", "--stdout", query}, fileArgs...)...)
- }
- default:
- return fmt.Errorf("invalid diffType: %s", diffType)
- }
-
- stderr := new(bytes.Buffer)
-
- cmd.Dir = repoPath
- cmd.Stdout = writer
- cmd.Stderr = stderr
- pid := process.GetManager().Add(fmt.Sprintf("GetRawDiffForFile: [repo_path: %s]", repoPath), cancel)
- defer process.GetManager().Remove(pid)
-
- if err = cmd.Run(); err != nil {
- return fmt.Errorf("Run: %v - %s", err, stderr)
- }
- return nil
-}
-
// GetDiffCommit builds a Diff representing the given commitID.
func GetDiffCommit(repoPath, commitID string, maxLines, maxLineCharacters, maxFiles int) (*Diff, error) {
return GetDiffRange(repoPath, "", commitID, maxLines, maxLineCharacters, maxFiles)
diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go
index 58604d97c4..efdf439933 100644
--- a/services/gitdiff/gitdiff_test.go
+++ b/services/gitdiff/gitdiff_test.go
@@ -41,68 +41,6 @@ func TestDiffToHTML(t *testing.T) {
}, DiffLineDel))
}
-const exampleDiff = `diff --git a/README.md b/README.md
---- a/README.md
-+++ b/README.md
-@@ -1,3 +1,6 @@
- # gitea-github-migrator
-+
-+ Build Status
-- Latest Release
- Docker Pulls
-+ cut off
-+ cut off`
-
-func TestCutDiffAroundLine(t *testing.T) {
- result := CutDiffAroundLine(strings.NewReader(exampleDiff), 4, false, 3)
- resultByLine := strings.Split(result, "\n")
- assert.Len(t, resultByLine, 7)
- // Check if headers got transferred
- assert.Equal(t, "diff --git a/README.md b/README.md", resultByLine[0])
- assert.Equal(t, "--- a/README.md", resultByLine[1])
- assert.Equal(t, "+++ b/README.md", resultByLine[2])
- // Check if hunk header is calculated correctly
- assert.Equal(t, "@@ -2,2 +3,2 @@", resultByLine[3])
- // Check if line got transferred
- 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)
- 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)
- assert.Equal(t, exampleDiff, newResult)
-
- emptyResult := CutDiffAroundLine(strings.NewReader(exampleDiff), 6, false, 0)
- assert.Empty(t, emptyResult)
-
- // Line is out of scope
- emptyResult = CutDiffAroundLine(strings.NewReader(exampleDiff), 434, false, 0)
- assert.Empty(t, emptyResult)
-}
-
-func BenchmarkCutDiffAroundLine(b *testing.B) {
- for n := 0; n < b.N; n++ {
- CutDiffAroundLine(strings.NewReader(exampleDiff), 3, true, 3)
- }
-}
-
-func ExampleCutDiffAroundLine() {
- const diff = `diff --git a/README.md b/README.md
---- a/README.md
-+++ b/README.md
-@@ -1,3 +1,6 @@
- # gitea-github-migrator
-+
-+ Build Status
-- Latest Release
- Docker Pulls
-+ cut off
-+ cut off`
- result := CutDiffAroundLine(strings.NewReader(diff), 4, false, 3)
- println(result)
-}
-
func TestParsePatch(t *testing.T) {
var diff = `diff --git "a/README.md" "b/README.md"
--- a/README.md
@@ -209,11 +147,3 @@ func TestGetDiffRangeWithWhitespaceBehavior(t *testing.T) {
}
}
}
-
-func TestParseDiffHunkString(t *testing.T) {
- leftLine, leftHunk, rightLine, rightHunk := ParseDiffHunkString("@@ -19,3 +19,5 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER")
- assert.EqualValues(t, 19, leftLine)
- assert.EqualValues(t, 3, leftHunk)
- assert.EqualValues(t, 19, rightLine)
- assert.EqualValues(t, 5, rightHunk)
-}
diff --git a/services/pull/review.go b/services/pull/review.go
index 2bc8240230..2b7c9e8646 100644
--- a/services/pull/review.go
+++ b/services/pull/review.go
@@ -14,7 +14,6 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/services/gitdiff"
)
// CreateCodeComment creates a comment on the code line
@@ -140,10 +139,10 @@ func createCodeComment(doer *models.User, repo *models.Repository, issue *models
return nil, fmt.Errorf("GetRefCommitID[%s]: %v", pr.GetGitRefName(), err)
}
patchBuf := new(bytes.Buffer)
- if err := gitdiff.GetRawDiffForFile(gitRepo.Path, pr.MergeBase, headCommitID, gitdiff.RawDiffNormal, treePath, patchBuf); err != nil {
+ if err := git.GetRepoRawDiffForFile(gitRepo, pr.MergeBase, headCommitID, git.RawDiffNormal, treePath, patchBuf); err != nil {
return nil, fmt.Errorf("GetRawDiffForLine[%s, %s, %s, %s]: %v", err, gitRepo.Path, pr.MergeBase, headCommitID, treePath)
}
- patch = gitdiff.CutDiffAroundLine(patchBuf, int64((&models.Comment{Line: line}).UnsignedLine()), line < 0, setting.UI.CodeCommentLines)
+ patch = git.CutDiffAroundLine(patchBuf, int64((&models.Comment{Line: line}).UnsignedLine()), line < 0, setting.UI.CodeCommentLines)
}
return models.CreateComment(&models.CreateCommentOptions{
Type: models.CommentTypeCode,