Use full-file highlighting for diff sections (#36561)

* Fix #35252
* Fix #35999
* Improve diff rendering, don't add unnecessary "added"/"removed" tags for a full-line change
* Also fix a "space trimming" bug in #36539 and add tests
* Use chroma "SQL" lexer instead of "MySQL" to workaround a bug (35999)
This commit is contained in:
wxiaoguang
2026-02-10 11:29:28 +08:00
committed by GitHub
parent 269bc1b112
commit 8cc8150922
15 changed files with 391 additions and 192 deletions
+23 -89
View File
@@ -4,7 +4,6 @@
package repo
import (
"bufio"
gocontext "context"
"encoding/csv"
"errors"
@@ -744,13 +743,16 @@ func attachHiddenCommentIDs(section *gitdiff.DiffSection, lineComments map[int64
// ExcerptBlob render blob excerpt contents
func ExcerptBlob(ctx *context.Context) {
commitID := ctx.PathParam("sha")
lastLeft := ctx.FormInt("last_left")
lastRight := ctx.FormInt("last_right")
idxLeft := ctx.FormInt("left")
idxRight := ctx.FormInt("right")
leftHunkSize := ctx.FormInt("left_hunk_size")
rightHunkSize := ctx.FormInt("right_hunk_size")
direction := ctx.FormString("direction")
opts := gitdiff.BlobExcerptOptions{
LastLeft: ctx.FormInt("last_left"),
LastRight: ctx.FormInt("last_right"),
LeftIndex: ctx.FormInt("left"),
RightIndex: ctx.FormInt("right"),
LeftHunkSize: ctx.FormInt("left_hunk_size"),
RightHunkSize: ctx.FormInt("right_hunk_size"),
Direction: ctx.FormString("direction"),
Language: ctx.FormString("filelang"),
}
filePath := ctx.FormString("path")
gitRepo := ctx.Repo.GitRepo
@@ -770,61 +772,27 @@ func ExcerptBlob(ctx *context.Context) {
diffBlobExcerptData.BaseLink = ctx.Repo.RepoLink + "/wiki/blob_excerpt"
}
chunkSize := gitdiff.BlobExcerptChunkSize
commit, err := gitRepo.GetCommit(commitID)
if err != nil {
ctx.HTTPError(http.StatusInternalServerError, "GetCommit")
ctx.ServerError("GetCommit", err)
return
}
section := &gitdiff.DiffSection{
FileName: filePath,
}
if direction == "up" && (idxLeft-lastLeft) > chunkSize {
idxLeft -= chunkSize
idxRight -= chunkSize
leftHunkSize += chunkSize
rightHunkSize += chunkSize
section.Lines, err = getExcerptLines(commit, filePath, idxLeft-1, idxRight-1, chunkSize)
} else if direction == "down" && (idxLeft-lastLeft) > chunkSize {
section.Lines, err = getExcerptLines(commit, filePath, lastLeft, lastRight, chunkSize)
lastLeft += chunkSize
lastRight += chunkSize
} else {
offset := -1
if direction == "down" {
offset = 0
}
section.Lines, err = getExcerptLines(commit, filePath, lastLeft, lastRight, idxRight-lastRight+offset)
leftHunkSize = 0
rightHunkSize = 0
idxLeft = lastLeft
idxRight = lastRight
}
blob, err := commit.Tree.GetBlobByPath(filePath)
if err != nil {
ctx.HTTPError(http.StatusInternalServerError, "getExcerptLines")
ctx.ServerError("GetBlobByPath", err)
return
}
newLineSection := &gitdiff.DiffLine{
Type: gitdiff.DiffLineSection,
SectionInfo: &gitdiff.DiffLineSectionInfo{
Path: filePath,
LastLeftIdx: lastLeft,
LastRightIdx: lastRight,
LeftIdx: idxLeft,
RightIdx: idxRight,
LeftHunkSize: leftHunkSize,
RightHunkSize: rightHunkSize,
},
reader, err := blob.DataAsync()
if err != nil {
ctx.ServerError("DataAsync", err)
return
}
if newLineSection.GetExpandDirection() != "" {
newLineSection.Content = fmt.Sprintf("@@ -%d,%d +%d,%d @@\n", idxLeft, leftHunkSize, idxRight, rightHunkSize)
switch direction {
case "up":
section.Lines = append([]*gitdiff.DiffLine{newLineSection}, section.Lines...)
case "down":
section.Lines = append(section.Lines, newLineSection)
}
defer reader.Close()
section, err := gitdiff.BuildBlobExcerptDiffSection(filePath, reader, opts)
if err != nil {
ctx.ServerError("BuildBlobExcerptDiffSection", err)
return
}
diffBlobExcerptData.PullIssueIndex = ctx.FormInt64("pull_issue_index")
@@ -865,37 +833,3 @@ func ExcerptBlob(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplBlobExcerpt)
}
func getExcerptLines(commit *git.Commit, filePath string, idxLeft, idxRight, chunkSize int) ([]*gitdiff.DiffLine, error) {
blob, err := commit.Tree.GetBlobByPath(filePath)
if err != nil {
return nil, err
}
reader, err := blob.DataAsync()
if err != nil {
return nil, err
}
defer reader.Close()
scanner := bufio.NewScanner(reader)
var diffLines []*gitdiff.DiffLine
for line := 0; line < idxRight+chunkSize; line++ {
if ok := scanner.Scan(); !ok {
break
}
if line < idxRight {
continue
}
lineText := scanner.Text()
diffLine := &gitdiff.DiffLine{
LeftIdx: idxLeft + (line - idxRight) + 1,
RightIdx: line + 1,
Type: gitdiff.DiffLinePlain,
Content: " " + lineText,
}
diffLines = append(diffLines, diffLine)
}
if err = scanner.Err(); err != nil {
return nil, fmt.Errorf("getExcerptLines scan: %w", err)
}
return diffLines, nil
}