mirror of
https://github.com/go-gitea/gitea.git
synced 2026-04-04 18:56:28 +02:00
162 lines
4.1 KiB
Go
162 lines
4.1 KiB
Go
// Copyright 2025 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package group
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
group_model "code.gitea.io/gitea/models/group"
|
|
"code.gitea.io/gitea/models/organization"
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
user_model "code.gitea.io/gitea/models/user"
|
|
"code.gitea.io/gitea/modules/gitrepo"
|
|
"code.gitea.io/gitea/modules/log"
|
|
"code.gitea.io/gitea/modules/setting"
|
|
"code.gitea.io/gitea/modules/util"
|
|
)
|
|
|
|
func NewGroup(ctx context.Context, g *group_model.Group) error {
|
|
var err error
|
|
if len(g.Name) == 0 {
|
|
return util.NewInvalidArgumentErrorf("empty group name")
|
|
}
|
|
has, err := db.ExistByID[user_model.User](ctx, g.OwnerID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !has {
|
|
return organization.ErrOrgNotExist{ID: g.OwnerID}
|
|
}
|
|
g.LowerName = strings.ToLower(g.Name)
|
|
ctx, committer, err := db.TxContext(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer committer.Close()
|
|
|
|
if err = db.Insert(ctx, g); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = RecalculateGroupAccess(ctx, g, true); err != nil {
|
|
return err
|
|
}
|
|
|
|
return committer.Commit()
|
|
}
|
|
|
|
func MoveRepositoryToGroup(ctx context.Context, repo *repo_model.Repository, newGroupID int64, groupSortOrder int) error {
|
|
sess := db.GetEngine(ctx)
|
|
if newGroupID > 0 {
|
|
newGroup, err := group_model.GetGroupByID(ctx, newGroupID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if newGroup.OwnerID != repo.OwnerID {
|
|
return fmt.Errorf("repo[%d]'s ownerID is not equal to new parent group[%d]'s owner ID", repo.ID, newGroup.ID)
|
|
}
|
|
}
|
|
repo.GroupID = newGroupID
|
|
repo.GroupSortOrder = groupSortOrder
|
|
cnt, err := sess.
|
|
Table("repository").
|
|
ID(repo.ID).
|
|
MustCols("group_id").
|
|
Update(repo)
|
|
log.Info("updated %d rows?", cnt)
|
|
return err
|
|
}
|
|
|
|
type MoveGroupOptions struct {
|
|
NewParent, ItemID int64
|
|
IsGroup bool
|
|
NewPos int
|
|
}
|
|
|
|
func MoveGroupItem(ctx context.Context, opts MoveGroupOptions, doer *user_model.User) (err error) {
|
|
var committer db.Committer
|
|
ctx, committer, err = db.TxContext(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer committer.Close()
|
|
var parentGroup *group_model.Group
|
|
if opts.NewParent > 0 {
|
|
parentGroup, err = group_model.GetGroupByID(ctx, opts.NewParent)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
canAccessNewParent, err := parentGroup.CanAccess(ctx, doer)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !canAccessNewParent {
|
|
return errors.New("cannot access new parent group")
|
|
}
|
|
|
|
err = parentGroup.LoadSubgroups(ctx, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if opts.IsGroup {
|
|
var group *group_model.Group
|
|
group, err = group_model.GetGroupByID(ctx, opts.ItemID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if opts.NewPos < 0 && parentGroup != nil {
|
|
opts.NewPos = len(parentGroup.Subgroups)
|
|
}
|
|
if group.ParentGroupID != opts.NewParent || group.SortOrder != opts.NewPos {
|
|
if err = group_model.MoveGroup(ctx, group, opts.NewParent, opts.NewPos); err != nil {
|
|
return err
|
|
}
|
|
if err = RecalculateGroupAccess(ctx, group, false); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
} else {
|
|
var repo *repo_model.Repository
|
|
repo, err = repo_model.GetRepositoryByID(ctx, opts.ItemID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if opts.NewPos < 0 {
|
|
var repoCount int64
|
|
repoCount, err = repo_model.CountRepository(ctx, repo_model.SearchRepoOptions{
|
|
GroupID: opts.NewParent,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
opts.NewPos = int(repoCount)
|
|
}
|
|
if repo.GroupID != opts.NewParent || repo.GroupSortOrder != opts.NewPos {
|
|
ndir := filepath.Dir(filepath.Join(setting.RepoRootPath, filepath.FromSlash(repo_model.RelativePath(repo.OwnerName, repo.Name, opts.NewParent))))
|
|
_, err = os.Stat(ndir)
|
|
if err != nil {
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
_ = os.MkdirAll(ndir, 0o755)
|
|
} else {
|
|
return err
|
|
}
|
|
}
|
|
if err = gitrepo.RenameRepository(ctx, repo, repo_model.StorageRepo(repo_model.RelativePath(repo.OwnerName, repo.Name, opts.NewParent))); err != nil {
|
|
return err
|
|
}
|
|
if err = MoveRepositoryToGroup(ctx, repo, opts.NewParent, opts.NewPos); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return committer.Commit()
|
|
}
|