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
This commit is contained in:
parent
e0a780d75b
commit
6375419468
|
@ -15,6 +15,8 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrBranchNotExist represents an error that branch with such name does not exist.
|
// 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()
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -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))
|
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
|
// IsOwnedBy returns true when user owns this repository
|
||||||
func (repo *Repository) IsOwnedBy(userID int64) bool {
|
func (repo *Repository) IsOwnedBy(userID int64) bool {
|
||||||
return repo.OwnerID == userID
|
return repo.OwnerID == userID
|
||||||
|
|
|
@ -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.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.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 <strong>%[1]s</strong> %[2]s
|
||||||
|
|
||||||
milestones.new = New Milestone
|
milestones.new = New Milestone
|
||||||
milestones.closed = Closed %s
|
milestones.closed = Closed %s
|
||||||
milestones.update_ago = Updated %s
|
milestones.update_ago = Updated %s
|
||||||
|
|
|
@ -977,6 +977,18 @@ func renderCode(ctx *context.Context) {
|
||||||
return
|
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
|
var treeNames []string
|
||||||
paths := make([]string, 0, 5)
|
paths := make([]string, 0, 5)
|
||||||
if len(ctx.Repo.TreePath) > 0 {
|
if len(ctx.Repo.TreePath) > 0 {
|
||||||
|
|
11
templates/repo/code/recently_pushed_new_branches.tmpl
Normal file
11
templates/repo/code/recently_pushed_new_branches.tmpl
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{{range .RecentlyPushedNewBranches}}
|
||||||
|
<div class="ui positive message gt-df gt-ac">
|
||||||
|
<div class="gt-f1">
|
||||||
|
{{$timeSince := TimeSince .UpdatedUnix.AsTime $.locale}}
|
||||||
|
{{$.locale.Tr "repo.pulls.recently_pushed_new_branches" (PathEscapeSegments .Name) $timeSince | Safe}}
|
||||||
|
</div>
|
||||||
|
<a aria-role="button" class="ui compact positive button gt-m-0" href="{{$.Repository.ComposeBranchCompareURL $.Repository.BaseRepo (PathEscapeSegments .Name)}}">
|
||||||
|
{{$.locale.Tr "repo.pulls.compare_changes"}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
|
@ -3,6 +3,7 @@
|
||||||
{{template "repo/header" .}}
|
{{template "repo/header" .}}
|
||||||
<div class="ui container {{if .IsBlame}}fluid padded{{end}}">
|
<div class="ui container {{if .IsBlame}}fluid padded{{end}}">
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
|
{{template "repo/code/recently_pushed_new_branches" .}}
|
||||||
{{if and (not .HideRepoInfo) (not .IsBlame)}}
|
{{if and (not .HideRepoInfo) (not .IsBlame)}}
|
||||||
<div class="ui repo-description">
|
<div class="ui repo-description">
|
||||||
<div id="repo-desc">
|
<div id="repo-desc">
|
||||||
|
|
|
@ -120,9 +120,9 @@ func testCreateBranches(t *testing.T, giteaURL *url.URL) {
|
||||||
req := NewRequest(t, "GET", redirectURL)
|
req := NewRequest(t, "GET", redirectURL)
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||||
assert.Equal(t,
|
assert.Contains(t,
|
||||||
test.FlashMessage,
|
|
||||||
strings.TrimSpace(htmlDoc.doc.Find(".ui.message").Text()),
|
strings.TrimSpace(htmlDoc.doc.Find(".ui.message").Text()),
|
||||||
|
test.FlashMessage,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue