aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2024-12-07 20:39:35 -0800
committerGitHub <noreply@github.com>2024-12-08 04:39:35 +0000
commitcd7bf77b2f709f9e95b98fc938f873839f76ff91 (patch)
treec465818444098bcacf75e0804163aa8d78b17037
parentad994780af48e2aff27b0e7e496fd559dc0fe3fc (diff)
downloadgitea-cd7bf77b2f709f9e95b98fc938f873839f76ff91.tar.gz
gitea-cd7bf77b2f709f9e95b98fc938f873839f76ff91.zip
Split issue/pull view router function as multiple smaller functions (#32749)
This PR splits issue/pull view function into multiple smaller functions. It also removed duplicated branches load.
-rw-r--r--routers/web/repo/issue_view.go616
-rw-r--r--routers/web/repo/pull.go38
2 files changed, 356 insertions, 298 deletions
diff --git a/routers/web/repo/issue_view.go b/routers/web/repo/issue_view.go
index 54ff36db49..09b57f4e78 100644
--- a/routers/web/repo/issue_view.go
+++ b/routers/web/repo/issue_view.go
@@ -325,14 +325,6 @@ func ViewIssue(ctx *context.Context) {
ctx.Data["NewIssueChooseTemplate"] = issue_service.HasTemplatesOrContactLinks(ctx.Repo.Repository, ctx.Repo.GitRepo)
}
- if issue.IsPull && !ctx.Repo.CanRead(unit.TypeIssues) {
- ctx.Data["IssueDependencySearchType"] = "pulls"
- } else if !issue.IsPull && !ctx.Repo.CanRead(unit.TypePullRequests) {
- ctx.Data["IssueDependencySearchType"] = "issues"
- } else {
- ctx.Data["IssueDependencySearchType"] = "all"
- }
-
ctx.Data["IsProjectsEnabled"] = ctx.Repo.CanRead(unit.TypeProjects)
ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled
upload.AddUploadContext(ctx, "comment")
@@ -349,54 +341,217 @@ func ViewIssue(ctx *context.Context) {
ctx.Data["Title"] = fmt.Sprintf("#%d - %s", issue.Index, emoji.ReplaceAliases(issue.Title))
- iw := new(issues_model.IssueWatch)
- if ctx.Doer != nil {
- iw.UserID = ctx.Doer.ID
- iw.IssueID = issue.ID
- iw.IsWatching, err = issues_model.CheckIssueWatch(ctx, ctx.Doer, issue)
- if err != nil {
- ctx.ServerError("CheckIssueWatch", err)
+ if ctx.IsSigned {
+ // Update issue-user.
+ if err = activities_model.SetIssueReadBy(ctx, issue.ID, ctx.Doer.ID); err != nil {
+ ctx.ServerError("ReadBy", err)
return
}
}
- ctx.Data["IssueWatch"] = iw
- rctx := renderhelper.NewRenderContextRepoComment(ctx, ctx.Repo.Repository)
- issue.RenderedContent, err = markdown.RenderString(rctx, issue.Content)
- if err != nil {
- ctx.ServerError("RenderString", err)
+
+ pageMetaData := retrieveRepoIssueMetaData(ctx, ctx.Repo.Repository, issue, issue.IsPull)
+ if ctx.Written() {
return
}
+ pageMetaData.LabelsData.SetSelectedLabels(issue.Labels)
- repo := ctx.Repo.Repository
+ prepareFuncs := []func(*context.Context, *issues_model.Issue){
+ prepareIssueViewContent,
+ func(ctx *context.Context, issue *issues_model.Issue) {
+ preparePullViewPullInfo(ctx, issue)
+ },
+ prepareIssueViewCommentsAndSidebarParticipants,
+ preparePullViewReviewAndMerge,
+ prepareIssueViewSidebarWatch,
+ prepareIssueViewSidebarTimeTracker,
+ prepareIssueViewSidebarDependency,
+ prepareIssueViewSidebarPin,
+ }
+
+ for _, prepareFunc := range prepareFuncs {
+ prepareFunc(ctx, issue)
+ if ctx.Written() {
+ return
+ }
+ }
// Get more information if it's a pull request.
if issue.IsPull {
if issue.PullRequest.HasMerged {
ctx.Data["DisableStatusChange"] = issue.PullRequest.HasMerged
- PrepareMergedViewPullInfo(ctx, issue)
} else {
- PrepareViewPullInfo(ctx, issue)
ctx.Data["DisableStatusChange"] = ctx.Data["IsPullRequestBroken"] == true && issue.IsClosed
}
- if ctx.Written() {
+ }
+
+ ctx.Data["Reference"] = issue.Ref
+ ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login?redirect_to=" + url.QueryEscape(ctx.Data["Link"].(string))
+ ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.Doer.ID)
+ ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
+ ctx.Data["HasProjectsWritePermission"] = ctx.Repo.CanWrite(unit.TypeProjects)
+ ctx.Data["IsRepoAdmin"] = ctx.IsSigned && (ctx.Repo.IsAdmin() || ctx.Doer.IsAdmin)
+ ctx.Data["LockReasons"] = setting.Repository.Issue.LockReasons
+ ctx.Data["RefEndName"] = git.RefName(issue.Ref).ShortName()
+
+ tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
+ if err != nil {
+ ctx.ServerError("GetTagNamesByRepoID", err)
+ return
+ }
+ ctx.Data["Tags"] = tags
+
+ ctx.Data["CanBlockUser"] = func(blocker, blockee *user_model.User) bool {
+ return user_service.CanBlockUser(ctx, ctx.Doer, blocker, blockee)
+ }
+
+ ctx.HTML(http.StatusOK, tplIssueView)
+}
+
+func prepareIssueViewSidebarDependency(ctx *context.Context, issue *issues_model.Issue) {
+ if issue.IsPull && !ctx.Repo.CanRead(unit.TypeIssues) {
+ ctx.Data["IssueDependencySearchType"] = "pulls"
+ } else if !issue.IsPull && !ctx.Repo.CanRead(unit.TypePullRequests) {
+ ctx.Data["IssueDependencySearchType"] = "issues"
+ } else {
+ ctx.Data["IssueDependencySearchType"] = "all"
+ }
+
+ // Check if the user can use the dependencies
+ ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx, ctx.Doer, issue.IsPull)
+
+ // check if dependencies can be created across repositories
+ ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies
+
+ // Get Dependencies
+ blockedBy, err := issue.BlockedByDependencies(ctx, db.ListOptions{})
+ if err != nil {
+ ctx.ServerError("BlockedByDependencies", err)
+ return
+ }
+ ctx.Data["BlockedByDependencies"], ctx.Data["BlockedByDependenciesNotPermitted"] = checkBlockedByIssues(ctx, blockedBy)
+ if ctx.Written() {
+ return
+ }
+
+ blocking, err := issue.BlockingDependencies(ctx)
+ if err != nil {
+ ctx.ServerError("BlockingDependencies", err)
+ return
+ }
+
+ ctx.Data["BlockingDependencies"], ctx.Data["BlockingDependenciesNotPermitted"] = checkBlockedByIssues(ctx, blocking)
+}
+
+func preparePullViewSigning(ctx *context.Context, issue *issues_model.Issue) {
+ if !issue.IsPull {
+ return
+ }
+ pull := issue.PullRequest
+ ctx.Data["WillSign"] = false
+ if ctx.Doer != nil {
+ sign, key, _, err := asymkey_service.SignMerge(ctx, pull, ctx.Doer, pull.BaseRepo.RepoPath(), pull.BaseBranch, pull.GetGitRefName())
+ ctx.Data["WillSign"] = sign
+ ctx.Data["SigningKey"] = key
+ if err != nil {
+ if asymkey_service.IsErrWontSign(err) {
+ ctx.Data["WontSignReason"] = err.(*asymkey_service.ErrWontSign).Reason
+ } else {
+ ctx.Data["WontSignReason"] = "error"
+ log.Error("Error whilst checking if could sign pr %d in repo %s. Error: %v", pull.ID, pull.BaseRepo.FullName(), err)
+ }
+ }
+ } else {
+ ctx.Data["WontSignReason"] = "not_signed_in"
+ }
+}
+
+func prepareIssueViewSidebarWatch(ctx *context.Context, issue *issues_model.Issue) {
+ iw := new(issues_model.IssueWatch)
+ if ctx.Doer != nil {
+ iw.UserID = ctx.Doer.ID
+ iw.IssueID = issue.ID
+ var err error
+ iw.IsWatching, err = issues_model.CheckIssueWatch(ctx, ctx.Doer, issue)
+ if err != nil {
+ ctx.ServerError("CheckIssueWatch", err)
return
}
}
+ ctx.Data["IssueWatch"] = iw
+}
- pageMetaData := retrieveRepoIssueMetaData(ctx, repo, issue, issue.IsPull)
- if ctx.Written() {
+func prepareIssueViewSidebarTimeTracker(ctx *context.Context, issue *issues_model.Issue) {
+ if !ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
return
}
- pageMetaData.LabelsData.SetSelectedLabels(issue.Labels)
if ctx.IsSigned {
- // Update issue-user.
- if err = activities_model.SetIssueReadBy(ctx, issue.ID, ctx.Doer.ID); err != nil {
- ctx.ServerError("ReadBy", err)
+ // Deal with the stopwatch
+ ctx.Data["IsStopwatchRunning"] = issues_model.StopwatchExists(ctx, ctx.Doer.ID, issue.ID)
+ if !ctx.Data["IsStopwatchRunning"].(bool) {
+ exists, _, swIssue, err := issues_model.HasUserStopwatch(ctx, ctx.Doer.ID)
+ if err != nil {
+ ctx.ServerError("HasUserStopwatch", err)
+ return
+ }
+ ctx.Data["HasUserStopwatch"] = exists
+ if exists {
+ // Add warning if the user has already a stopwatch
+ // Add link to the issue of the already running stopwatch
+ ctx.Data["OtherStopwatchURL"] = swIssue.Link()
+ }
+ }
+ ctx.Data["CanUseTimetracker"] = ctx.Repo.CanUseTimetracker(ctx, issue, ctx.Doer)
+ } else {
+ ctx.Data["CanUseTimetracker"] = false
+ }
+ var err error
+ if ctx.Data["WorkingUsers"], err = issues_model.TotalTimesForEachUser(ctx, &issues_model.FindTrackedTimesOptions{IssueID: issue.ID}); err != nil {
+ ctx.ServerError("TotalTimesForEachUser", err)
+ return
+ }
+}
+
+func preparePullViewDeleteBranch(ctx *context.Context, issue *issues_model.Issue, canDelete bool) {
+ if !issue.IsPull {
+ return
+ }
+ pull := issue.PullRequest
+ isPullBranchDeletable := canDelete &&
+ pull.HeadRepo != nil &&
+ git.IsBranchExist(ctx, pull.HeadRepo.RepoPath(), pull.HeadBranch) &&
+ (!pull.HasMerged || ctx.Data["HeadBranchCommitID"] == ctx.Data["PullHeadCommitID"])
+
+ if isPullBranchDeletable && pull.HasMerged {
+ exist, err := issues_model.HasUnmergedPullRequestsByHeadInfo(ctx, pull.HeadRepoID, pull.HeadBranch)
+ if err != nil {
+ ctx.ServerError("HasUnmergedPullRequestsByHeadInfo", err)
return
}
+
+ isPullBranchDeletable = !exist
}
+ ctx.Data["IsPullBranchDeletable"] = isPullBranchDeletable
+}
+func prepareIssueViewSidebarPin(ctx *context.Context, issue *issues_model.Issue) {
+ var pinAllowed bool
+ if !issue.IsPinned() {
+ var err error
+ pinAllowed, err = issues_model.IsNewPinAllowed(ctx, issue.RepoID, issue.IsPull)
+ if err != nil {
+ ctx.ServerError("IsNewPinAllowed", err)
+ return
+ }
+ } else {
+ pinAllowed = true
+ }
+
+ ctx.Data["NewPinAllowed"] = pinAllowed
+ ctx.Data["PinEnabled"] = setting.Repository.Issue.MaxPinned != 0
+}
+
+func prepareIssueViewCommentsAndSidebarParticipants(ctx *context.Context, issue *issues_model.Issue) {
var (
role issues_model.RoleDescriptor
ok bool
@@ -404,45 +559,9 @@ func ViewIssue(ctx *context.Context) {
comment *issues_model.Comment
participants = make([]*user_model.User, 1, 10)
latestCloseCommentID int64
+ err error
)
- if ctx.Repo.Repository.IsTimetrackerEnabled(ctx) {
- if ctx.IsSigned {
- // Deal with the stopwatch
- ctx.Data["IsStopwatchRunning"] = issues_model.StopwatchExists(ctx, ctx.Doer.ID, issue.ID)
- if !ctx.Data["IsStopwatchRunning"].(bool) {
- var exists bool
- var swIssue *issues_model.Issue
- if exists, _, swIssue, err = issues_model.HasUserStopwatch(ctx, ctx.Doer.ID); err != nil {
- ctx.ServerError("HasUserStopwatch", err)
- return
- }
- ctx.Data["HasUserStopwatch"] = exists
- if exists {
- // Add warning if the user has already a stopwatch
- // Add link to the issue of the already running stopwatch
- ctx.Data["OtherStopwatchURL"] = swIssue.Link()
- }
- }
- ctx.Data["CanUseTimetracker"] = ctx.Repo.CanUseTimetracker(ctx, issue, ctx.Doer)
- } else {
- ctx.Data["CanUseTimetracker"] = false
- }
- if ctx.Data["WorkingUsers"], err = issues_model.TotalTimesForEachUser(ctx, &issues_model.FindTrackedTimesOptions{IssueID: issue.ID}); err != nil {
- ctx.ServerError("TotalTimesForEachUser", err)
- return
- }
- }
- // Check if the user can use the dependencies
- ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx, ctx.Doer, issue.IsPull)
-
- // check if dependencies can be created across repositories
- ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies
-
- if issue.ShowRole, err = roleDescriptor(ctx, repo, issue.Poster, issue, issue.HasOriginalAuthor()); err != nil {
- ctx.ServerError("roleDescriptor", err)
- return
- }
marked[issue.PosterID] = issue.ShowRole
// Render comments and fetch participants.
@@ -461,7 +580,7 @@ func ViewIssue(ctx *context.Context) {
comment.Issue = issue
if comment.Type == issues_model.CommentTypeComment || comment.Type == issues_model.CommentTypeReview {
- rctx = renderhelper.NewRenderContextRepoComment(ctx, repo)
+ rctx := renderhelper.NewRenderContextRepoComment(ctx, issue.Repo)
comment.RenderedContent, err = markdown.RenderString(rctx, comment.Content)
if err != nil {
ctx.ServerError("RenderString", err)
@@ -474,7 +593,7 @@ func ViewIssue(ctx *context.Context) {
continue
}
- comment.ShowRole, err = roleDescriptor(ctx, repo, comment.Poster, issue, comment.HasOriginalAuthor())
+ comment.ShowRole, err = roleDescriptor(ctx, issue.Repo, comment.Poster, issue, comment.HasOriginalAuthor())
if err != nil {
ctx.ServerError("roleDescriptor", err)
return
@@ -537,7 +656,7 @@ func ViewIssue(ctx *context.Context) {
}
}
} else if comment.Type.HasContentSupport() {
- rctx = renderhelper.NewRenderContextRepoComment(ctx, repo)
+ rctx := renderhelper.NewRenderContextRepoComment(ctx, issue.Repo)
comment.RenderedContent, err = markdown.RenderString(rctx, comment.Content)
if err != nil {
ctx.ServerError("RenderString", err)
@@ -572,7 +691,7 @@ func ViewIssue(ctx *context.Context) {
continue
}
- c.ShowRole, err = roleDescriptor(ctx, repo, c.Poster, issue, c.HasOriginalAuthor())
+ c.ShowRole, err = roleDescriptor(ctx, issue.Repo, c.Poster, issue, c.HasOriginalAuthor())
if err != nil {
ctx.ServerError("roleDescriptor", err)
return
@@ -629,266 +748,201 @@ func ViewIssue(ctx *context.Context) {
// Combine multiple label assignments into a single comment
combineLabelComments(issue)
+ var hiddenCommentTypes *big.Int
+ if ctx.IsSigned {
+ val, err := user_model.GetUserSetting(ctx, ctx.Doer.ID, user_model.SettingsKeyHiddenCommentTypes)
+ if err != nil {
+ ctx.ServerError("GetUserSetting", err)
+ return
+ }
+ hiddenCommentTypes, _ = new(big.Int).SetString(val, 10) // we can safely ignore the failed conversion here
+ }
+ ctx.Data["ShouldShowCommentType"] = func(commentType issues_model.CommentType) bool {
+ return hiddenCommentTypes == nil || hiddenCommentTypes.Bit(int(commentType)) == 0
+ }
+
+ // prepare for sidebar participants
+ ctx.Data["Participants"] = participants
+ ctx.Data["NumParticipants"] = len(participants)
+}
+
+func preparePullViewReviewAndMerge(ctx *context.Context, issue *issues_model.Issue) {
getBranchData(ctx, issue)
- if issue.IsPull {
- pull := issue.PullRequest
- pull.Issue = issue
- canDelete := false
- allowMerge := false
- canWriteToHeadRepo := false
-
- if ctx.IsSigned {
- if err := pull.LoadHeadRepo(ctx); err != nil {
- log.Error("LoadHeadRepo: %v", err)
- } else if pull.HeadRepo != nil {
- perm, err := access_model.GetUserRepoPermission(ctx, pull.HeadRepo, ctx.Doer)
- if err != nil {
- ctx.ServerError("GetUserRepoPermission", err)
- return
- }
- if perm.CanWrite(unit.TypeCode) {
- // Check if branch is not protected
- if pull.HeadBranch != pull.HeadRepo.DefaultBranch {
- if protected, err := git_model.IsBranchProtected(ctx, pull.HeadRepo.ID, pull.HeadBranch); err != nil {
- log.Error("IsProtectedBranch: %v", err)
- } else if !protected {
- canDelete = true
- ctx.Data["DeleteBranchLink"] = issue.Link() + "/cleanup"
- }
- }
- canWriteToHeadRepo = true
- }
- }
+ if !issue.IsPull {
+ return
+ }
- if err := pull.LoadBaseRepo(ctx); err != nil {
- log.Error("LoadBaseRepo: %v", err)
- }
- perm, err := access_model.GetUserRepoPermission(ctx, pull.BaseRepo, ctx.Doer)
+ pull := issue.PullRequest
+ pull.Issue = issue
+ canDelete := false
+ allowMerge := false
+ canWriteToHeadRepo := false
+
+ if ctx.IsSigned {
+ if err := pull.LoadHeadRepo(ctx); err != nil {
+ log.Error("LoadHeadRepo: %v", err)
+ } else if pull.HeadRepo != nil {
+ perm, err := access_model.GetUserRepoPermission(ctx, pull.HeadRepo, ctx.Doer)
if err != nil {
ctx.ServerError("GetUserRepoPermission", err)
return
}
- if !canWriteToHeadRepo { // maintainers maybe allowed to push to head repo even if they can't write to it
- canWriteToHeadRepo = pull.AllowMaintainerEdit && perm.CanWrite(unit.TypeCode)
- }
- allowMerge, err = pull_service.IsUserAllowedToMerge(ctx, pull, perm, ctx.Doer)
- if err != nil {
- ctx.ServerError("IsUserAllowedToMerge", err)
- return
- }
-
- if ctx.Data["CanMarkConversation"], err = issues_model.CanMarkConversation(ctx, issue, ctx.Doer); err != nil {
- ctx.ServerError("CanMarkConversation", err)
- return
+ if perm.CanWrite(unit.TypeCode) {
+ // Check if branch is not protected
+ if pull.HeadBranch != pull.HeadRepo.DefaultBranch {
+ if protected, err := git_model.IsBranchProtected(ctx, pull.HeadRepo.ID, pull.HeadBranch); err != nil {
+ log.Error("IsProtectedBranch: %v", err)
+ } else if !protected {
+ canDelete = true
+ ctx.Data["DeleteBranchLink"] = issue.Link() + "/cleanup"
+ }
+ }
+ canWriteToHeadRepo = true
}
}
- ctx.Data["CanWriteToHeadRepo"] = canWriteToHeadRepo
- ctx.Data["ShowMergeInstructions"] = canWriteToHeadRepo
- ctx.Data["AllowMerge"] = allowMerge
-
- prUnit, err := repo.GetUnit(ctx, unit.TypePullRequests)
- if err != nil {
- ctx.ServerError("GetUnit", err)
- return
- }
- prConfig := prUnit.PullRequestsConfig()
-
- ctx.Data["AutodetectManualMerge"] = prConfig.AutodetectManualMerge
-
- var mergeStyle repo_model.MergeStyle
- // Check correct values and select default
- if ms, ok := ctx.Data["MergeStyle"].(repo_model.MergeStyle); !ok ||
- !prConfig.IsMergeStyleAllowed(ms) {
- defaultMergeStyle := prConfig.GetDefaultMergeStyle()
- if prConfig.IsMergeStyleAllowed(defaultMergeStyle) && !ok {
- mergeStyle = defaultMergeStyle
- } else if prConfig.AllowMerge {
- mergeStyle = repo_model.MergeStyleMerge
- } else if prConfig.AllowRebase {
- mergeStyle = repo_model.MergeStyleRebase
- } else if prConfig.AllowRebaseMerge {
- mergeStyle = repo_model.MergeStyleRebaseMerge
- } else if prConfig.AllowSquash {
- mergeStyle = repo_model.MergeStyleSquash
- } else if prConfig.AllowFastForwardOnly {
- mergeStyle = repo_model.MergeStyleFastForwardOnly
- } else if prConfig.AllowManualMerge {
- mergeStyle = repo_model.MergeStyleManuallyMerged
- }
+ if err := pull.LoadBaseRepo(ctx); err != nil {
+ log.Error("LoadBaseRepo: %v", err)
}
-
- ctx.Data["MergeStyle"] = mergeStyle
-
- defaultMergeMessage, defaultMergeBody, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, mergeStyle)
+ perm, err := access_model.GetUserRepoPermission(ctx, pull.BaseRepo, ctx.Doer)
if err != nil {
- ctx.ServerError("GetDefaultMergeMessage", err)
+ ctx.ServerError("GetUserRepoPermission", err)
return
}
- ctx.Data["DefaultMergeMessage"] = defaultMergeMessage
- ctx.Data["DefaultMergeBody"] = defaultMergeBody
-
- defaultSquashMergeMessage, defaultSquashMergeBody, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, repo_model.MergeStyleSquash)
- if err != nil {
- ctx.ServerError("GetDefaultSquashMergeMessage", err)
- return
+ if !canWriteToHeadRepo { // maintainers maybe allowed to push to head repo even if they can't write to it
+ canWriteToHeadRepo = pull.AllowMaintainerEdit && perm.CanWrite(unit.TypeCode)
}
- ctx.Data["DefaultSquashMergeMessage"] = defaultSquashMergeMessage
- ctx.Data["DefaultSquashMergeBody"] = defaultSquashMergeBody
-
- pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pull.BaseRepoID, pull.BaseBranch)
+ allowMerge, err = pull_service.IsUserAllowedToMerge(ctx, pull, perm, ctx.Doer)
if err != nil {
- ctx.ServerError("LoadProtectedBranch", err)
+ ctx.ServerError("IsUserAllowedToMerge", err)
return
}
- if pb != nil {
- pb.Repo = pull.BaseRepo
- ctx.Data["ProtectedBranch"] = pb
- ctx.Data["IsBlockedByApprovals"] = !issues_model.HasEnoughApprovals(ctx, pb, pull)
- ctx.Data["IsBlockedByRejection"] = issues_model.MergeBlockedByRejectedReview(ctx, pb, pull)
- ctx.Data["IsBlockedByOfficialReviewRequests"] = issues_model.MergeBlockedByOfficialReviewRequests(ctx, pb, pull)
- ctx.Data["IsBlockedByOutdatedBranch"] = issues_model.MergeBlockedByOutdatedBranch(pb, pull)
- ctx.Data["GrantedApprovals"] = issues_model.GetGrantedApprovalsCount(ctx, pb, pull)
- ctx.Data["RequireSigned"] = pb.RequireSignedCommits
- ctx.Data["ChangedProtectedFiles"] = pull.ChangedProtectedFiles
- ctx.Data["IsBlockedByChangedProtectedFiles"] = len(pull.ChangedProtectedFiles) != 0
- ctx.Data["ChangedProtectedFilesNum"] = len(pull.ChangedProtectedFiles)
- ctx.Data["RequireApprovalsWhitelist"] = pb.EnableApprovalsWhitelist
- }
- ctx.Data["WillSign"] = false
- if ctx.Doer != nil {
- sign, key, _, err := asymkey_service.SignMerge(ctx, pull, ctx.Doer, pull.BaseRepo.RepoPath(), pull.BaseBranch, pull.GetGitRefName())
- ctx.Data["WillSign"] = sign
- ctx.Data["SigningKey"] = key
- if err != nil {
- if asymkey_service.IsErrWontSign(err) {
- ctx.Data["WontSignReason"] = err.(*asymkey_service.ErrWontSign).Reason
- } else {
- ctx.Data["WontSignReason"] = "error"
- log.Error("Error whilst checking if could sign pr %d in repo %s. Error: %v", pull.ID, pull.BaseRepo.FullName(), err)
- }
- }
- } else {
- ctx.Data["WontSignReason"] = "not_signed_in"
- }
-
- isPullBranchDeletable := canDelete &&
- pull.HeadRepo != nil &&
- git.IsBranchExist(ctx, pull.HeadRepo.RepoPath(), pull.HeadBranch) &&
- (!pull.HasMerged || ctx.Data["HeadBranchCommitID"] == ctx.Data["PullHeadCommitID"])
-
- if isPullBranchDeletable && pull.HasMerged {
- exist, err := issues_model.HasUnmergedPullRequestsByHeadInfo(ctx, pull.HeadRepoID, pull.HeadBranch)
- if err != nil {
- ctx.ServerError("HasUnmergedPullRequestsByHeadInfo", err)
- return
- }
-
- isPullBranchDeletable = !exist
+ if ctx.Data["CanMarkConversation"], err = issues_model.CanMarkConversation(ctx, issue, ctx.Doer); err != nil {
+ ctx.ServerError("CanMarkConversation", err)
+ return
}
- ctx.Data["IsPullBranchDeletable"] = isPullBranchDeletable
+ }
- stillCanManualMerge := func() bool {
- if pull.HasMerged || issue.IsClosed || !ctx.IsSigned {
- return false
- }
- if pull.CanAutoMerge() || pull.IsWorkInProgress(ctx) || pull.IsChecking() {
- return false
- }
- if allowMerge && prConfig.AllowManualMerge {
- return true
- }
+ ctx.Data["CanWriteToHeadRepo"] = canWriteToHeadRepo
+ ctx.Data["ShowMergeInstructions"] = canWriteToHeadRepo
+ ctx.Data["AllowMerge"] = allowMerge
- return false
- }
+ prUnit, err := issue.Repo.GetUnit(ctx, unit.TypePullRequests)
+ if err != nil {
+ ctx.ServerError("GetUnit", err)
+ return
+ }
+ prConfig := prUnit.PullRequestsConfig()
- ctx.Data["StillCanManualMerge"] = stillCanManualMerge()
+ ctx.Data["AutodetectManualMerge"] = prConfig.AutodetectManualMerge
- // Check if there is a pending pr merge
- ctx.Data["HasPendingPullRequestMerge"], ctx.Data["PendingPullRequestMerge"], err = pull_model.GetScheduledMergeByPullID(ctx, pull.ID)
- if err != nil {
- ctx.ServerError("GetScheduledMergeByPullID", err)
- return
+ var mergeStyle repo_model.MergeStyle
+ // Check correct values and select default
+ if ms, ok := ctx.Data["MergeStyle"].(repo_model.MergeStyle); !ok ||
+ !prConfig.IsMergeStyleAllowed(ms) {
+ defaultMergeStyle := prConfig.GetDefaultMergeStyle()
+ if prConfig.IsMergeStyleAllowed(defaultMergeStyle) && !ok {
+ mergeStyle = defaultMergeStyle
+ } else if prConfig.AllowMerge {
+ mergeStyle = repo_model.MergeStyleMerge
+ } else if prConfig.AllowRebase {
+ mergeStyle = repo_model.MergeStyleRebase
+ } else if prConfig.AllowRebaseMerge {
+ mergeStyle = repo_model.MergeStyleRebaseMerge
+ } else if prConfig.AllowSquash {
+ mergeStyle = repo_model.MergeStyleSquash
+ } else if prConfig.AllowFastForwardOnly {
+ mergeStyle = repo_model.MergeStyleFastForwardOnly
+ } else if prConfig.AllowManualMerge {
+ mergeStyle = repo_model.MergeStyleManuallyMerged
}
}
- // Get Dependencies
- blockedBy, err := issue.BlockedByDependencies(ctx, db.ListOptions{})
+ ctx.Data["MergeStyle"] = mergeStyle
+
+ defaultMergeMessage, defaultMergeBody, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, mergeStyle)
if err != nil {
- ctx.ServerError("BlockedByDependencies", err)
+ ctx.ServerError("GetDefaultMergeMessage", err)
return
}
- ctx.Data["BlockedByDependencies"], ctx.Data["BlockedByDependenciesNotPermitted"] = checkBlockedByIssues(ctx, blockedBy)
- if ctx.Written() {
+ ctx.Data["DefaultMergeMessage"] = defaultMergeMessage
+ ctx.Data["DefaultMergeBody"] = defaultMergeBody
+
+ defaultSquashMergeMessage, defaultSquashMergeBody, err := pull_service.GetDefaultMergeMessage(ctx, ctx.Repo.GitRepo, pull, repo_model.MergeStyleSquash)
+ if err != nil {
+ ctx.ServerError("GetDefaultSquashMergeMessage", err)
return
}
+ ctx.Data["DefaultSquashMergeMessage"] = defaultSquashMergeMessage
+ ctx.Data["DefaultSquashMergeBody"] = defaultSquashMergeBody
- blocking, err := issue.BlockingDependencies(ctx)
+ pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pull.BaseRepoID, pull.BaseBranch)
if err != nil {
- ctx.ServerError("BlockingDependencies", err)
+ ctx.ServerError("LoadProtectedBranch", err)
return
}
- ctx.Data["BlockingDependencies"], ctx.Data["BlockingDependenciesNotPermitted"] = checkBlockedByIssues(ctx, blocking)
+ if pb != nil {
+ pb.Repo = pull.BaseRepo
+ ctx.Data["ProtectedBranch"] = pb
+ ctx.Data["IsBlockedByApprovals"] = !issues_model.HasEnoughApprovals(ctx, pb, pull)
+ ctx.Data["IsBlockedByRejection"] = issues_model.MergeBlockedByRejectedReview(ctx, pb, pull)
+ ctx.Data["IsBlockedByOfficialReviewRequests"] = issues_model.MergeBlockedByOfficialReviewRequests(ctx, pb, pull)
+ ctx.Data["IsBlockedByOutdatedBranch"] = issues_model.MergeBlockedByOutdatedBranch(pb, pull)
+ ctx.Data["GrantedApprovals"] = issues_model.GetGrantedApprovalsCount(ctx, pb, pull)
+ ctx.Data["RequireSigned"] = pb.RequireSignedCommits
+ ctx.Data["ChangedProtectedFiles"] = pull.ChangedProtectedFiles
+ ctx.Data["IsBlockedByChangedProtectedFiles"] = len(pull.ChangedProtectedFiles) != 0
+ ctx.Data["ChangedProtectedFilesNum"] = len(pull.ChangedProtectedFiles)
+ ctx.Data["RequireApprovalsWhitelist"] = pb.EnableApprovalsWhitelist
+ }
+
+ preparePullViewSigning(ctx, issue)
if ctx.Written() {
return
}
- var pinAllowed bool
- if !issue.IsPinned() {
- pinAllowed, err = issues_model.IsNewPinAllowed(ctx, issue.RepoID, issue.IsPull)
- if err != nil {
- ctx.ServerError("IsNewPinAllowed", err)
- return
- }
- } else {
- pinAllowed = true
+ preparePullViewDeleteBranch(ctx, issue, canDelete)
+ if ctx.Written() {
+ return
}
- ctx.Data["Participants"] = participants
- ctx.Data["NumParticipants"] = len(participants)
- ctx.Data["Issue"] = issue
- ctx.Data["Reference"] = issue.Ref
- ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login?redirect_to=" + url.QueryEscape(ctx.Data["Link"].(string))
- ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.Doer.ID)
- ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
- ctx.Data["HasProjectsWritePermission"] = ctx.Repo.CanWrite(unit.TypeProjects)
- ctx.Data["IsRepoAdmin"] = ctx.IsSigned && (ctx.Repo.IsAdmin() || ctx.Doer.IsAdmin)
- ctx.Data["LockReasons"] = setting.Repository.Issue.LockReasons
- ctx.Data["RefEndName"] = git.RefName(issue.Ref).ShortName()
- ctx.Data["NewPinAllowed"] = pinAllowed
- ctx.Data["PinEnabled"] = setting.Repository.Issue.MaxPinned != 0
-
- var hiddenCommentTypes *big.Int
- if ctx.IsSigned {
- val, err := user_model.GetUserSetting(ctx, ctx.Doer.ID, user_model.SettingsKeyHiddenCommentTypes)
- if err != nil {
- ctx.ServerError("GetUserSetting", err)
- return
+ stillCanManualMerge := func() bool {
+ if pull.HasMerged || issue.IsClosed || !ctx.IsSigned {
+ return false
}
- hiddenCommentTypes, _ = new(big.Int).SetString(val, 10) // we can safely ignore the failed conversion here
- }
- ctx.Data["ShouldShowCommentType"] = func(commentType issues_model.CommentType) bool {
- return hiddenCommentTypes == nil || hiddenCommentTypes.Bit(int(commentType)) == 0
+ if pull.CanAutoMerge() || pull.IsWorkInProgress(ctx) || pull.IsChecking() {
+ return false
+ }
+ if allowMerge && prConfig.AllowManualMerge {
+ return true
+ }
+
+ return false
}
- // For sidebar
- PrepareBranchList(ctx)
- if ctx.Written() {
+ ctx.Data["StillCanManualMerge"] = stillCanManualMerge()
+
+ // Check if there is a pending pr merge
+ ctx.Data["HasPendingPullRequestMerge"], ctx.Data["PendingPullRequestMerge"], err = pull_model.GetScheduledMergeByPullID(ctx, pull.ID)
+ if err != nil {
+ ctx.ServerError("GetScheduledMergeByPullID", err)
return
}
+}
- tags, err := repo_model.GetTagNamesByRepoID(ctx, ctx.Repo.Repository.ID)
+func prepareIssueViewContent(ctx *context.Context, issue *issues_model.Issue) {
+ var err error
+ rctx := renderhelper.NewRenderContextRepoComment(ctx, ctx.Repo.Repository)
+ issue.RenderedContent, err = markdown.RenderString(rctx, issue.Content)
if err != nil {
- ctx.ServerError("GetTagNamesByRepoID", err)
+ ctx.ServerError("RenderString", err)
return
}
- ctx.Data["Tags"] = tags
-
- ctx.Data["CanBlockUser"] = func(blocker, blockee *user_model.User) bool {
- return user_service.CanBlockUser(ctx, ctx.Doer, blocker, blockee)
+ if issue.ShowRole, err = roleDescriptor(ctx, issue.Repo, issue.Poster, issue, issue.HasOriginalAuthor()); err != nil {
+ ctx.ServerError("roleDescriptor", err)
+ return
}
-
- ctx.HTML(http.StatusOK, tplIssueView)
+ ctx.Data["Issue"] = issue
}
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index 0325585e53..9694ae845b 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -263,8 +263,18 @@ func GetMergedBaseCommitID(ctx *context.Context, issue *issues_model.Issue) stri
return baseCommit
}
-// PrepareMergedViewPullInfo show meta information for a merged pull request view page
-func PrepareMergedViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.CompareInfo {
+func preparePullViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.CompareInfo {
+ if !issue.IsPull {
+ return nil
+ }
+ if issue.PullRequest.HasMerged {
+ return prepareMergedViewPullInfo(ctx, issue)
+ }
+ return prepareViewPullInfo(ctx, issue)
+}
+
+// prepareMergedViewPullInfo show meta information for a merged pull request view page
+func prepareMergedViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.CompareInfo {
pull := issue.PullRequest
setMergeTarget(ctx, pull)
@@ -309,8 +319,8 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *issues_model.Issue)
return compareInfo
}
-// PrepareViewPullInfo show meta information for a pull request preview page
-func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.CompareInfo {
+// prepareViewPullInfo show meta information for a pull request preview page
+func prepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.CompareInfo {
ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes
repo := ctx.Repo.Repository
@@ -610,15 +620,8 @@ func ViewPullCommits(ctx *context.Context) {
if !ok {
return
}
- pull := issue.PullRequest
-
- var prInfo *git.CompareInfo
- if pull.HasMerged {
- prInfo = PrepareMergedViewPullInfo(ctx, issue)
- } else {
- prInfo = PrepareViewPullInfo(ctx, issue)
- }
+ prInfo := preparePullViewPullInfo(ctx, issue)
if ctx.Written() {
return
} else if prInfo == nil {
@@ -662,11 +665,12 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
gitRepo = ctx.Repo.GitRepo
)
- var prInfo *git.CompareInfo
- if pull.HasMerged {
- prInfo = PrepareMergedViewPullInfo(ctx, issue)
- } else {
- prInfo = PrepareViewPullInfo(ctx, issue)
+ prInfo := preparePullViewPullInfo(ctx, issue)
+ if ctx.Written() {
+ return
+ } else if prInfo == nil {
+ ctx.NotFound("ViewPullFiles", nil)
+ return
}
// Validate the given commit sha to show (if any passed)