初始提交: Gitea 项目代码
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
|
||||
"gitea.dev/modules/htmlutil"
|
||||
"gitea.dev/modules/svg"
|
||||
"gitea.dev/modules/util"
|
||||
"gitea.dev/services/context"
|
||||
)
|
||||
|
||||
type pullMergeBoxInfoItem struct {
|
||||
ItemClass string
|
||||
SvgIconHTML template.HTML
|
||||
InfoHTML template.HTML
|
||||
ListItems []template.HTML
|
||||
}
|
||||
|
||||
type pullMergeBoxInfoItemCollection struct {
|
||||
items []*pullMergeBoxInfoItem
|
||||
}
|
||||
|
||||
type pullInfoSection struct {
|
||||
InfoItems []*pullMergeBoxInfoItem
|
||||
}
|
||||
|
||||
func escapeStringSliceToHTML(s []string) (ret []template.HTML) {
|
||||
for _, v := range s {
|
||||
ret = append(ret, template.HTML(template.HTMLEscapeString(v)))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (c *pullMergeBoxInfoItemCollection) AddInfoItem(svg, info template.HTML, optItems ...[]template.HTML) {
|
||||
c.items = append(c.items, &pullMergeBoxInfoItem{
|
||||
SvgIconHTML: svg,
|
||||
InfoHTML: info,
|
||||
ListItems: util.OptionalArg(optItems),
|
||||
})
|
||||
}
|
||||
|
||||
func (c *pullMergeBoxInfoItemCollection) AddErrorItem(svg, info template.HTML, optItems ...[]template.HTML) {
|
||||
c.items = append(c.items, &pullMergeBoxInfoItem{
|
||||
ItemClass: "tw-text-red",
|
||||
SvgIconHTML: svg,
|
||||
InfoHTML: info,
|
||||
ListItems: util.OptionalArg(optItems),
|
||||
})
|
||||
}
|
||||
|
||||
func (prInfo *pullRequestViewInfo) prepareMergeBoxIconColor() {
|
||||
pull := prInfo.issue.PullRequest
|
||||
mergeBoxData := prInfo.MergeBoxData
|
||||
|
||||
showAsNormalColor := prInfo.issue.IsClosed || prInfo.workInProgressPrefix != "" || pull.IsEmpty() || pull.IsFilesConflicted()
|
||||
showAsErrorColor := false
|
||||
showAsWarningColor := pull.IsChecking()
|
||||
|
||||
if statusCheckData := mergeBoxData.StatusCheckData; statusCheckData != nil {
|
||||
showAsErrorColor = statusCheckData.pullCommitStatusState.IsError() || statusCheckData.pullCommitStatusState.IsFailure() ||
|
||||
statusCheckData.RequiredChecksState.IsError() || statusCheckData.RequiredChecksState.IsFailure()
|
||||
|
||||
showAsWarningColor = showAsWarningColor ||
|
||||
statusCheckData.pullCommitStatusState.IsWarning() || statusCheckData.pullCommitStatusState.IsPending() ||
|
||||
(mergeBoxData.enableStatusCheck && (statusCheckData.RequiredChecksState.IsWarning() || statusCheckData.RequiredChecksState.IsPending()))
|
||||
}
|
||||
|
||||
hasBlockers := len(mergeBoxData.infoCommitBlockers.items) > 0 || len(mergeBoxData.infoProtectionBlockers.items) > 0
|
||||
|
||||
switch {
|
||||
case pull.HasMerged:
|
||||
prInfo.MergeBoxData.TimelineIconClass = "tw-text-purple"
|
||||
case showAsNormalColor:
|
||||
prInfo.MergeBoxData.TimelineIconClass = "tw-text-text-light"
|
||||
case showAsErrorColor:
|
||||
prInfo.MergeBoxData.TimelineIconClass = "tw-text-red"
|
||||
case showAsWarningColor:
|
||||
prInfo.MergeBoxData.TimelineIconClass = "tw-text-yellow"
|
||||
case hasBlockers:
|
||||
prInfo.MergeBoxData.TimelineIconClass = "tw-text-red"
|
||||
case pull.IsStatusMergeable():
|
||||
prInfo.MergeBoxData.TimelineIconClass = "tw-text-green"
|
||||
default:
|
||||
prInfo.MergeBoxData.TimelineIconClass = "tw-text-text-light"
|
||||
}
|
||||
}
|
||||
|
||||
func (prInfo *pullRequestViewInfo) prepareMergeBoxInfoItems(ctx *context.Context) {
|
||||
pull := prInfo.issue.PullRequest
|
||||
data := prInfo.MergeBoxData
|
||||
|
||||
if pull.HasMerged && data.IsPullBranchDeletable {
|
||||
data.ClosedInfoTitle = ctx.Locale.Tr("repo.pulls.merged_success")
|
||||
data.ClosedInfoBody = ctx.Locale.Tr("repo.pulls.merged_info_text", htmlutil.HTMLFormat("<code>%s</code>", prInfo.headTarget))
|
||||
return
|
||||
} else if prInfo.issue.IsClosed {
|
||||
data.ClosedInfoTitle = ctx.Locale.Tr("repo.pulls.closed")
|
||||
if prInfo.IsPullRequestBroken {
|
||||
data.ClosedInfoBody = ctx.Locale.Tr("repo.pulls.cant_reopen_deleted_branch")
|
||||
} else {
|
||||
data.ClosedInfoBody = ctx.Locale.Tr("repo.pulls.reopen_to_merge")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if pull.IsFilesConflicted() {
|
||||
detailItems := escapeStringSliceToHTML(pull.ConflictedFiles)
|
||||
if len(detailItems) == 0 {
|
||||
detailItems = append(detailItems, ctx.Locale.Tr("repo.pulls.files_conflicted_no_listed_files"))
|
||||
}
|
||||
if len(detailItems) > 10 {
|
||||
detailItems = detailItems[:10]
|
||||
detailItems = append(detailItems, "...")
|
||||
}
|
||||
prInfo.MergeBoxData.infoCommitBlockers.AddInfoItem(
|
||||
svg.RenderHTML("octicon-x"),
|
||||
ctx.Locale.Tr("repo.pulls.files_conflicted"),
|
||||
detailItems,
|
||||
)
|
||||
}
|
||||
|
||||
if prInfo.IsPullRequestBroken {
|
||||
prInfo.MergeBoxData.infoCommitBlockers.AddInfoItem(
|
||||
svg.RenderHTML("octicon-x"),
|
||||
ctx.Locale.Tr("repo.pulls.data_broken"),
|
||||
)
|
||||
}
|
||||
|
||||
if pull.IsChecking() {
|
||||
prInfo.MergeBoxData.infoCommitBlockers.AddInfoItem(
|
||||
svg.RenderHTML("gitea-running", 16, "rotate-clockwise"),
|
||||
ctx.Locale.Tr("repo.pulls.is_checking"),
|
||||
)
|
||||
}
|
||||
|
||||
if pull.IsAncestor() {
|
||||
prInfo.MergeBoxData.infoCommitBlockers.AddInfoItem(
|
||||
svg.RenderHTML("octicon-alert"),
|
||||
ctx.Locale.Tr("repo.pulls.is_ancestor"),
|
||||
)
|
||||
}
|
||||
|
||||
if !pull.IsStatusMergeable() {
|
||||
// it is only a "protection" level blocker, it can be bypassed by admin (e.g.: manually merged)
|
||||
if pull.IsEmpty() {
|
||||
prInfo.MergeBoxData.infoProtectionBlockers.AddInfoItem(
|
||||
svg.RenderHTML("octicon-alert"),
|
||||
ctx.Locale.Tr("repo.pulls.is_empty"),
|
||||
)
|
||||
} else {
|
||||
prInfo.MergeBoxData.infoProtectionBlockers.AddErrorItem(
|
||||
svg.RenderHTML("octicon-x"),
|
||||
ctx.Locale.Tr("repo.pulls.cannot_auto_merge_desc"),
|
||||
)
|
||||
prInfo.MergeBoxData.infoProtectionBlockers.AddInfoItem(
|
||||
svg.RenderHTML("octicon-info"),
|
||||
ctx.Locale.Tr("repo.pulls.cannot_auto_merge_helper"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if !data.hasPermToMerge {
|
||||
prInfo.MergeBoxData.infoProtectionBlockers.AddInfoItem(
|
||||
svg.RenderHTML("octicon-info"),
|
||||
ctx.Locale.Tr("repo.pulls.no_merge_access"),
|
||||
)
|
||||
}
|
||||
|
||||
if data.canMergeNow {
|
||||
if data.hasOverridableBlockers {
|
||||
prompt := ctx.Locale.Tr("repo.pulls.required_status_check_bypass_allowlist")
|
||||
if data.canBypassProtectionAsAdmin {
|
||||
prompt = ctx.Locale.Tr("repo.pulls.required_status_check_administrator")
|
||||
}
|
||||
prInfo.MergeBoxData.infoMergePrompts.AddInfoItem(
|
||||
svg.RenderHTML("octicon-dot-fill"),
|
||||
prompt,
|
||||
)
|
||||
} else if pull.IsStatusMergeable() || pull.IsEmpty() {
|
||||
prInfo.MergeBoxData.infoMergePrompts.AddInfoItem(
|
||||
svg.RenderHTML("octicon-check"),
|
||||
ctx.Locale.Tr("repo.pulls.can_auto_merge_desc"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if len(data.infoCommitBlockers.items) > 0 {
|
||||
data.InfoSections = append(data.InfoSections, &pullInfoSection{data.infoCommitBlockers.items})
|
||||
} else {
|
||||
data.InfoSections = append(data.InfoSections, &pullInfoSection{data.infoProtectionBlockers.items})
|
||||
}
|
||||
data.InfoSections = append(data.InfoSections, &pullInfoSection{data.infoMergePrompts.items})
|
||||
}
|
||||
Reference in New Issue
Block a user