diff --git a/models/git_diff.go b/models/git_diff.go index 546e47fcf..231e9fcbe 100644 --- a/models/git_diff.go +++ b/models/git_diff.go @@ -266,6 +266,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 @@ -337,6 +340,11 @@ func CutDiffAroundLine(originalDiff io.Reader, line int64, old bool, numbersOfLi } } + // No hunk found + if currentLine == 0 { + return "" + } + if len(hunk)-headerLines < numbersOfLine { // No need to cut the hunk => return existing hunk return strings.Join(hunk, "\n") diff --git a/models/git_diff_test.go b/models/git_diff_test.go index ee4f4dd6c..35407d740 100644 --- a/models/git_diff_test.go +++ b/models/git_diff_test.go @@ -71,6 +71,32 @@ func TestCutDiffAroundLine(t *testing.T) { 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(exampleDiff), 4, false, 3) + println(result) } func TestDiff_LoadComments(t *testing.T) {