From 6375419468edc95fdfac94aac3b0e10b23743557 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 8 Jul 2023 11:19:00 +0800 Subject: [PATCH] Newly pushed branches hints on repository home page (#25715) This PR will display a pull request creation hint on the repository home page when there are newly created branches with no pull request. Only the recent 6 hours and 2 updated branches will be displayed. Inspired by #14003 Replace #14003 Resolves #311 Resolves #13196 Resolves #23743 co-authored by @kolaente --- models/git/branch.go | 21 +++++++++++++++++++ models/repo/repo.go | 12 +++++++++++ options/locale/locale_en-US.ini | 2 ++ routers/web/repo/view.go | 12 +++++++++++ .../code/recently_pushed_new_branches.tmpl | 11 ++++++++++ templates/repo/home.tmpl | 1 + tests/integration/repo_branch_test.go | 4 ++-- 7 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 templates/repo/code/recently_pushed_new_branches.tmpl diff --git a/models/git/branch.go b/models/git/branch.go index 5e9954495..97891f01e 100644 --- a/models/git/branch.go +++ b/models/git/branch.go @@ -15,6 +15,8 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" + + "xorm.io/builder" ) // ErrBranchNotExist represents an error that branch with such name does not exist. @@ -378,3 +380,22 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str return committer.Commit() } + +// FindRecentlyPushedNewBranches return at most 2 new branches pushed by the user in 6 hours which has no opened PRs created +func FindRecentlyPushedNewBranches(ctx context.Context, repoID, userID int64) (BranchList, error) { + branches := make(BranchList, 0, 2) + subQuery := builder.Select("head_branch").From("pull_request"). + InnerJoin("issue", "issue.id = pull_request.issue_id"). + Where(builder.Eq{ + "pull_request.head_repo_id": repoID, + "issue.is_closed": false, + }) + err := db.GetEngine(ctx). + Where("pusher_id=? AND is_deleted=?", userID, false). + And("updated_unix >= ?", time.Now().Add(-time.Hour*6).Unix()). + NotIn("name", subQuery). + OrderBy("branch.updated_unix DESC"). + Limit(2). + Find(&branches) + return branches, err +} diff --git a/models/repo/repo.go b/models/repo/repo.go index b7c02057c..3d1f2dcfa 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -528,6 +528,18 @@ func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) strin return fmt.Sprintf("%s/%s/compare/%s...%s", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name), util.PathEscapeSegments(oldCommitID), util.PathEscapeSegments(newCommitID)) } +func (repo *Repository) ComposeBranchCompareURL(baseRepo *Repository, branchName string) string { + if baseRepo == nil { + baseRepo = repo + } + var cmpBranchEscaped string + if repo.ID != baseRepo.ID { + cmpBranchEscaped = fmt.Sprintf("%s/%s:", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name)) + } + cmpBranchEscaped = fmt.Sprintf("%s%s", cmpBranchEscaped, util.PathEscapeSegments(branchName)) + return fmt.Sprintf("%s/compare/%s...%s", baseRepo.Link(), util.PathEscapeSegments(baseRepo.DefaultBranch), cmpBranchEscaped) +} + // IsOwnedBy returns true when user owns this repository func (repo *Repository) IsOwnedBy(userID int64) bool { return repo.OwnerID == userID diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index a0901451a..58fd84308 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1767,6 +1767,8 @@ pulls.auto_merge_canceled_schedule_comment = `canceled auto merging this pull re pulls.delete.title = Delete this pull request? pulls.delete.text = Do you really want to delete this pull request? (This will permanently remove all content. Consider closing it instead, if you intend to keep it archived) +pulls.recently_pushed_new_branches = You pushed on branch %[1]s %[2]s + milestones.new = New Milestone milestones.closed = Closed %s milestones.update_ago = Updated %s diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index ad87bae9b..acea08d62 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -977,6 +977,18 @@ func renderCode(ctx *context.Context) { return } + if ctx.Doer != nil { + if err := ctx.Repo.Repository.GetBaseRepo(ctx); err != nil { + ctx.ServerError("GetBaseRepo", err) + return + } + ctx.Data["RecentlyPushedNewBranches"], err = git_model.FindRecentlyPushedNewBranches(ctx, ctx.Repo.Repository.ID, ctx.Doer.ID) + if err != nil { + ctx.ServerError("GetRecentlyPushedBranches", err) + return + } + } + var treeNames []string paths := make([]string, 0, 5) if len(ctx.Repo.TreePath) > 0 { diff --git a/templates/repo/code/recently_pushed_new_branches.tmpl b/templates/repo/code/recently_pushed_new_branches.tmpl new file mode 100644 index 000000000..e936fa4bb --- /dev/null +++ b/templates/repo/code/recently_pushed_new_branches.tmpl @@ -0,0 +1,11 @@ +{{range .RecentlyPushedNewBranches}} +
+
+ {{$timeSince := TimeSince .UpdatedUnix.AsTime $.locale}} + {{$.locale.Tr "repo.pulls.recently_pushed_new_branches" (PathEscapeSegments .Name) $timeSince | Safe}} +
+ + {{$.locale.Tr "repo.pulls.compare_changes"}} + +
+{{end}} diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl index 01ea5d912..386908e42 100644 --- a/templates/repo/home.tmpl +++ b/templates/repo/home.tmpl @@ -3,6 +3,7 @@ {{template "repo/header" .}}
{{template "base/alert" .}} + {{template "repo/code/recently_pushed_new_branches" .}} {{if and (not .HideRepoInfo) (not .IsBlame)}}
diff --git a/tests/integration/repo_branch_test.go b/tests/integration/repo_branch_test.go index c56aa43c5..91674ddc8 100644 --- a/tests/integration/repo_branch_test.go +++ b/tests/integration/repo_branch_test.go @@ -120,9 +120,9 @@ func testCreateBranches(t *testing.T, giteaURL *url.URL) { req := NewRequest(t, "GET", redirectURL) resp := session.MakeRequest(t, req, http.StatusOK) htmlDoc := NewHTMLParser(t, resp.Body) - assert.Equal(t, - test.FlashMessage, + assert.Contains(t, strings.TrimSpace(htmlDoc.doc.Find(".ui.message").Text()), + test.FlashMessage, ) } }