diff --git a/models/git/branch.go b/models/git/branch.go index 07c94a8ba5..6021e1101f 100644 --- a/models/git/branch.go +++ b/models/git/branch.go @@ -472,7 +472,7 @@ type RecentlyPushedNewBranch struct { // if opts.CommitAfterUnix is 0, we will find the branches that were committed to in the last 2 hours // if opts.ListOptions is not set, we will only display top 2 latest branches. // Protected branches will be skipped since they are unlikely to be used to create new PRs. -func FindRecentlyPushedNewBranches(ctx context.Context, doer *user_model.User, opts *FindRecentlyPushedNewBranchesOptions) ([]*RecentlyPushedNewBranch, error) { +func FindRecentlyPushedNewBranches(ctx context.Context, doer *user_model.User, opts FindRecentlyPushedNewBranchesOptions) ([]*RecentlyPushedNewBranch, error) { if doer == nil { return []*RecentlyPushedNewBranch{}, nil } diff --git a/models/repo/repo.go b/models/repo/repo.go index 34d1bf55f6..2403b3b40b 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -652,7 +652,13 @@ func (repo *Repository) AllowsPulls(ctx context.Context) bool { } // CanEnableEditor returns true if repository meets the requirements of web editor. +// FIXME: most CanEnableEditor calls should be replaced with CanContentChange +// And all other like CanCreateBranch / CanEnablePulls should also be updated func (repo *Repository) CanEnableEditor() bool { + return repo.CanContentChange() +} + +func (repo *Repository) CanContentChange() bool { return !repo.IsMirror && !repo.IsArchived } diff --git a/routers/web/repo/common_recentbranches.go b/routers/web/repo/common_recentbranches.go new file mode 100644 index 0000000000..c2083dec73 --- /dev/null +++ b/routers/web/repo/common_recentbranches.go @@ -0,0 +1,73 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package repo + +import ( + git_model "code.gitea.io/gitea/models/git" + access_model "code.gitea.io/gitea/models/perm/access" + unit_model "code.gitea.io/gitea/models/unit" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/services/context" + repo_service "code.gitea.io/gitea/services/repository" +) + +type RecentBranchesPromptDataStruct struct { + RecentlyPushedNewBranches []*git_model.RecentlyPushedNewBranch +} + +func prepareRecentlyPushedNewBranches(ctx *context.Context) { + if ctx.Doer == nil { + return + } + if err := ctx.Repo.Repository.GetBaseRepo(ctx); err != nil { + log.Error("GetBaseRepo: %v", err) + return + } + + opts := git_model.FindRecentlyPushedNewBranchesOptions{ + Repo: ctx.Repo.Repository, + BaseRepo: ctx.Repo.Repository, + } + if ctx.Repo.Repository.IsFork { + opts.BaseRepo = ctx.Repo.Repository.BaseRepo + } + + baseRepoPerm, err := access_model.GetUserRepoPermission(ctx, opts.BaseRepo, ctx.Doer) + if err != nil { + log.Error("GetUserRepoPermission: %v", err) + return + } + if !opts.Repo.CanContentChange() || !opts.BaseRepo.CanContentChange() { + return + } + if !opts.BaseRepo.UnitEnabled(ctx, unit_model.TypePullRequests) || !baseRepoPerm.CanRead(unit_model.TypePullRequests) { + return + } + + var finalBranches []*git_model.RecentlyPushedNewBranch + branches, err := git_model.FindRecentlyPushedNewBranches(ctx, ctx.Doer, opts) + if err != nil { + log.Error("FindRecentlyPushedNewBranches failed: %v", err) + return + } + + for _, branch := range branches { + divergingInfo, err := repo_service.GetBranchDivergingInfo(ctx, + branch.BranchRepo, branch.BranchName, // "base" repo for diverging info + opts.BaseRepo, opts.BaseRepo.DefaultBranch, // "head" repo for diverging info + ) + if err != nil { + log.Error("GetBranchDivergingInfo failed: %v", err) + continue + } + branchRepoHasNewCommits := divergingInfo.BaseHasNewCommits + baseRepoCommitsBehind := divergingInfo.HeadCommitsBehind + if branchRepoHasNewCommits || baseRepoCommitsBehind > 0 { + finalBranches = append(finalBranches, branch) + } + } + if len(finalBranches) > 0 { + ctx.Data["RecentBranchesPromptData"] = RecentBranchesPromptDataStruct{finalBranches} + } +} diff --git a/routers/web/repo/issue_list.go b/routers/web/repo/issue_list.go index b55f4bcc90..fd34422cfc 100644 --- a/routers/web/repo/issue_list.go +++ b/routers/web/repo/issue_list.go @@ -767,6 +767,10 @@ func Issues(ctx *context.Context) { } ctx.Data["Title"] = ctx.Tr("repo.pulls") ctx.Data["PageIsPullList"] = true + prepareRecentlyPushedNewBranches(ctx) + if ctx.Written() { + return + } } else { MustEnableIssues(ctx) if ctx.Written() { diff --git a/routers/web/repo/view_home.go b/routers/web/repo/view_home.go index c7396d44e3..5482780c98 100644 --- a/routers/web/repo/view_home.go +++ b/routers/web/repo/view_home.go @@ -15,7 +15,6 @@ import ( "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" - access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" unit_model "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" @@ -196,56 +195,6 @@ func prepareUpstreamDivergingInfo(ctx *context.Context) { ctx.Data["UpstreamDivergingInfo"] = upstreamDivergingInfo } -func prepareRecentlyPushedNewBranches(ctx *context.Context) { - if ctx.Doer != nil { - if err := ctx.Repo.Repository.GetBaseRepo(ctx); err != nil { - ctx.ServerError("GetBaseRepo", err) - return - } - - opts := &git_model.FindRecentlyPushedNewBranchesOptions{ - Repo: ctx.Repo.Repository, - BaseRepo: ctx.Repo.Repository, - } - if ctx.Repo.Repository.IsFork { - opts.BaseRepo = ctx.Repo.Repository.BaseRepo - } - - baseRepoPerm, err := access_model.GetUserRepoPermission(ctx, opts.BaseRepo, ctx.Doer) - if err != nil { - ctx.ServerError("GetUserRepoPermission", err) - return - } - - if !opts.Repo.IsMirror && !opts.BaseRepo.IsMirror && - opts.BaseRepo.UnitEnabled(ctx, unit_model.TypePullRequests) && - baseRepoPerm.CanRead(unit_model.TypePullRequests) { - var finalBranches []*git_model.RecentlyPushedNewBranch - branches, err := git_model.FindRecentlyPushedNewBranches(ctx, ctx.Doer, opts) - if err != nil { - log.Error("FindRecentlyPushedNewBranches failed: %v", err) - } - - for _, branch := range branches { - divergingInfo, err := repo_service.GetBranchDivergingInfo(ctx, - branch.BranchRepo, branch.BranchName, // "base" repo for diverging info - opts.BaseRepo, opts.BaseRepo.DefaultBranch, // "head" repo for diverging info - ) - if err != nil { - log.Error("GetBranchDivergingInfo failed: %v", err) - continue - } - branchRepoHasNewCommits := divergingInfo.BaseHasNewCommits - baseRepoCommitsBehind := divergingInfo.HeadCommitsBehind - if branchRepoHasNewCommits || baseRepoCommitsBehind > 0 { - finalBranches = append(finalBranches, branch) - } - } - ctx.Data["RecentlyPushedNewBranches"] = finalBranches - } - } -} - func updateContextRepoEmptyAndStatus(ctx *context.Context, empty bool, status repo_model.RepositoryStatus) { if ctx.Repo.Repository.IsEmpty == empty && ctx.Repo.Repository.Status == status { return diff --git a/templates/repo/code/recently_pushed_new_branches.tmpl b/templates/repo/code/recently_pushed_new_branches.tmpl index 4a864ba756..8569bd6c13 100644 --- a/templates/repo/code/recently_pushed_new_branches.tmpl +++ b/templates/repo/code/recently_pushed_new_branches.tmpl @@ -1,12 +1,18 @@ -{{range .RecentlyPushedNewBranches}} -
-
- {{$timeSince := DateUtils.TimeSince .CommitTime}} - {{$branchLink := HTMLFormat `%s` .BranchLink .BranchDisplayName}} +{{/* Template Attributes: +* RecentBranchesPromptData +*/}} +{{$data := .RecentBranchesPromptData}} +{{if $data}} + {{range $recentBranch := $data.RecentlyPushedNewBranches}} +
+
+ {{$timeSince := DateUtils.TimeSince $recentBranch.CommitTime}} + {{$branchLink := HTMLFormat `%s` $recentBranch.BranchLink .BranchDisplayName}} {{ctx.Locale.Tr "repo.pulls.recently_pushed_new_branches" $branchLink $timeSince}}
- + {{ctx.Locale.Tr "repo.pulls.compare_changes"}}
+ {{end}} {{end}} diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl index f86b90502d..2a6c0d2fe5 100644 --- a/templates/repo/home.tmpl +++ b/templates/repo/home.tmpl @@ -15,7 +15,7 @@
{{end}} - {{template "repo/code/recently_pushed_new_branches" .}} + {{template "repo/code/recently_pushed_new_branches" dict "RecentBranchesPromptData" .RecentBranchesPromptData}}
diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index 0ab761e038..1fe220e1b8 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -4,6 +4,8 @@
{{template "base/alert" .}} + {{template "repo/code/recently_pushed_new_branches" dict "RecentBranchesPromptData" .RecentBranchesPromptData}} + {{if .PinnedIssues}}
{{range .PinnedIssues}} diff --git a/templates/repo/view.tmpl b/templates/repo/view.tmpl index 85d09d03a1..f99fe2f57a 100644 --- a/templates/repo/view.tmpl +++ b/templates/repo/view.tmpl @@ -14,7 +14,7 @@
{{end}} - {{template "repo/code/recently_pushed_new_branches" .}} + {{template "repo/code/recently_pushed_new_branches" dict "RecentBranchesPromptData" .RecentBranchesPromptData}}