mirror of
https://github.com/go-gitea/gitea.git
synced 2026-02-10 22:08:57 +00:00
* 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)
122 lines
3.5 KiB
Go
122 lines
3.5 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package gitdiff
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"html/template"
|
|
"io"
|
|
|
|
"code.gitea.io/gitea/modules/setting"
|
|
)
|
|
|
|
type BlobExcerptOptions struct {
|
|
LastLeft int
|
|
LastRight int
|
|
LeftIndex int
|
|
RightIndex int
|
|
LeftHunkSize int
|
|
RightHunkSize int
|
|
Direction string
|
|
Language string
|
|
}
|
|
|
|
func fillExcerptLines(section *DiffSection, filePath string, reader io.Reader, lang string, idxLeft, idxRight, chunkSize int) error {
|
|
buf := &bytes.Buffer{}
|
|
scanner := bufio.NewScanner(reader)
|
|
var diffLines []*DiffLine
|
|
for line := 0; line < idxRight+chunkSize; line++ {
|
|
if ok := scanner.Scan(); !ok {
|
|
break
|
|
}
|
|
lineText := scanner.Text()
|
|
if buf.Len()+len(lineText) < int(setting.UI.MaxDisplayFileSize) {
|
|
buf.WriteString(lineText)
|
|
buf.WriteByte('\n')
|
|
}
|
|
if line < idxRight {
|
|
continue
|
|
}
|
|
diffLine := &DiffLine{
|
|
LeftIdx: idxLeft + (line - idxRight) + 1,
|
|
RightIdx: line + 1,
|
|
Type: DiffLinePlain,
|
|
Content: " " + lineText,
|
|
}
|
|
diffLines = append(diffLines, diffLine)
|
|
}
|
|
if err := scanner.Err(); err != nil {
|
|
return fmt.Errorf("fillExcerptLines scan: %w", err)
|
|
}
|
|
section.Lines = diffLines
|
|
// DiffLinePlain always uses right lines
|
|
section.highlightedRightLines.value = highlightCodeLines(filePath, lang, []*DiffSection{section}, false /* right */, buf.Bytes())
|
|
return nil
|
|
}
|
|
|
|
func BuildBlobExcerptDiffSection(filePath string, reader io.Reader, opts BlobExcerptOptions) (*DiffSection, error) {
|
|
lastLeft, lastRight, idxLeft, idxRight := opts.LastLeft, opts.LastRight, opts.LeftIndex, opts.RightIndex
|
|
leftHunkSize, rightHunkSize, direction := opts.LeftHunkSize, opts.RightHunkSize, opts.Direction
|
|
language := opts.Language
|
|
|
|
chunkSize := BlobExcerptChunkSize
|
|
section := &DiffSection{
|
|
language: &diffVarMutable[string]{value: language},
|
|
highlightedLeftLines: &diffVarMutable[map[int]template.HTML]{},
|
|
highlightedRightLines: &diffVarMutable[map[int]template.HTML]{},
|
|
FileName: filePath,
|
|
}
|
|
var err error
|
|
if direction == "up" && (idxLeft-lastLeft) > chunkSize {
|
|
idxLeft -= chunkSize
|
|
idxRight -= chunkSize
|
|
leftHunkSize += chunkSize
|
|
rightHunkSize += chunkSize
|
|
err = fillExcerptLines(section, filePath, reader, language, idxLeft-1, idxRight-1, chunkSize)
|
|
} else if direction == "down" && (idxLeft-lastLeft) > chunkSize {
|
|
err = fillExcerptLines(section, filePath, reader, language, lastLeft, lastRight, chunkSize)
|
|
lastLeft += chunkSize
|
|
lastRight += chunkSize
|
|
} else {
|
|
offset := -1
|
|
if direction == "down" {
|
|
offset = 0
|
|
}
|
|
err = fillExcerptLines(section, filePath, reader, language, lastLeft, lastRight, idxRight-lastRight+offset)
|
|
leftHunkSize = 0
|
|
rightHunkSize = 0
|
|
idxLeft = lastLeft
|
|
idxRight = lastRight
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
newLineSection := &DiffLine{
|
|
Type: DiffLineSection,
|
|
SectionInfo: &DiffLineSectionInfo{
|
|
language: &diffVarMutable[string]{value: opts.Language},
|
|
Path: filePath,
|
|
LastLeftIdx: lastLeft,
|
|
LastRightIdx: lastRight,
|
|
LeftIdx: idxLeft,
|
|
RightIdx: idxRight,
|
|
LeftHunkSize: leftHunkSize,
|
|
RightHunkSize: rightHunkSize,
|
|
},
|
|
}
|
|
if newLineSection.GetExpandDirection() != "" {
|
|
newLineSection.Content = fmt.Sprintf("@@ -%d,%d +%d,%d @@\n", idxLeft, leftHunkSize, idxRight, rightHunkSize)
|
|
switch direction {
|
|
case "up":
|
|
section.Lines = append([]*DiffLine{newLineSection}, section.Lines...)
|
|
case "down":
|
|
section.Lines = append(section.Lines, newLineSection)
|
|
}
|
|
}
|
|
return section, nil
|
|
}
|