summaryrefslogtreecommitdiffstats
path: root/models/git_diff.go
diff options
context:
space:
mode:
authorAndrey Nering <andrey.nering@gmail.com>2016-08-07 13:49:47 -0300
committer无闻 <u@gogs.io>2016-08-07 09:49:47 -0700
commit2772791fdad8f0ec4ae49aad020f8afdff2f9c46 (patch)
treefb07f73dfbab67a42d492009ae97119d39a0587a /models/git_diff.go
parent08c976f8117b92b25ea197e7dc0372b49d9ee412 (diff)
downloadgitea-2772791fdad8f0ec4ae49aad020f8afdff2f9c46.tar.gz
gitea-2772791fdad8f0ec4ae49aad020f8afdff2f9c46.zip
Improve diff highlight (#3390)
- Try to reduce memory allocations - Add possibility to disable diff highlight (can improve performance for large diffs) - Tweaking with cost for prettier (cleaner) diffs - Do not calculate diff when the number of removed lines in a block is not equal to the number of added lines (this usually resulted in ugly diffs)
Diffstat (limited to 'models/git_diff.go')
-rw-r--r--models/git_diff.go82
1 files changed, 54 insertions, 28 deletions
diff --git a/models/git_diff.go b/models/git_diff.go
index a3040081b0..5c5954fcac 100644
--- a/models/git_diff.go
+++ b/models/git_diff.go
@@ -26,6 +26,7 @@ import (
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/process"
+ "github.com/gogits/gogs/modules/setting"
"github.com/gogits/gogs/modules/template/highlight"
)
@@ -70,17 +71,18 @@ var (
)
func diffToHTML(diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTML {
- var buf bytes.Buffer
+ buf := bytes.NewBuffer(nil)
for i := range diffs {
- if diffs[i].Type == diffmatchpatch.DiffInsert && lineType == DIFF_LINE_ADD {
+ switch {
+ case diffs[i].Type == diffmatchpatch.DiffInsert && lineType == DIFF_LINE_ADD:
buf.Write(addedCodePrefix)
buf.WriteString(html.EscapeString(diffs[i].Text))
buf.Write(codeTagSuffix)
- } else if diffs[i].Type == diffmatchpatch.DiffDelete && lineType == DIFF_LINE_DEL {
+ case diffs[i].Type == diffmatchpatch.DiffDelete && lineType == DIFF_LINE_DEL:
buf.Write(removedCodePrefix)
buf.WriteString(html.EscapeString(diffs[i].Text))
buf.Write(codeTagSuffix)
- } else if diffs[i].Type == diffmatchpatch.DiffEqual {
+ case diffs[i].Type == diffmatchpatch.DiffEqual:
buf.WriteString(html.EscapeString(diffs[i].Text))
}
}
@@ -90,62 +92,86 @@ func diffToHTML(diffs []diffmatchpatch.Diff, lineType DiffLineType) template.HTM
// get an specific line by type (add or del) and file line number
func (diffSection *DiffSection) GetLine(lineType DiffLineType, idx int) *DiffLine {
- difference := 0
+ var (
+ difference = 0
+ addCount = 0
+ delCount = 0
+ matchDiffLine *DiffLine
+ )
+LOOP:
for _, diffLine := range diffSection.Lines {
- if diffLine.Type == DIFF_LINE_PLAIN {
- // get the difference of line numbers between ADD and DEL versions
+ switch diffLine.Type {
+ case DIFF_LINE_ADD:
+ addCount++
+ case DIFF_LINE_DEL:
+ delCount++
+ default:
+ if matchDiffLine != nil {
+ break LOOP
+ }
difference = diffLine.RightIdx - diffLine.LeftIdx
- continue
+ addCount = 0
+ delCount = 0
}
- if lineType == DIFF_LINE_DEL {
+ switch lineType {
+ case DIFF_LINE_DEL:
if diffLine.RightIdx == 0 && diffLine.LeftIdx == idx-difference {
- return diffLine
+ matchDiffLine = diffLine
}
- } else if lineType == DIFF_LINE_ADD {
+ case DIFF_LINE_ADD:
if diffLine.LeftIdx == 0 && diffLine.RightIdx == idx+difference {
- return diffLine
+ matchDiffLine = diffLine
}
}
}
+
+ if addCount == delCount {
+ return matchDiffLine
+ }
return nil
}
+var diffMatchPatch = diffmatchpatch.New()
+
+func init() {
+ diffMatchPatch.DiffEditCost = 100
+}
+
// computes inline diff for the given line
func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) template.HTML {
- var compareDiffLine *DiffLine
- var diff1, diff2 string
-
- getDefaultReturn := func() template.HTML {
+ if setting.Git.DisableDiffHighlight {
return template.HTML(html.EscapeString(diffLine.Content[1:]))
}
-
- // just compute diff for adds and removes
- if diffLine.Type != DIFF_LINE_ADD && diffLine.Type != DIFF_LINE_DEL {
- return getDefaultReturn()
- }
+ var (
+ compareDiffLine *DiffLine
+ diff1 string
+ diff2 string
+ )
// try to find equivalent diff line. ignore, otherwise
- if diffLine.Type == DIFF_LINE_ADD {
+ switch diffLine.Type {
+ case DIFF_LINE_ADD:
compareDiffLine = diffSection.GetLine(DIFF_LINE_DEL, diffLine.RightIdx)
if compareDiffLine == nil {
- return getDefaultReturn()
+ return template.HTML(html.EscapeString(diffLine.Content[1:]))
}
diff1 = compareDiffLine.Content
diff2 = diffLine.Content
- } else {
+ case DIFF_LINE_DEL:
compareDiffLine = diffSection.GetLine(DIFF_LINE_ADD, diffLine.LeftIdx)
if compareDiffLine == nil {
- return getDefaultReturn()
+ return template.HTML(html.EscapeString(diffLine.Content[1:]))
}
diff1 = diffLine.Content
diff2 = compareDiffLine.Content
+ default:
+ return template.HTML(html.EscapeString(diffLine.Content[1:]))
}
- dmp := diffmatchpatch.New()
- diffRecord := dmp.DiffMain(diff1[1:], diff2[1:], true)
- diffRecord = dmp.DiffCleanupSemantic(diffRecord)
+ diffRecord := diffMatchPatch.DiffMain(diff1[1:], diff2[1:], true)
+ diffRecord = diffMatchPatch.DiffCleanupEfficiency(diffRecord)
return diffToHTML(diffRecord, diffLine.Type)
}