@@ -14,6 +14,7 @@ import (
1414 "net/http"
1515 "net/url"
1616 "path/filepath"
17+ "sort"
1718 "strings"
1819
1920 "code.gitea.io/gitea/models/db"
@@ -43,6 +44,7 @@ import (
4344 "code.gitea.io/gitea/services/context/upload"
4445 "code.gitea.io/gitea/services/gitdiff"
4546 pull_service "code.gitea.io/gitea/services/pull"
47+ user_service "code.gitea.io/gitea/services/user"
4648)
4749
4850const (
@@ -638,6 +640,11 @@ func PrepareCompareDiff(
638640 }
639641 ctx .Data ["DiffShortStat" ] = diffShortStat
640642 ctx .Data ["Diff" ] = diff
643+ ctx .Data ["DiffBlobExcerptData" ] = & gitdiff.DiffBlobExcerptData {
644+ BaseLink : ci .HeadRepo .Link () + "/blob_excerpt" ,
645+ DiffStyle : ctx .FormString ("style" ),
646+ AfterCommitID : headCommitID ,
647+ }
641648 ctx .Data ["DiffNotAvailable" ] = diffShortStat .NumFiles == 0
642649
643650 if ! fileOnly {
@@ -865,6 +872,28 @@ func CompareDiff(ctx *context.Context) {
865872 ctx .HTML (http .StatusOK , tplCompare )
866873}
867874
875+ // attachCommentsToLines attaches comments to their corresponding diff lines
876+ func attachCommentsToLines (section * gitdiff.DiffSection , lineComments map [int64 ][]* issues_model.Comment ) {
877+ for _ , line := range section .Lines {
878+ if comments , ok := lineComments [int64 (line .LeftIdx * - 1 )]; ok {
879+ line .Comments = append (line .Comments , comments ... )
880+ }
881+ if comments , ok := lineComments [int64 (line .RightIdx )]; ok {
882+ line .Comments = append (line .Comments , comments ... )
883+ }
884+ sort .SliceStable (line .Comments , func (i , j int ) bool {
885+ return line .Comments [i ].CreatedUnix < line .Comments [j ].CreatedUnix
886+ })
887+ }
888+ }
889+
890+ // attachHiddenCommentIDs calculates and attaches hidden comment IDs to expand buttons
891+ func attachHiddenCommentIDs (section * gitdiff.DiffSection , lineComments map [int64 ][]* issues_model.Comment ) {
892+ for _ , line := range section .Lines {
893+ gitdiff .FillHiddenCommentIDsForDiffLine (line , lineComments )
894+ }
895+ }
896+
868897// ExcerptBlob render blob excerpt contents
869898func ExcerptBlob (ctx * context.Context ) {
870899 commitID := ctx .PathParam ("sha" )
@@ -874,19 +903,26 @@ func ExcerptBlob(ctx *context.Context) {
874903 idxRight := ctx .FormInt ("right" )
875904 leftHunkSize := ctx .FormInt ("left_hunk_size" )
876905 rightHunkSize := ctx .FormInt ("right_hunk_size" )
877- anchor := ctx .FormString ("anchor" )
878906 direction := ctx .FormString ("direction" )
879907 filePath := ctx .FormString ("path" )
880908 gitRepo := ctx .Repo .GitRepo
909+
910+ diffBlobExcerptData := & gitdiff.DiffBlobExcerptData {
911+ BaseLink : ctx .Repo .RepoLink + "/blob_excerpt" ,
912+ DiffStyle : ctx .FormString ("style" ),
913+ AfterCommitID : commitID ,
914+ }
915+
881916 if ctx .Data ["PageIsWiki" ] == true {
882917 var err error
883- gitRepo , err = gitrepo .OpenRepository (ctx , ctx .Repo .Repository .WikiStorageRepo ())
918+ gitRepo , err = gitrepo .RepositoryFromRequestContextOrOpen (ctx , ctx .Repo .Repository .WikiStorageRepo ())
884919 if err != nil {
885920 ctx .ServerError ("OpenRepository" , err )
886921 return
887922 }
888- defer gitRepo . Close ()
923+ diffBlobExcerptData . BaseLink = ctx . Repo . RepoLink + "/wiki/blob_excerpt"
889924 }
925+
890926 chunkSize := gitdiff .BlobExcerptChunkSize
891927 commit , err := gitRepo .GetCommit (commitID )
892928 if err != nil {
@@ -947,10 +983,43 @@ func ExcerptBlob(ctx *context.Context) {
947983 section .Lines = append (section .Lines , lineSection )
948984 }
949985 }
986+
987+ diffBlobExcerptData .PullIssueIndex = ctx .FormInt64 ("pull_issue_index" )
988+ if diffBlobExcerptData .PullIssueIndex > 0 {
989+ if ! ctx .Repo .CanRead (unit .TypePullRequests ) {
990+ ctx .NotFound (nil )
991+ return
992+ }
993+
994+ issue , err := issues_model .GetIssueByIndex (ctx , ctx .Repo .Repository .ID , diffBlobExcerptData .PullIssueIndex )
995+ if err != nil {
996+ log .Error ("GetIssueByIndex error: %v" , err )
997+ } else if issue .IsPull {
998+ // FIXME: DIFF-CONVERSATION-DATA: the following data assignment is fragile
999+ ctx .Data ["Issue" ] = issue
1000+ ctx .Data ["CanBlockUser" ] = func (blocker , blockee * user_model.User ) bool {
1001+ return user_service .CanBlockUser (ctx , ctx .Doer , blocker , blockee )
1002+ }
1003+ // and "diff/comment_form.tmpl" (reply comment) needs them
1004+ ctx .Data ["PageIsPullFiles" ] = true
1005+ ctx .Data ["AfterCommitID" ] = diffBlobExcerptData .AfterCommitID
1006+
1007+ allComments , err := issues_model .FetchCodeComments (ctx , issue , ctx .Doer , ctx .FormBool ("show_outdated" ))
1008+ if err != nil {
1009+ log .Error ("FetchCodeComments error: %v" , err )
1010+ } else {
1011+ if lineComments , ok := allComments [filePath ]; ok {
1012+ attachCommentsToLines (section , lineComments )
1013+ attachHiddenCommentIDs (section , lineComments )
1014+ }
1015+ }
1016+ }
1017+ }
1018+
9501019 ctx .Data ["section" ] = section
9511020 ctx .Data ["FileNameHash" ] = git .HashFilePathForWebUI (filePath )
952- ctx .Data ["AfterCommitID " ] = commitID
953- ctx . Data [ "Anchor" ] = anchor
1021+ ctx .Data ["DiffBlobExcerptData " ] = diffBlobExcerptData
1022+
9541023 ctx .HTML (http .StatusOK , tplBlobExcerpt )
9551024}
9561025
0 commit comments