fix: full file highlighting for git diff with CR char (#38484)

fix #38481
This commit is contained in:
wxiaoguang
2026-07-16 19:36:46 +08:00
committed by GitHub
parent f15868d442
commit 875b2e8def
2 changed files with 20 additions and 1 deletions

View File

@@ -1285,6 +1285,8 @@ func getDiffBasic(ctx context.Context, gitRepo *git.Repository, opts *DiffOption
return nil, nil, nil, err
}
// HINT: GIT-DIFF-HIGHLIGHT-LINE-NUMBER: git doesn't treat CR(\r) as EOL, CR is just a plain char which can appear anywhere in the diff output
// Since we have to do full-file-highlighting for the diff result, we need to make sure the highlighted lines exactly match the git's diff output.
cmdDiff := gitcmd.NewCommand().
AddArguments("diff", "--src-prefix=\\a/", "--dst-prefix=\\b/").
AddArguments(opts.WhitespaceBehavior...).
@@ -1405,8 +1407,12 @@ func highlightCodeLines(name, lang string, sections []*DiffSection, isLeft bool,
if setting.Git.DisableDiffHighlight || len(rawContent) > MaxFullFileHighlightSizeLimit {
return nil
}
content := util.UnsafeBytesToString(charset.ToUTF8(rawContent, charset.ConvertOpts{}))
// HINT: GIT-DIFF-HIGHLIGHT-LINE-NUMBER: it should handle all CR(\r) before highlight to make line numbers match
if strings.Contains(content, "\r") {
content = strings.ReplaceAll(content, "\r\n", "\n")
content = strings.ReplaceAll(content, "\r", "␍")
}
lexer := highlight.DetectChromaLexerByFileName(name, lang)
highlightedNewContent := highlight.RenderCodeByLexer(lexer, content)
unsafeLines := highlight.UnsafeSplitHighlightedLines(highlightedNewContent)

View File

@@ -1143,6 +1143,19 @@ func TestHighlightCodeLines(t *testing.T) {
1: `<span class="n">b</span>` + nl,
}, ret)
})
t.Run("CharCR", func(t *testing.T) {
diffFile := &DiffFile{
Name: "a.txt",
Sections: []*DiffSection{
{
Lines: []*DiffLine{{LeftIdx: 1}, {LeftIdx: 2}},
},
},
}
ret := highlightCodeLinesForDiffFile(diffFile, true, []byte("a\rb\r\nc"))
assert.Equal(t, "a␍b\n", string(ret[0]))
assert.Equal(t, `c`, string(ret[1]))
})
}
func TestSyncUserSpecificDiff_UpdatedFiles(t *testing.T) {