Skip to content

Commit

Permalink
fix highlight problem of git diff
Browse files Browse the repository at this point in the history
related go-gitea#23176

try fix it with @silverwind solution in
 go-gitea#23176 (comment)

looks the result is good. but looks it will
cost to much memorry when the file is large.
maybe limt the max file size?

Signed-off-by: a1012112796 <1012112796@qq.com>
  • Loading branch information
a1012112796 committed Apr 25, 2023
1 parent 56d4893 commit 5f93560
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 13 deletions.
29 changes: 23 additions & 6 deletions routers/web/repo/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package repo

import (
"bufio"
"bytes"
gocontext "context"
"encoding/csv"
"errors"
Expand All @@ -27,6 +28,7 @@ import (
"code.gitea.io/gitea/modules/context"
csv_module "code.gitea.io/gitea/modules/csv"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/highlight"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/setting"
Expand Down Expand Up @@ -929,8 +931,21 @@ func getExcerptLines(commit *git.Commit, filePath string, idxLeft, idxRight, chu
if err != nil {
return nil, err
}
defer reader.Close()
scanner := bufio.NewScanner(reader)

content, err := io.ReadAll(reader)
_ = reader.Close()
if err != nil {
log.Error("io.ReadAll: %v", err)
return nil, err
}

highlightedContent, _, err := highlight.File(filePath, "", content)
if err != nil {
log.Error("highlight.File: %v", err)
return nil, err
}

scanner := bufio.NewScanner(bytes.NewBuffer(content))
var diffLines []*gitdiff.DiffLine
for line := 0; line < idxRight+chunkSize; line++ {
if ok := scanner.Scan(); !ok {
Expand All @@ -941,10 +956,12 @@ func getExcerptLines(commit *git.Commit, filePath string, idxLeft, idxRight, chu
}
lineText := scanner.Text()
diffLine := &gitdiff.DiffLine{
LeftIdx: idxLeft + (line - idxRight) + 1,
RightIdx: line + 1,
Type: gitdiff.DiffLinePlain,
Content: " " + lineText,
LeftIdx: idxLeft + (line - idxRight) + 1,
RightIdx: line + 1,
Type: gitdiff.DiffLinePlain,
Content: " " + lineText,
HighlightContent: highlightedContent[line],
HasHighlightContent: true,
}
diffLines = append(diffLines, diffLine)
}
Expand Down
99 changes: 92 additions & 7 deletions services/gitdiff/gitdiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,15 @@ const (

// DiffLine represents a line difference in a DiffSection.
type DiffLine struct {
LeftIdx int
RightIdx int
Match int
Type DiffLineType
Content string
Comments []*issues_model.Comment
SectionInfo *DiffLineSectionInfo
LeftIdx int
RightIdx int
Match int
Type DiffLineType
Content string
Comments []*issues_model.Comment
SectionInfo *DiffLineSectionInfo
HighlightContent string
HasHighlightContent bool
}

// DiffLineSectionInfo represents diff line section meta data
Expand Down Expand Up @@ -306,13 +308,23 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine, loc
case DiffLineSection:
return getLineContent(diffLine.Content[1:], locale)
case DiffLineAdd:
if diffLine.HasHighlightContent {
status, content := charset.EscapeControlHTML(diffLine.HighlightContent, locale)
return DiffInline{EscapeStatus: status, Content: template.HTML(content)}
}

compareDiffLine = diffSection.GetLine(DiffLineDel, diffLine.RightIdx)
if compareDiffLine == nil {
return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:], locale)
}
diff1 = compareDiffLine.Content
diff2 = diffLine.Content
case DiffLineDel:
if diffLine.HasHighlightContent {
status, content := charset.EscapeControlHTML(diffLine.HighlightContent, locale)
return DiffInline{EscapeStatus: status, Content: template.HTML(content)}
}

compareDiffLine = diffSection.GetLine(DiffLineAdd, diffLine.LeftIdx)
if compareDiffLine == nil {
return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:], locale)
Expand All @@ -321,6 +333,11 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine, loc
diff2 = compareDiffLine.Content
default:
if strings.IndexByte(" +-", diffLine.Content[0]) > -1 {
if diffLine.HasHighlightContent {
status, content := charset.EscapeControlHTML(diffLine.HighlightContent, locale)
return DiffInline{EscapeStatus: status, Content: template.HTML(content)}
}

return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content[1:], locale)
}
return DiffInlineWithHighlightCode(diffSection.FileName, language, diffLine.Content, locale)
Expand Down Expand Up @@ -1064,13 +1081,46 @@ type DiffOptions struct {
// Passing the empty string as beforeCommitID returns a diff from the parent commit.
// The whitespaceBehavior is either an empty string or a git flag
func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff, error) {

loadCommitFileContent := func(commit *git.Commit, path, lang string) ([]string, string) {
entry, err := commit.GetTreeEntryByPath(path)
if err != nil {
log.Error("GetTreeEntryByPath: %v", err)
return nil, ""
}

f, err := entry.Blob().DataAsync()
if err != nil {
log.Error("Blob.DataAsync: %v", err)
return nil, ""
}

// TODO: maybe should limit file size?
content, err := io.ReadAll(f)
_ = f.Close()
if err != nil {
log.Error("io.ReadAll: %v", err)
return nil, ""
}

highlightedContent, lang, err := highlight.File(path, lang, content)
if err != nil {
log.Error("highlight.File: %v", err)
return nil, ""
}

return highlightedContent, lang
}

repoPath := gitRepo.Path

commit, err := gitRepo.GetCommit(opts.AfterCommitID)
if err != nil {
return nil, err
}

var beforeCommit *git.Commit

cmdDiff := git.NewCommand(gitRepo.Ctx)
if (len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == git.EmptySHA) && commit.ParentCount() == 0 {
cmdDiff.AddArguments("diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M").
Expand All @@ -1082,6 +1132,12 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
if len(actualBeforeCommitID) == 0 {
parentCommit, _ := commit.Parent(0)
actualBeforeCommitID = parentCommit.ID.String()
beforeCommit = parentCommit
} else {
beforeCommit, err = gitRepo.GetCommit(actualBeforeCommitID)
if err != nil {
return nil, err
}
}

cmdDiff.AddArguments("diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M").
Expand Down Expand Up @@ -1172,6 +1228,35 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
if tailSection != nil {
diffFile.Sections = append(diffFile.Sections, tailSection)
}

// render full file for edited file
if diffFile.Type != DiffFileChange || beforeCommit == nil {
continue
}

var newContent []string
oldContent, _ := loadCommitFileContent(beforeCommit, diffFile.OldName, diffFile.Language)
newContent, diffFile.Language = loadCommitFileContent(commit, diffFile.Name, diffFile.Language)

for _, diffSection := range diffFile.Sections {
for _, diffLine := range diffSection.Lines {
switch diffLine.Type {
case DiffLineAdd:
fallthrough
case DiffLinePlain:
if diffLine.RightIdx > 0 && diffLine.RightIdx <= len(newContent) {
diffLine.HighlightContent = newContent[diffLine.RightIdx-1]
diffLine.HasHighlightContent = true
}

case DiffLineDel:
if diffLine.LeftIdx > 0 && diffLine.LeftIdx <= len(oldContent) {
diffLine.HighlightContent = oldContent[diffLine.LeftIdx-1]
diffLine.HasHighlightContent = true
}
}
}
}
}

separator := "..."
Expand Down

0 comments on commit 5f93560

Please sign in to comment.