Skip to content

Commit 112c034

Browse files
committed
fix
1 parent 2ce6302 commit 112c034

11 files changed

Lines changed: 277 additions & 164 deletions

File tree

routers/web/repo/compare.go

Lines changed: 22 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package repo
55

66
import (
7-
"bufio"
87
gocontext "context"
98
"encoding/csv"
109
"errors"
@@ -744,13 +743,16 @@ func attachHiddenCommentIDs(section *gitdiff.DiffSection, lineComments map[int64
744743
// ExcerptBlob render blob excerpt contents
745744
func ExcerptBlob(ctx *context.Context) {
746745
commitID := ctx.PathParam("sha")
747-
lastLeft := ctx.FormInt("last_left")
748-
lastRight := ctx.FormInt("last_right")
749-
idxLeft := ctx.FormInt("left")
750-
idxRight := ctx.FormInt("right")
751-
leftHunkSize := ctx.FormInt("left_hunk_size")
752-
rightHunkSize := ctx.FormInt("right_hunk_size")
753-
direction := ctx.FormString("direction")
746+
opts := gitdiff.BlobExcerptOptions{
747+
LastLeft: ctx.FormInt("last_left"),
748+
LastRight: ctx.FormInt("last_right"),
749+
LeftIndex: ctx.FormInt("left"),
750+
RightIndex: ctx.FormInt("right"),
751+
LeftHunkSize: ctx.FormInt("left_hunk_size"),
752+
RightHunkSize: ctx.FormInt("right_hunk_size"),
753+
Direction: ctx.FormString("direction"),
754+
Language: ctx.FormString("filelang"),
755+
}
754756
filePath := ctx.FormString("path")
755757
gitRepo := ctx.Repo.GitRepo
756758

@@ -770,61 +772,27 @@ func ExcerptBlob(ctx *context.Context) {
770772
diffBlobExcerptData.BaseLink = ctx.Repo.RepoLink + "/wiki/blob_excerpt"
771773
}
772774

773-
chunkSize := gitdiff.BlobExcerptChunkSize
774775
commit, err := gitRepo.GetCommit(commitID)
775776
if err != nil {
776-
ctx.HTTPError(http.StatusInternalServerError, "GetCommit")
777+
ctx.ServerError("GetCommit", err)
777778
return
778779
}
779-
section := &gitdiff.DiffSection{
780-
FileName: filePath,
781-
}
782-
if direction == "up" && (idxLeft-lastLeft) > chunkSize {
783-
idxLeft -= chunkSize
784-
idxRight -= chunkSize
785-
leftHunkSize += chunkSize
786-
rightHunkSize += chunkSize
787-
section.Lines, err = getExcerptLines(commit, filePath, idxLeft-1, idxRight-1, chunkSize)
788-
} else if direction == "down" && (idxLeft-lastLeft) > chunkSize {
789-
section.Lines, err = getExcerptLines(commit, filePath, lastLeft, lastRight, chunkSize)
790-
lastLeft += chunkSize
791-
lastRight += chunkSize
792-
} else {
793-
offset := -1
794-
if direction == "down" {
795-
offset = 0
796-
}
797-
section.Lines, err = getExcerptLines(commit, filePath, lastLeft, lastRight, idxRight-lastRight+offset)
798-
leftHunkSize = 0
799-
rightHunkSize = 0
800-
idxLeft = lastLeft
801-
idxRight = lastRight
780+
blob, err := commit.Tree.GetBlobByPath(filePath)
781+
if err != nil {
782+
ctx.ServerError("GetBlobByPath", err)
783+
return
802784
}
785+
reader, err := blob.DataAsync()
803786
if err != nil {
804-
ctx.HTTPError(http.StatusInternalServerError, "getExcerptLines")
787+
ctx.ServerError("DataAsync", err)
805788
return
806789
}
790+
defer reader.Close()
807791

808-
newLineSection := &gitdiff.DiffLine{
809-
Type: gitdiff.DiffLineSection,
810-
SectionInfo: &gitdiff.DiffLineSectionInfo{
811-
Path: filePath,
812-
LastLeftIdx: lastLeft,
813-
LastRightIdx: lastRight,
814-
LeftIdx: idxLeft,
815-
RightIdx: idxRight,
816-
LeftHunkSize: leftHunkSize,
817-
RightHunkSize: rightHunkSize,
818-
},
819-
}
820-
if newLineSection.GetExpandDirection() != "" {
821-
newLineSection.Content = fmt.Sprintf("@@ -%d,%d +%d,%d @@\n", idxLeft, leftHunkSize, idxRight, rightHunkSize)
822-
switch direction {
823-
case "up":
824-
section.Lines = append([]*gitdiff.DiffLine{newLineSection}, section.Lines...)
825-
case "down":
826-
section.Lines = append(section.Lines, newLineSection)
827-
}
792+
section, err := gitdiff.BuildBlobExcerptDiffSection(filePath, reader, opts)
793+
if err != nil {
794+
ctx.ServerError("BuildBlobExcerptDiffSection", err)
795+
return
828796
}
829797

830798
diffBlobExcerptData.PullIssueIndex = ctx.FormInt64("pull_issue_index")
@@ -865,37 +833,3 @@ func ExcerptBlob(ctx *context.Context) {
865833

866834
ctx.HTML(http.StatusOK, tplBlobExcerpt)
867835
}
868-
869-
func getExcerptLines(commit *git.Commit, filePath string, idxLeft, idxRight, chunkSize int) ([]*gitdiff.DiffLine, error) {
870-
blob, err := commit.Tree.GetBlobByPath(filePath)
871-
if err != nil {
872-
return nil, err
873-
}
874-
reader, err := blob.DataAsync()
875-
if err != nil {
876-
return nil, err
877-
}
878-
defer reader.Close()
879-
scanner := bufio.NewScanner(reader)
880-
var diffLines []*gitdiff.DiffLine
881-
for line := 0; line < idxRight+chunkSize; line++ {
882-
if ok := scanner.Scan(); !ok {
883-
break
884-
}
885-
if line < idxRight {
886-
continue
887-
}
888-
lineText := scanner.Text()
889-
diffLine := &gitdiff.DiffLine{
890-
LeftIdx: idxLeft + (line - idxRight) + 1,
891-
RightIdx: line + 1,
892-
Type: gitdiff.DiffLinePlain,
893-
Content: " " + lineText,
894-
}
895-
diffLines = append(diffLines, diffLine)
896-
}
897-
if err = scanner.Err(); err != nil {
898-
return nil, fmt.Errorf("getExcerptLines scan: %w", err)
899-
}
900-
return diffLines, nil
901-
}

routers/web/repo/editor_preview.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ package repo
66
import (
77
"net/http"
88

9+
"code.gitea.io/gitea/modules/setting"
910
"code.gitea.io/gitea/services/context"
1011
files_service "code.gitea.io/gitea/services/repository/files"
1112
)
1213

1314
func DiffPreviewPost(ctx *context.Context) {
14-
content := ctx.FormString("content")
15+
newContent := ctx.FormString("content")
1516
treePath := files_service.CleanGitTreePath(ctx.Repo.TreePath)
1617
if treePath == "" {
1718
ctx.HTTPError(http.StatusBadRequest, "file name to diff is invalid")
@@ -27,7 +28,12 @@ func DiffPreviewPost(ctx *context.Context) {
2728
return
2829
}
2930

30-
diff, err := files_service.GetDiffPreview(ctx, ctx.Repo.Repository, ctx.Repo.BranchName, treePath, content)
31+
oldContent, err := entry.Blob().GetBlobContent(setting.UI.MaxDisplayFileSize)
32+
if err != nil {
33+
ctx.ServerError("GetBlobBytes", err)
34+
return
35+
}
36+
diff, err := files_service.GetDiffPreview(ctx, ctx.Repo.Repository, ctx.Repo.BranchName, treePath, oldContent, newContent)
3137
if err != nil {
3238
ctx.ServerError("GetDiffPreview", err)
3339
return

services/gitdiff/gitdiff.go

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ type DiffLine struct {
8181

8282
// DiffLineSectionInfo represents diff line section meta data
8383
type DiffLineSectionInfo struct {
84-
Path string
84+
Path string
85+
language *diffVarMutable[string] // it will be filled later, so it must be a pointer to the DiffFile.language
8586

8687
// These line "idx" are 1-based line numbers
8788
// Left/Right refer to the left/right side of the diff:
@@ -165,15 +166,19 @@ func (d *DiffLine) GetLineTypeMarker() string {
165166
}
166167

167168
func (d *DiffLine) getBlobExcerptQuery() string {
169+
language := ""
170+
if d.SectionInfo.language != nil {
171+
language = d.SectionInfo.language.value
172+
}
168173
query := fmt.Sprintf(
169174
"last_left=%d&last_right=%d&"+
170175
"left=%d&right=%d&"+
171176
"left_hunk_size=%d&right_hunk_size=%d&"+
172-
"path=%s",
177+
"path=%s&filelang=%s",
173178
d.SectionInfo.LastLeftIdx, d.SectionInfo.LastRightIdx,
174179
d.SectionInfo.LeftIdx, d.SectionInfo.RightIdx,
175180
d.SectionInfo.LeftHunkSize, d.SectionInfo.RightHunkSize,
176-
url.QueryEscape(d.SectionInfo.Path))
181+
url.QueryEscape(d.SectionInfo.Path), url.QueryEscape(language))
177182
return query
178183
}
179184

@@ -266,11 +271,12 @@ func FillHiddenCommentIDsForDiffLine(line *DiffLine, lineComments map[int64][]*i
266271
line.SectionInfo.HiddenCommentIDs = hiddenCommentIDs
267272
}
268273

269-
func getDiffLineSectionInfo(treePath, line string, lastLeftIdx, lastRightIdx int) *DiffLineSectionInfo {
274+
func newDiffLineSectionInfo(curFile *DiffFile, line string, lastLeftIdx, lastRightIdx int) *DiffLineSectionInfo {
270275
leftLine, leftHunk, rightLine, rightHunk := git.ParseDiffHunkString(line)
271276

272277
return &DiffLineSectionInfo{
273-
Path: treePath,
278+
Path: curFile.Name,
279+
language: &curFile.language,
274280
LastLeftIdx: lastLeftIdx,
275281
LastRightIdx: lastRightIdx,
276282
LeftIdx: leftLine,
@@ -290,7 +296,10 @@ func getLineContent(content string, locale translation.Locale) DiffInline {
290296

291297
// DiffSection represents a section of a DiffFile.
292298
type DiffSection struct {
293-
file *DiffFile
299+
language *diffVarMutable[string]
300+
highlightedLeftLines *diffVarMutable[map[int]template.HTML]
301+
highlightedRightLines *diffVarMutable[map[int]template.HTML]
302+
294303
FileName string
295304
Lines []*DiffLine
296305
}
@@ -339,9 +348,9 @@ func (diffSection *DiffSection) getDiffLineForRender(diffLineType DiffLineType,
339348
var fileLanguage string
340349
var highlightedLeftLines, highlightedRightLines map[int]template.HTML
341350
// when a "diff section" is manually prepared by ExcerptBlob, it doesn't have "file" information
342-
if diffSection.file != nil {
343-
fileLanguage = diffSection.file.Language
344-
highlightedLeftLines, highlightedRightLines = diffSection.file.highlightedLeftLines, diffSection.file.highlightedRightLines
351+
if diffSection.language != nil {
352+
fileLanguage = diffSection.language.value
353+
highlightedLeftLines, highlightedRightLines = diffSection.highlightedLeftLines.value, diffSection.highlightedRightLines.value
345354
}
346355

347356
var lineHTML template.HTML
@@ -392,6 +401,11 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine, loc
392401
}
393402
}
394403

404+
// diffVarMutable is a wrapper to make a variable mutable to be shared across structs
405+
type diffVarMutable[T any] struct {
406+
value T
407+
}
408+
395409
// DiffFile represents a file diff.
396410
type DiffFile struct {
397411
// only used internally to parse Ambiguous filenames
@@ -418,7 +432,6 @@ type DiffFile struct {
418432
IsIncompleteLineTooLong bool
419433

420434
// will be filled by the extra loop in GitDiffForRender
421-
Language string
422435
IsGenerated bool
423436
IsVendored bool
424437
SubmoduleDiffInfo *SubmoduleDiffInfo // IsSubmodule==true, then there must be a SubmoduleDiffInfo
@@ -430,9 +443,10 @@ type DiffFile struct {
430443
IsViewed bool // User specific
431444
HasChangedSinceLastReview bool // User specific
432445

433-
// for render purpose only, will be filled by the extra loop in GitDiffForRender
434-
highlightedLeftLines map[int]template.HTML
435-
highlightedRightLines map[int]template.HTML
446+
// for render purpose only, will be filled by the extra loop in GitDiffForRender, they are 0-based
447+
language diffVarMutable[string]
448+
highlightedLeftLines diffVarMutable[map[int]template.HTML]
449+
highlightedRightLines diffVarMutable[map[int]template.HTML]
436450
}
437451

438452
// GetType returns type of diff file.
@@ -470,6 +484,7 @@ func (diffFile *DiffFile) GetTailSectionAndLimitedContent(leftCommit, rightCommi
470484
Content: " ",
471485
SectionInfo: &DiffLineSectionInfo{
472486
Path: diffFile.Name,
487+
language: &diffFile.language,
473488
LastLeftIdx: lastLine.LeftIdx,
474489
LastRightIdx: lastLine.RightIdx,
475490
LeftIdx: leftLineCount,
@@ -907,6 +922,14 @@ func skipToNextDiffHead(input *bufio.Reader) (line string, err error) {
907922
return line, err
908923
}
909924

925+
func newDiffSectionForDiffFile(curFile *DiffFile) *DiffSection {
926+
return &DiffSection{
927+
language: &curFile.language,
928+
highlightedLeftLines: &curFile.highlightedLeftLines,
929+
highlightedRightLines: &curFile.highlightedRightLines,
930+
}
931+
}
932+
910933
func parseHunks(ctx context.Context, curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio.Reader) (lineBytes []byte, isFragment bool, err error) {
911934
sb := strings.Builder{}
912935

@@ -964,12 +987,12 @@ func parseHunks(ctx context.Context, curFile *DiffFile, maxLines, maxLineCharact
964987
line := sb.String()
965988

966989
// Create a new section to represent this hunk
967-
curSection = &DiffSection{file: curFile}
990+
curSection = newDiffSectionForDiffFile(curFile)
968991
lastLeftIdx = -1
969992
curFile.Sections = append(curFile.Sections, curSection)
970993

971994
// FIXME: the "-1" can't be right, these "line idx" are all 1-based, maybe there are other bugs that covers this bug.
972-
lineSectionInfo := getDiffLineSectionInfo(curFile.Name, line, leftLine-1, rightLine-1)
995+
lineSectionInfo := newDiffLineSectionInfo(curFile, line, leftLine-1, rightLine-1)
973996
diffLine := &DiffLine{
974997
Type: DiffLineSection,
975998
Content: line,
@@ -1004,7 +1027,7 @@ func parseHunks(ctx context.Context, curFile *DiffFile, maxLines, maxLineCharact
10041027
rightLine++
10051028
if curSection == nil {
10061029
// Create a new section to represent this hunk
1007-
curSection = &DiffSection{file: curFile}
1030+
curSection = newDiffSectionForDiffFile(curFile)
10081031
curFile.Sections = append(curFile.Sections, curSection)
10091032
lastLeftIdx = -1
10101033
}
@@ -1037,7 +1060,7 @@ func parseHunks(ctx context.Context, curFile *DiffFile, maxLines, maxLineCharact
10371060
}
10381061
if curSection == nil {
10391062
// Create a new section to represent this hunk
1040-
curSection = &DiffSection{file: curFile}
1063+
curSection = newDiffSectionForDiffFile(curFile)
10411064
curFile.Sections = append(curFile.Sections, curSection)
10421065
lastLeftIdx = -1
10431066
}
@@ -1064,7 +1087,7 @@ func parseHunks(ctx context.Context, curFile *DiffFile, maxLines, maxLineCharact
10641087
lastLeftIdx = -1
10651088
if curSection == nil {
10661089
// Create a new section to represent this hunk
1067-
curSection = &DiffSection{file: curFile}
1090+
curSection = newDiffSectionForDiffFile(curFile)
10681091
curFile.Sections = append(curFile.Sections, curSection)
10691092
}
10701093
curSection.Lines = append(curSection.Lines, diffLine)
@@ -1309,7 +1332,7 @@ func GetDiffForRender(ctx context.Context, repoLink string, gitRepo *git.Reposit
13091332
isVendored, isGenerated = attrs.GetVendored(), attrs.GetGenerated()
13101333
language := attrs.GetLanguage()
13111334
if language.Has() {
1312-
diffFile.Language = language.Value()
1335+
diffFile.language.value = language.Value()
13131336
}
13141337
attrDiff = attrs.Get(attribute.Diff).ToString()
13151338
}
@@ -1336,24 +1359,33 @@ func GetDiffForRender(ctx context.Context, repoLink string, gitRepo *git.Reposit
13361359
shouldFullFileHighlight := !setting.Git.DisableDiffHighlight && attrDiff.Value() == ""
13371360
if shouldFullFileHighlight {
13381361
if limitedContent.LeftContent != nil && limitedContent.LeftContent.buf.Len() < MaxDiffHighlightEntireFileSize {
1339-
diffFile.highlightedLeftLines = highlightCodeLines(diffFile, true /* left */, limitedContent.LeftContent.buf.Bytes())
1362+
diffFile.highlightedLeftLines.value = highlightCodeLinesForDiffFile(diffFile, true /* left */, limitedContent.LeftContent.buf.Bytes())
13401363
}
13411364
if limitedContent.RightContent != nil && limitedContent.RightContent.buf.Len() < MaxDiffHighlightEntireFileSize {
1342-
diffFile.highlightedRightLines = highlightCodeLines(diffFile, false /* right */, limitedContent.RightContent.buf.Bytes())
1365+
diffFile.highlightedRightLines.value = highlightCodeLinesForDiffFile(diffFile, false /* right */, limitedContent.RightContent.buf.Bytes())
13431366
}
13441367
}
13451368
}
13461369

13471370
return diff, nil
13481371
}
13491372

1350-
func highlightCodeLines(diffFile *DiffFile, isLeft bool, rawContent []byte) map[int]template.HTML {
1373+
func FillDiffFileHighlightLinesByContent(diffFile *DiffFile, left, right []byte) {
1374+
diffFile.highlightedLeftLines.value = highlightCodeLinesForDiffFile(diffFile, true /* left */, left)
1375+
diffFile.highlightedRightLines.value = highlightCodeLinesForDiffFile(diffFile, false /* right */, right)
1376+
}
1377+
1378+
func highlightCodeLinesForDiffFile(diffFile *DiffFile, isLeft bool, rawContent []byte) map[int]template.HTML {
1379+
return highlightCodeLines(diffFile.Name, diffFile.language.value, diffFile.Sections, isLeft, rawContent)
1380+
}
1381+
1382+
func highlightCodeLines(name, lang string, sections []*DiffSection, isLeft bool, rawContent []byte) map[int]template.HTML {
13511383
content := util.UnsafeBytesToString(charset.ToUTF8(rawContent, charset.ConvertOpts{}))
1352-
highlightedNewContent, _ := highlight.RenderCodeFast(diffFile.Name, diffFile.Language, content)
1384+
highlightedNewContent, _ := highlight.RenderCodeFast(name, lang, content)
13531385
unsafeLines := highlight.UnsafeSplitHighlightedLines(highlightedNewContent)
13541386
lines := make(map[int]template.HTML, len(unsafeLines))
13551387
// only save the highlighted lines we need, but not the whole file, to save memory
1356-
for _, sec := range diffFile.Sections {
1388+
for _, sec := range sections {
13571389
for _, ln := range sec.Lines {
13581390
lineIdx := ln.LeftIdx
13591391
if !isLeft {

0 commit comments

Comments
 (0)