Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
5.0 KiB
179 lines
5.0 KiB
// Copyright 2021 The Gitea Authors. All rights reserved. |
|
// Use of this source code is governed by a MIT-style |
|
// license that can be found in the LICENSE file. |
|
|
|
package repo |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"strings" |
|
"time" |
|
|
|
"code.gitea.io/gitea/models/db" |
|
user_model "code.gitea.io/gitea/models/user" |
|
"code.gitea.io/gitea/modules/log" |
|
"code.gitea.io/gitea/modules/util" |
|
) |
|
|
|
// UpdateRepositoryOwnerNames updates repository owner_names (this should only be used when the ownerName has changed case) |
|
func UpdateRepositoryOwnerNames(ownerID int64, ownerName string) error { |
|
if ownerID == 0 { |
|
return nil |
|
} |
|
ctx, committer, err := db.TxContext() |
|
if err != nil { |
|
return err |
|
} |
|
defer committer.Close() |
|
|
|
if _, err := db.GetEngine(ctx).Where("owner_id = ?", ownerID).Cols("owner_name").Update(&Repository{ |
|
OwnerName: ownerName, |
|
}); err != nil { |
|
return err |
|
} |
|
|
|
return committer.Commit() |
|
} |
|
|
|
// UpdateRepositoryUpdatedTime updates a repository's updated time |
|
func UpdateRepositoryUpdatedTime(repoID int64, updateTime time.Time) error { |
|
_, err := db.GetEngine(db.DefaultContext).Exec("UPDATE repository SET updated_unix = ? WHERE id = ?", updateTime.Unix(), repoID) |
|
return err |
|
} |
|
|
|
// UpdateRepositoryColsCtx updates repository's columns |
|
func UpdateRepositoryColsCtx(ctx context.Context, repo *Repository, cols ...string) error { |
|
_, err := db.GetEngine(ctx).ID(repo.ID).Cols(cols...).Update(repo) |
|
return err |
|
} |
|
|
|
// UpdateRepositoryCols updates repository's columns |
|
func UpdateRepositoryCols(repo *Repository, cols ...string) error { |
|
return UpdateRepositoryColsCtx(db.DefaultContext, repo, cols...) |
|
} |
|
|
|
// ErrReachLimitOfRepo represents a "ReachLimitOfRepo" kind of error. |
|
type ErrReachLimitOfRepo struct { |
|
Limit int |
|
} |
|
|
|
// IsErrReachLimitOfRepo checks if an error is a ErrReachLimitOfRepo. |
|
func IsErrReachLimitOfRepo(err error) bool { |
|
_, ok := err.(ErrReachLimitOfRepo) |
|
return ok |
|
} |
|
|
|
func (err ErrReachLimitOfRepo) Error() string { |
|
return fmt.Sprintf("user has reached maximum limit of repositories [limit: %d]", err.Limit) |
|
} |
|
|
|
// ErrRepoAlreadyExist represents a "RepoAlreadyExist" kind of error. |
|
type ErrRepoAlreadyExist struct { |
|
Uname string |
|
Name string |
|
} |
|
|
|
// IsErrRepoAlreadyExist checks if an error is a ErrRepoAlreadyExist. |
|
func IsErrRepoAlreadyExist(err error) bool { |
|
_, ok := err.(ErrRepoAlreadyExist) |
|
return ok |
|
} |
|
|
|
func (err ErrRepoAlreadyExist) Error() string { |
|
return fmt.Sprintf("repository already exists [uname: %s, name: %s]", err.Uname, err.Name) |
|
} |
|
|
|
// ErrRepoFilesAlreadyExist represents a "RepoFilesAlreadyExist" kind of error. |
|
type ErrRepoFilesAlreadyExist struct { |
|
Uname string |
|
Name string |
|
} |
|
|
|
// IsErrRepoFilesAlreadyExist checks if an error is a ErrRepoAlreadyExist. |
|
func IsErrRepoFilesAlreadyExist(err error) bool { |
|
_, ok := err.(ErrRepoFilesAlreadyExist) |
|
return ok |
|
} |
|
|
|
func (err ErrRepoFilesAlreadyExist) Error() string { |
|
return fmt.Sprintf("repository files already exist [uname: %s, name: %s]", err.Uname, err.Name) |
|
} |
|
|
|
// CheckCreateRepository check if could created a repository |
|
func CheckCreateRepository(doer, u *user_model.User, name string, overwriteOrAdopt bool) error { |
|
if !doer.CanCreateRepo() { |
|
return ErrReachLimitOfRepo{u.MaxRepoCreation} |
|
} |
|
|
|
if err := IsUsableRepoName(name); err != nil { |
|
return err |
|
} |
|
|
|
has, err := IsRepositoryExist(u, name) |
|
if err != nil { |
|
return fmt.Errorf("IsRepositoryExist: %v", err) |
|
} else if has { |
|
return ErrRepoAlreadyExist{u.Name, name} |
|
} |
|
|
|
repoPath := RepoPath(u.Name, name) |
|
isExist, err := util.IsExist(repoPath) |
|
if err != nil { |
|
log.Error("Unable to check if %s exists. Error: %v", repoPath, err) |
|
return err |
|
} |
|
if !overwriteOrAdopt && isExist { |
|
return ErrRepoFilesAlreadyExist{u.Name, name} |
|
} |
|
return nil |
|
} |
|
|
|
// ChangeRepositoryName changes all corresponding setting from old repository name to new one. |
|
func ChangeRepositoryName(doer *user_model.User, repo *Repository, newRepoName string) (err error) { |
|
oldRepoName := repo.Name |
|
newRepoName = strings.ToLower(newRepoName) |
|
if err = IsUsableRepoName(newRepoName); err != nil { |
|
return err |
|
} |
|
|
|
if err := repo.GetOwner(db.DefaultContext); err != nil { |
|
return err |
|
} |
|
|
|
has, err := IsRepositoryExist(repo.Owner, newRepoName) |
|
if err != nil { |
|
return fmt.Errorf("IsRepositoryExist: %v", err) |
|
} else if has { |
|
return ErrRepoAlreadyExist{repo.Owner.Name, newRepoName} |
|
} |
|
|
|
newRepoPath := RepoPath(repo.Owner.Name, newRepoName) |
|
if err = util.Rename(repo.RepoPath(), newRepoPath); err != nil { |
|
return fmt.Errorf("rename repository directory: %v", err) |
|
} |
|
|
|
wikiPath := repo.WikiPath() |
|
isExist, err := util.IsExist(wikiPath) |
|
if err != nil { |
|
log.Error("Unable to check if %s exists. Error: %v", wikiPath, err) |
|
return err |
|
} |
|
if isExist { |
|
if err = util.Rename(wikiPath, WikiPath(repo.Owner.Name, newRepoName)); err != nil { |
|
return fmt.Errorf("rename repository wiki: %v", err) |
|
} |
|
} |
|
|
|
ctx, committer, err := db.TxContext() |
|
if err != nil { |
|
return err |
|
} |
|
defer committer.Close() |
|
|
|
if err := NewRedirect(ctx, repo.Owner.ID, repo.ID, oldRepoName, newRepoName); err != nil { |
|
return err |
|
} |
|
|
|
return committer.Commit() |
|
}
|
|
|