|
5 | 5 | package repo
|
6 | 6 |
|
7 | 7 | import (
|
| 8 | + "bufio" |
8 | 9 | "fmt"
|
| 10 | + "html" |
9 | 11 | "path"
|
| 12 | + "path/filepath" |
10 | 13 | "strings"
|
11 | 14 |
|
12 | 15 | "code.gitea.io/gitea/models"
|
13 | 16 | "code.gitea.io/gitea/modules/base"
|
14 | 17 | "code.gitea.io/gitea/modules/context"
|
15 | 18 | "code.gitea.io/gitea/modules/git"
|
| 19 | + "code.gitea.io/gitea/modules/highlight" |
16 | 20 | "code.gitea.io/gitea/modules/log"
|
17 | 21 | "code.gitea.io/gitea/modules/setting"
|
18 | 22 | "code.gitea.io/gitea/services/gitdiff"
|
19 | 23 | )
|
20 | 24 |
|
21 | 25 | const (
|
22 |
| - tplCompare base.TplName = "repo/diff/compare" |
| 26 | + tplCompare base.TplName = "repo/diff/compare" |
| 27 | + tplBlobExcerpt base.TplName = "repo/diff/blob_excerpt" |
23 | 28 | )
|
24 | 29 |
|
25 | 30 | // setPathsCompareContext sets context data for source and raw paths
|
@@ -423,3 +428,105 @@ func CompareDiff(ctx *context.Context) {
|
423 | 428 |
|
424 | 429 | ctx.HTML(200, tplCompare)
|
425 | 430 | }
|
| 431 | + |
| 432 | +// ExcerptBlob render blob excerpt conten |
| 433 | +func ExcerptBlob(ctx *context.Context) { |
| 434 | + commitID := ctx.Params("sha") |
| 435 | + lastLeft := ctx.QueryInt("last_left") |
| 436 | + lastRight := ctx.QueryInt("last_right") |
| 437 | + idxLeft := ctx.QueryInt("left") |
| 438 | + idxRight := ctx.QueryInt("right") |
| 439 | + leftHunkSize := ctx.QueryInt("left_hunk_size") |
| 440 | + rightHunkSize := ctx.QueryInt("right_hunk_size") |
| 441 | + anchor := ctx.Query("anchor") |
| 442 | + direction := ctx.Query("direction") |
| 443 | + filePath := ctx.Query("path") |
| 444 | + gitRepo := ctx.Repo.GitRepo |
| 445 | + chunkSize := 20 |
| 446 | + commit, err := gitRepo.GetCommit(commitID) |
| 447 | + if err != nil { |
| 448 | + ctx.Error(500, "GetCommit") |
| 449 | + return |
| 450 | + } |
| 451 | + section := &gitdiff.DiffSection{ |
| 452 | + Name: filePath, |
| 453 | + } |
| 454 | + if direction == "up" && (idxLeft-lastLeft) > chunkSize { |
| 455 | + idxLeft -= chunkSize |
| 456 | + idxRight -= chunkSize |
| 457 | + leftHunkSize += chunkSize |
| 458 | + rightHunkSize += chunkSize |
| 459 | + section.Lines, err = getExcerptLines(commit, filePath, idxLeft-1, idxRight-1, chunkSize) |
| 460 | + } else if direction == "down" && (idxLeft-lastLeft) > chunkSize { |
| 461 | + section.Lines, err = getExcerptLines(commit, filePath, lastLeft, lastRight, chunkSize) |
| 462 | + lastLeft += chunkSize |
| 463 | + lastRight += chunkSize |
| 464 | + } else { |
| 465 | + section.Lines, err = getExcerptLines(commit, filePath, lastLeft, lastRight, idxRight-lastRight-1) |
| 466 | + } |
| 467 | + if err != nil { |
| 468 | + ctx.Error(500, "getExcerptLines") |
| 469 | + return |
| 470 | + } |
| 471 | + if idxRight > lastRight { |
| 472 | + lineText := " " |
| 473 | + if rightHunkSize > 0 || leftHunkSize > 0 { |
| 474 | + lineText = fmt.Sprintf("@@ -%d,%d +%d,%d @@\n", idxLeft, leftHunkSize, idxRight, rightHunkSize) |
| 475 | + } |
| 476 | + lineText = html.EscapeString(lineText) |
| 477 | + lineSection := &gitdiff.DiffLine{ |
| 478 | + Type: gitdiff.DiffLineSection, |
| 479 | + Content: lineText, |
| 480 | + SectionInfo: &gitdiff.DiffLineSectionInfo{ |
| 481 | + Path: filePath, |
| 482 | + LastLeftIdx: lastLeft, |
| 483 | + LastRightIdx: lastRight, |
| 484 | + LeftIdx: idxLeft, |
| 485 | + RightIdx: idxRight, |
| 486 | + LeftHunkSize: leftHunkSize, |
| 487 | + RightHunkSize: rightHunkSize, |
| 488 | + }} |
| 489 | + if direction == "up" { |
| 490 | + section.Lines = append([]*gitdiff.DiffLine{lineSection}, section.Lines...) |
| 491 | + } else if direction == "down" { |
| 492 | + section.Lines = append(section.Lines, lineSection) |
| 493 | + } |
| 494 | + } |
| 495 | + ctx.Data["section"] = section |
| 496 | + ctx.Data["fileName"] = filePath |
| 497 | + ctx.Data["highlightClass"] = highlight.FileNameToHighlightClass(filepath.Base(filePath)) |
| 498 | + ctx.Data["AfterCommitID"] = commitID |
| 499 | + ctx.Data["Anchor"] = anchor |
| 500 | + ctx.HTML(200, tplBlobExcerpt) |
| 501 | +} |
| 502 | + |
| 503 | +func getExcerptLines(commit *git.Commit, filePath string, idxLeft int, idxRight int, chunkSize int) ([]*gitdiff.DiffLine, error) { |
| 504 | + blob, err := commit.Tree.GetBlobByPath(filePath) |
| 505 | + if err != nil { |
| 506 | + return nil, err |
| 507 | + } |
| 508 | + reader, err := blob.DataAsync() |
| 509 | + defer reader.Close() |
| 510 | + if err != nil { |
| 511 | + return nil, err |
| 512 | + } |
| 513 | + scanner := bufio.NewScanner(reader) |
| 514 | + var diffLines []*gitdiff.DiffLine |
| 515 | + for line := 0; line < idxRight+chunkSize; line++ { |
| 516 | + if ok := scanner.Scan(); !ok { |
| 517 | + break |
| 518 | + } |
| 519 | + if line < idxRight { |
| 520 | + continue |
| 521 | + } |
| 522 | + lineText := scanner.Text() |
| 523 | + diffLine := &gitdiff.DiffLine{ |
| 524 | + LeftIdx: idxLeft + (line - idxRight) + 1, |
| 525 | + RightIdx: line + 1, |
| 526 | + Type: gitdiff.DiffLinePlain, |
| 527 | + Content: " " + lineText, |
| 528 | + } |
| 529 | + diffLines = append(diffLines, diffLine) |
| 530 | + } |
| 531 | + return diffLines, nil |
| 532 | +} |
0 commit comments