mirror of
https://github.com/go-gitea/gitea.git
synced 2024-09-12 00:34:20 -04:00
There's a bug in #25715: If user pushed a commit into another repo with same branch name, the no-related repo will display the recently pushed notification incorrectly. It is simple to fix this, we should match the repo id in the sql query. ![image](https://github.com/go-gitea/gitea/assets/18380374/9411a926-16f1-419e-a1b5-e953af38bab1) The latest commit is 2 weeks ago. ![image](https://github.com/go-gitea/gitea/assets/18380374/52f9ab22-4999-43ac-a86f-6d36fb1e0411) The notification comes from another repo with same branch name: ![image](https://github.com/go-gitea/gitea/assets/18380374/a26bc335-8e5b-4b9c-a965-c3dc3fa6f252) After: In forked repo: ![image](https://github.com/go-gitea/gitea/assets/18380374/ce6ffc35-deb7-4be7-8b09-184207392f32) New PR Link will redirect to the original repo: ![image](https://github.com/go-gitea/gitea/assets/18380374/7b98e76f-0c75-494c-9462-80cf9f98e786) In the original repo: ![image](https://github.com/go-gitea/gitea/assets/18380374/5f6a821b-e51a-4bbd-9980-d9eb94a3c847) New PR Link: ![image](https://github.com/go-gitea/gitea/assets/18380374/1ce8c879-9f11-4312-8c32-695d7d9af0df) In the same repo: ![image](https://github.com/go-gitea/gitea/assets/18380374/64b56073-4d0e-40c4-b8a0-80be7a775f69) New PR Link: ![image](https://github.com/go-gitea/gitea/assets/18380374/96e1b6a3-fb98-40ee-b2ee-648039fb0dcf) 08/15 Update: Follow #26257, added permission check and logic fix mentioned in https://github.com/go-gitea/gitea/pull/26257#discussion_r1294085203 2024/04/25 Update: Fix #30611 --------- Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
153 lines
4.1 KiB
Go
153 lines
4.1 KiB
Go
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package git
|
|
|
|
import (
|
|
"context"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
user_model "code.gitea.io/gitea/models/user"
|
|
"code.gitea.io/gitea/modules/container"
|
|
"code.gitea.io/gitea/modules/optional"
|
|
|
|
"xorm.io/builder"
|
|
)
|
|
|
|
type BranchList []*Branch
|
|
|
|
func (branches BranchList) LoadDeletedBy(ctx context.Context) error {
|
|
ids := container.FilterSlice(branches, func(branch *Branch) (int64, bool) {
|
|
return branch.DeletedByID, branch.IsDeleted
|
|
})
|
|
|
|
usersMap := make(map[int64]*user_model.User, len(ids))
|
|
if err := db.GetEngine(ctx).In("id", ids).Find(&usersMap); err != nil {
|
|
return err
|
|
}
|
|
for _, branch := range branches {
|
|
if !branch.IsDeleted {
|
|
continue
|
|
}
|
|
branch.DeletedBy = usersMap[branch.DeletedByID]
|
|
if branch.DeletedBy == nil {
|
|
branch.DeletedBy = user_model.NewGhostUser()
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (branches BranchList) LoadPusher(ctx context.Context) error {
|
|
ids := container.FilterSlice(branches, func(branch *Branch) (int64, bool) {
|
|
// pusher_id maybe zero because some branches are sync by backend with no pusher
|
|
return branch.PusherID, branch.PusherID > 0
|
|
})
|
|
|
|
usersMap := make(map[int64]*user_model.User, len(ids))
|
|
if err := db.GetEngine(ctx).In("id", ids).Find(&usersMap); err != nil {
|
|
return err
|
|
}
|
|
for _, branch := range branches {
|
|
if branch.PusherID <= 0 {
|
|
continue
|
|
}
|
|
branch.Pusher = usersMap[branch.PusherID]
|
|
if branch.Pusher == nil {
|
|
branch.Pusher = user_model.NewGhostUser()
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (branches BranchList) LoadRepo(ctx context.Context) error {
|
|
ids := container.FilterSlice(branches, func(branch *Branch) (int64, bool) {
|
|
return branch.RepoID, branch.RepoID > 0 && branch.Repo == nil
|
|
})
|
|
|
|
reposMap := make(map[int64]*repo_model.Repository, len(ids))
|
|
if err := db.GetEngine(ctx).In("id", ids).Find(&reposMap); err != nil {
|
|
return err
|
|
}
|
|
for _, branch := range branches {
|
|
if branch.RepoID <= 0 || branch.Repo != nil {
|
|
continue
|
|
}
|
|
branch.Repo = reposMap[branch.RepoID]
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type FindBranchOptions struct {
|
|
db.ListOptions
|
|
RepoID int64
|
|
ExcludeBranchNames []string
|
|
IsDeletedBranch optional.Option[bool]
|
|
OrderBy string
|
|
Keyword string
|
|
}
|
|
|
|
func (opts FindBranchOptions) ToConds() builder.Cond {
|
|
cond := builder.NewCond()
|
|
if opts.RepoID > 0 {
|
|
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
|
}
|
|
|
|
if len(opts.ExcludeBranchNames) > 0 {
|
|
cond = cond.And(builder.NotIn("name", opts.ExcludeBranchNames))
|
|
}
|
|
if opts.IsDeletedBranch.Has() {
|
|
cond = cond.And(builder.Eq{"is_deleted": opts.IsDeletedBranch.Value()})
|
|
}
|
|
if opts.Keyword != "" {
|
|
cond = cond.And(builder.Like{"name", opts.Keyword})
|
|
}
|
|
return cond
|
|
}
|
|
|
|
func (opts FindBranchOptions) ToOrders() string {
|
|
orderBy := opts.OrderBy
|
|
if opts.IsDeletedBranch.ValueOrDefault(true) { // if deleted branch included, put them at the end
|
|
if orderBy != "" {
|
|
orderBy += ", "
|
|
}
|
|
orderBy += "is_deleted ASC"
|
|
}
|
|
if orderBy == "" {
|
|
// the commit_time might be the same, so add the "name" to make sure the order is stable
|
|
return "commit_time DESC, name ASC"
|
|
}
|
|
|
|
return orderBy
|
|
}
|
|
|
|
func FindBranchNames(ctx context.Context, opts FindBranchOptions) ([]string, error) {
|
|
sess := db.GetEngine(ctx).Select("name").Where(opts.ToConds())
|
|
if opts.PageSize > 0 && !opts.IsListAll() {
|
|
sess = db.SetSessionPagination(sess, &opts.ListOptions)
|
|
}
|
|
|
|
var branches []string
|
|
if err := sess.Table("branch").OrderBy(opts.ToOrders()).Find(&branches); err != nil {
|
|
return nil, err
|
|
}
|
|
return branches, nil
|
|
}
|
|
|
|
func FindBranchesByRepoAndBranchName(ctx context.Context, repoBranches map[int64]string) (map[int64]string, error) {
|
|
cond := builder.NewCond()
|
|
for repoID, branchName := range repoBranches {
|
|
cond = cond.Or(builder.And(builder.Eq{"repo_id": repoID}, builder.Eq{"name": branchName}))
|
|
}
|
|
var branches []*Branch
|
|
if err := db.GetEngine(ctx).
|
|
Where(cond).Find(&branches); err != nil {
|
|
return nil, err
|
|
}
|
|
branchMap := make(map[int64]string, len(branches))
|
|
for _, branch := range branches {
|
|
branchMap[branch.RepoID] = branch.CommitID
|
|
}
|
|
return branchMap, nil
|
|
}
|