From 875b2e8defa6943ccd2c141efae6ffd6015fb13a Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Thu, 16 Jul 2026 19:36:46 +0800 Subject: [PATCH] fix: full file highlighting for git diff with CR char (#38484) fix #38481 --- services/gitdiff/gitdiff.go | 8 +++++++- services/gitdiff/gitdiff_test.go | 13 +++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 0b02ec2aa42..bd23295b6e7 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -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) diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index fd61a09972b..ebe5fc905e5 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -1143,6 +1143,19 @@ func TestHighlightCodeLines(t *testing.T) { 1: `b` + 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) {