mirror of https://github.com/go-gitea/gitea
improve
This commit is contained in:
parent
6517ad975f
commit
9a33437cd6
|
@ -393,55 +393,74 @@ 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
|
||||
// doer should not be nil
|
||||
// if commitAfterUnix is 0, will find the branches committed in recently 6 hours
|
||||
// TODO use options to find the branches
|
||||
func FindRecentlyPushedNewBranches(ctx context.Context, baseRepo *repo_model.Repository, doer *user_model.User, commitAfterUnix int64) (BranchList, error) {
|
||||
baseBranch, err := GetBranch(ctx, baseRepo.ID, baseRepo.DefaultBranch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
type FindRecentlyPushedNewBranchesOptions struct {
|
||||
Actor *user_model.User
|
||||
Repo *repo_model.Repository
|
||||
BaseRepo *repo_model.Repository
|
||||
CommitAfterUnix int64
|
||||
}
|
||||
|
||||
// search all related repos
|
||||
// FindRecentlyPushedNewBranches return at most 2 new branches pushed by the user in 6 hours which has no opened PRs created
|
||||
// opts.Actor should not be nil
|
||||
// if opts.CommitAfterUnix is 0, we will find the branches committed in recently 6 hours
|
||||
func FindRecentlyPushedNewBranches(ctx context.Context, opts *FindRecentlyPushedNewBranchesOptions) (BranchList, error) {
|
||||
// find all related repo ids
|
||||
repoOpts := repo_model.SearchRepoOptions{
|
||||
Actor: doer,
|
||||
Actor: opts.Actor,
|
||||
Private: true,
|
||||
AllPublic: false, // Include also all public repositories of users and public organisations
|
||||
AllLimited: false, // Include also all public repositories of limited organisations
|
||||
Fork: util.OptionalBoolTrue,
|
||||
ForkID: baseRepo.ID,
|
||||
ForkFrom: opts.BaseRepo.ID,
|
||||
Archived: util.OptionalBoolFalse,
|
||||
}
|
||||
repoCond := repo_model.SearchRepositoryCondition(&repoOpts).
|
||||
And(repo_model.AccessibleRepositoryCondition(doer, unit.TypeCode)).
|
||||
Or(builder.Eq{"id": baseRepo.ID})
|
||||
repoIds := builder.Select("id").From("repository").Where(repoCond)
|
||||
repoCond := repo_model.SearchRepositoryCondition(&repoOpts).And(repo_model.AccessibleRepositoryCondition(opts.Actor, unit.TypeCode))
|
||||
if opts.Repo == opts.BaseRepo {
|
||||
// should also include the brase repo's branches
|
||||
repoCond = repoCond.Or(builder.Eq{"id": opts.BaseRepo.ID})
|
||||
} else {
|
||||
// in fork repo, we only detect the fork repo's branch
|
||||
repoCond = repoCond.And(builder.Eq{"id": opts.Repo.ID})
|
||||
}
|
||||
repoIDs := builder.Select("id").From("repository").Where(repoCond)
|
||||
|
||||
// avoid check branches which have already created PRs
|
||||
// TODO add head_branch_id in pull_request table then we can get the branch id from pull_request table directly
|
||||
// find branches which have already created PRs
|
||||
prBranchIds := builder.Select("branch.id").From("branch").
|
||||
InnerJoin("pull_request", "branch.name = pull_request.head_branch AND branch.repo_id = pull_request.head_repo_id").
|
||||
InnerJoin("issue", "issue.id = pull_request.issue_id").
|
||||
Where(builder.Or(
|
||||
builder.Eq{"pull_request.has_merged": true},
|
||||
builder.In("pull_request.head_repo_id", repoIds),
|
||||
builder.Eq{"branch.id": baseBranch.ID},
|
||||
Where(builder.And(
|
||||
builder.Eq{"pull_request.base_repo_id": opts.BaseRepo.ID},
|
||||
builder.Eq{"pull_request.base_branch": opts.BaseRepo.DefaultBranch},
|
||||
builder.In("pull_request.head_repo_id", repoIDs),
|
||||
builder.Or(
|
||||
builder.Eq{"issue.is_closed": true},
|
||||
builder.Eq{"pull_request.has_merged": true},
|
||||
),
|
||||
))
|
||||
|
||||
if commitAfterUnix == 0 {
|
||||
commitAfterUnix = time.Now().Add(-time.Hour * 6).Unix()
|
||||
if opts.CommitAfterUnix == 0 {
|
||||
opts.CommitAfterUnix = time.Now().Add(-time.Hour * 6).Unix()
|
||||
}
|
||||
opts := FindBranchOptions{
|
||||
IDCond: builder.NotIn("id", prBranchIds),
|
||||
RepoCond: builder.In("repo_id", repoIds),
|
||||
CommitCond: builder.Neq{"commit_id": baseBranch.CommitID}, // newly created branch have no changes, so skip them,
|
||||
PusherID: doer.ID,
|
||||
|
||||
baseBranch, err := GetBranch(ctx, opts.BaseRepo.ID, opts.BaseRepo.DefaultBranch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
findBranchOpts := FindBranchOptions{
|
||||
RepoCond: builder.In("branch.repo_id", repoIDs),
|
||||
CommitCond: builder.Neq{"branch.commit_id": baseBranch.CommitID}, // newly created branch have no changes, so skip them,
|
||||
PusherID: opts.Actor.ID,
|
||||
IsDeletedBranch: util.OptionalBoolFalse,
|
||||
CommitAfterUnix: commitAfterUnix,
|
||||
CommitAfterUnix: opts.CommitAfterUnix,
|
||||
OrderBy: "branch.updated_unix DESC",
|
||||
// should not use branch name here, because if there are branches with same name in different repos,
|
||||
// we can not detect them correctly
|
||||
PullRequestCond: builder.NotIn("branch.id", prBranchIds),
|
||||
}
|
||||
opts.PageSize = 2
|
||||
opts.Page = 1
|
||||
return FindBranches(ctx, opts)
|
||||
// only display top 2 latest branch
|
||||
findBranchOpts.PageSize = 2
|
||||
findBranchOpts.Page = 1
|
||||
|
||||
return FindBranches(ctx, findBranchOpts)
|
||||
}
|
||||
|
|
|
@ -87,7 +87,6 @@ func (branches BranchList) LoadRepo(ctx context.Context) error {
|
|||
|
||||
type FindBranchOptions struct {
|
||||
db.ListOptions
|
||||
IDCond builder.Cond
|
||||
RepoIDs []int64 // overwrites RepoCond if the length is not 0
|
||||
RepoCond builder.Cond
|
||||
ExcludeBranchNames []string
|
||||
|
@ -97,13 +96,13 @@ type FindBranchOptions struct {
|
|||
CommitAfterUnix int64
|
||||
CommitBeforeUnix int64
|
||||
OrderBy string
|
||||
|
||||
// find branch by pull request
|
||||
PullRequestCond builder.Cond
|
||||
}
|
||||
|
||||
func (opts *FindBranchOptions) Cond() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
if opts.IDCond != nil {
|
||||
cond = cond.And(opts.IDCond)
|
||||
}
|
||||
|
||||
if len(opts.RepoIDs) == 1 {
|
||||
opts.RepoCond = builder.Eq{"branch.repo_id": opts.RepoIDs[0]}
|
||||
|
@ -136,6 +135,11 @@ func (opts *FindBranchOptions) Cond() builder.Cond {
|
|||
if opts.CommitBeforeUnix != 0 {
|
||||
cond = cond.And(builder.Lte{"branch.commit_time": opts.CommitBeforeUnix})
|
||||
}
|
||||
|
||||
if opts.PullRequestCond != nil {
|
||||
cond = cond.And(opts.PullRequestCond)
|
||||
}
|
||||
|
||||
return cond
|
||||
}
|
||||
|
||||
|
|
|
@ -189,35 +189,61 @@ func TestFindRecentlyPushedNewBranches(t *testing.T) {
|
|||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
|
||||
// test new branch of the repo and org fork repo
|
||||
// user2 is the owner of the repo and the organization
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
branches, err := git_model.FindRecentlyPushedNewBranches(db.DefaultContext, repo, user2, 1689838760)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 2, len(branches))
|
||||
assert.Equal(t, "new-commit", branches[0].Name)
|
||||
assert.Equal(t, "org-fork-new-commit", branches[1].Name)
|
||||
|
||||
// test new branch from user fork repo
|
||||
user8 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 8})
|
||||
branches, err = git_model.FindRecentlyPushedNewBranches(db.DefaultContext, repo, user8, 1689838760)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(branches))
|
||||
assert.Equal(t, "user-fork-new-commit", branches[0].Name)
|
||||
|
||||
// test new branch from private org with code permisstion repo
|
||||
user18 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 18})
|
||||
branches, err = git_model.FindRecentlyPushedNewBranches(db.DefaultContext, repo, user18, 1689838760)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(branches))
|
||||
assert.Equal(t, "private-org-fork-new-commit", branches[0].Name)
|
||||
|
||||
// test new branch from private org with no code permisstion repo
|
||||
user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||
branches, err = git_model.FindRecentlyPushedNewBranches(db.DefaultContext, repo, user5, 1689838760)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, len(branches))
|
||||
user8 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 8})
|
||||
user18 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 18})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
actor *user_model.User
|
||||
count int
|
||||
want []string
|
||||
}{
|
||||
// user2 is the owner of the repo and the organization
|
||||
{
|
||||
name: "new branch of the repo and org fork repo",
|
||||
actor: user2,
|
||||
count: 2,
|
||||
want: []string{"new-commit", "org-fork-new-commit"},
|
||||
},
|
||||
{
|
||||
name: "new branch from user fork repo",
|
||||
actor: user8,
|
||||
count: 1,
|
||||
want: []string{"user-fork-new-commit"},
|
||||
},
|
||||
{
|
||||
name: "new branch from private org with code permisstion repo",
|
||||
actor: user18,
|
||||
count: 1,
|
||||
want: []string{"private-org-fork-new-commit"},
|
||||
},
|
||||
{
|
||||
name: "new branch from private org with no code permisstion repo",
|
||||
actor: user5,
|
||||
count: 0,
|
||||
want: []string{"new-commit", "org-fork-new-commit"},
|
||||
},
|
||||
}
|
||||
|
||||
opts := &git_model.FindRecentlyPushedNewBranchesOptions{
|
||||
Repo: repo,
|
||||
BaseRepo: repo,
|
||||
CommitAfterUnix: 1689838760,
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
opts.Actor = tt.actor
|
||||
branches, err := git_model.FindRecentlyPushedNewBranches(db.DefaultContext, opts)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.count, len(branches))
|
||||
|
||||
for i := 1; i < tt.count; i++ {
|
||||
assert.Equal(t, tt.want[i], branches[i].Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TODO:test pr branch
|
||||
}
|
||||
|
|
|
@ -133,8 +133,9 @@ type SearchRepoOptions struct {
|
|||
// None -> include forks AND non-forks
|
||||
// True -> include just forks
|
||||
// False -> include just non-forks
|
||||
Fork util.OptionalBool
|
||||
ForkID int64 // If Fork option is True, you can use this option to limit the forks of a special repo by repo id.
|
||||
Fork util.OptionalBool
|
||||
// If Fork option is True, you can use this option to limit the forks of a special repo by repo id.
|
||||
ForkFrom int64
|
||||
// None -> include templates AND non-templates
|
||||
// True -> include just templates
|
||||
// False -> include just non-templates
|
||||
|
@ -469,8 +470,8 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
|
|||
} else {
|
||||
cond = cond.And(builder.Eq{"is_fork": opts.Fork == util.OptionalBoolTrue})
|
||||
|
||||
if opts.ForkID > 0 && opts.Fork == util.OptionalBoolTrue {
|
||||
cond = cond.And(builder.Eq{"fork_id": opts.ForkID})
|
||||
if opts.ForkFrom > 0 && opts.Fork == util.OptionalBoolTrue {
|
||||
cond = cond.And(builder.Eq{"fork_id": opts.ForkFrom})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -983,11 +983,15 @@ func renderCode(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
baseRepo := ctx.Repo.Repository
|
||||
if ctx.Repo.Repository.IsFork {
|
||||
baseRepo = ctx.Repo.Repository.BaseRepo
|
||||
opts := &git_model.FindRecentlyPushedNewBranchesOptions{
|
||||
Actor: ctx.Doer,
|
||||
Repo: ctx.Repo.Repository,
|
||||
BaseRepo: ctx.Repo.Repository,
|
||||
}
|
||||
branches, err := git_model.FindRecentlyPushedNewBranches(ctx, baseRepo, ctx.Doer, 0)
|
||||
if ctx.Repo.Repository.IsFork {
|
||||
opts.BaseRepo = ctx.Repo.Repository.BaseRepo
|
||||
}
|
||||
branches, err := git_model.FindRecentlyPushedNewBranches(ctx, opts)
|
||||
if err != nil {
|
||||
ctx.ServerError("FindRecentlyPushedNewBranches", err)
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue