Some repository refactors (#17950)

* some repository refactors

* remove unnecessary code

* Fix test

* Remove unnecessary banner
This commit is contained in:
Lunny Xiao 2021-12-12 23:48:20 +08:00 committed by GitHub
parent 0a7e8327a0
commit 5723240490
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
88 changed files with 1363 additions and 1388 deletions

View file

@ -14,7 +14,6 @@ import (
"sort"
"strconv"
"strings"
"time"
"unicode/utf8"
_ "image/jpeg" // Needed for jpeg support
@ -218,7 +217,7 @@ func getReviewers(ctx context.Context, repo *repo_model.Repository, doerID, post
"SELECT uid AS user_id FROM `org_user` WHERE org_id = ? "+
") AND id NOT IN (?, ?) ORDER BY name",
repo.ID, perm.AccessModeRead,
repo.ID, RepoWatchModeNormal, RepoWatchModeAuto,
repo.ID, repo_model.WatchModeNormal, repo_model.WatchModeAuto,
repo.OwnerID,
doerID, posterID).
Find(&users); err != nil {
@ -280,7 +279,7 @@ func CanUserForkRepo(user *user_model.User, repo *repo_model.Repository) (bool,
if user == nil {
return false, nil
}
if repo.OwnerID != user.ID && !HasForkedRepo(user.ID, repo.ID) {
if repo.OwnerID != user.ID && !repo_model.HasForkedRepo(user.ID, repo.ID) {
return true, nil
}
ownedOrgs, err := GetOrgsCanCreateRepoByUserID(user.ID)
@ -288,7 +287,7 @@ func CanUserForkRepo(user *user_model.User, repo *repo_model.Repository) (bool,
return false, err
}
for _, org := range ownedOrgs {
if repo.OwnerID != org.ID && !HasForkedRepo(org.ID, repo.ID) {
if repo.OwnerID != org.ID && !repo_model.HasForkedRepo(org.ID, repo.ID) {
return true, nil
}
}
@ -317,24 +316,6 @@ func CanUserDelete(repo *repo_model.Repository, user *user_model.User) (bool, er
return false, nil
}
// GetRepoReaders returns all users that have explicit read access or higher to the repository.
func GetRepoReaders(repo *repo_model.Repository) (_ []*user_model.User, err error) {
return getUsersWithAccessMode(db.DefaultContext, repo, perm.AccessModeRead)
}
// GetRepoWriters returns all users that have write access to the repository.
func GetRepoWriters(repo *repo_model.Repository) (_ []*user_model.User, err error) {
return getUsersWithAccessMode(db.DefaultContext, repo, perm.AccessModeWrite)
}
// IsRepoReader returns true if user has explicit read access or higher to the repository.
func IsRepoReader(repo *repo_model.Repository, userID int64) (bool, error) {
if repo.OwnerID == userID {
return true, nil
}
return db.GetEngine(db.DefaultContext).Where("repo_id = ? AND user_id = ? AND mode >= ?", repo.ID, userID, perm.AccessModeRead).Get(&Access{})
}
// getUsersWithAccessMode returns users that have at least given access mode to the repository.
func getUsersWithAccessMode(ctx context.Context, repo *repo_model.Repository, mode perm.AccessMode) (_ []*user_model.User, err error) {
if err = repo.GetOwner(ctx); err != nil {
@ -372,35 +353,6 @@ func SetRepoReadBy(repoID, userID int64) error {
return setRepoNotificationStatusReadIfUnread(db.GetEngine(db.DefaultContext), userID, repoID)
}
// 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 := repo_model.IsRepositoryExist(u, name)
if err != nil {
return fmt.Errorf("IsRepositoryExist: %v", err)
} else if has {
return ErrRepoAlreadyExist{u.Name, name}
}
repoPath := repo_model.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
}
// CreateRepoOptions contains the create repository options
type CreateRepoOptions struct {
Name string
@ -421,13 +373,6 @@ type CreateRepoOptions struct {
MirrorInterval string
}
// ForkRepoOptions contains the fork repository options
type ForkRepoOptions struct {
BaseRepo *repo_model.Repository
Name string
Description string
}
// GetRepoInitFile returns repository init files
func GetRepoInitFile(tp, name string) ([]byte, error) {
cleanedName := strings.TrimLeft(path.Clean("/"+name), "/")
@ -457,23 +402,9 @@ func GetRepoInitFile(tp, name string) ([]byte, error) {
}
}
var (
reservedRepoNames = []string{".", ".."}
reservedRepoPatterns = []string{"*.git", "*.wiki", "*.rss", "*.atom"}
)
// IsUsableRepoName returns true when repository is usable
func IsUsableRepoName(name string) error {
if db.AlphaDashDotPattern.MatchString(name) {
// Note: usually this error is normally caught up earlier in the UI
return db.ErrNameCharsNotAllowed{Name: name}
}
return db.IsUsableName(reservedRepoNames, reservedRepoPatterns, name)
}
// CreateRepository creates a repository for the user/organization.
func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository, overwriteOrAdopt bool) (err error) {
if err = IsUsableRepoName(repo.Name); err != nil {
if err = repo_model.IsUsableRepoName(repo.Name); err != nil {
return err
}
@ -481,7 +412,10 @@ func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_
if err != nil {
return fmt.Errorf("IsRepositoryExist: %v", err)
} else if has {
return ErrRepoAlreadyExist{u.Name, repo.Name}
return repo_model.ErrRepoAlreadyExist{
Uname: u.Name,
Name: repo.Name,
}
}
repoPath := repo_model.RepoPath(u.Name, repo.Name)
@ -492,7 +426,7 @@ func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_
}
if !overwriteOrAdopt && isExist {
log.Error("Files already exist in %s and we are not going to adopt or delete.", repoPath)
return ErrRepoFilesAlreadyExist{
return repo_model.ErrRepoFilesAlreadyExist{
Uname: u.Name,
Name: repo.Name,
}
@ -501,7 +435,7 @@ func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_
if err = db.Insert(ctx, repo); err != nil {
return err
}
if err = deleteRepoRedirect(db.GetEngine(ctx), u.ID, repo.Name); err != nil {
if err = repo_model.DeleteRedirect(ctx, u.ID, repo.Name); err != nil {
return err
}
@ -578,7 +512,7 @@ func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_
}
if setting.Service.AutoWatchNewRepos {
if err = watchRepo(db.GetEngine(ctx), doer.ID, repo.ID, true); err != nil {
if err = repo_model.WatchRepoCtx(ctx, doer.ID, repo.ID, true); err != nil {
return fmt.Errorf("watchRepo: %v", err)
}
}
@ -633,67 +567,6 @@ func DecrementRepoForkNum(ctx context.Context, repoID int64) error {
return err
}
// ChangeRepositoryName changes all corresponding setting from old repository name to new one.
func ChangeRepositoryName(doer *user_model.User, repo *repo_model.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 := repo_model.IsRepositoryExist(repo.Owner, newRepoName)
if err != nil {
return fmt.Errorf("IsRepositoryExist: %v", err)
} else if has {
return ErrRepoAlreadyExist{repo.Owner.Name, newRepoName}
}
newRepoPath := repo_model.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, repo_model.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 := newRepoRedirect(db.GetEngine(ctx), repo.Owner.ID, repo.ID, oldRepoName, newRepoName); err != nil {
return err
}
return committer.Commit()
}
func getRepositoriesByForkID(e db.Engine, forkID int64) ([]*repo_model.Repository, error) {
repos := make([]*repo_model.Repository, 0, 10)
return repos, e.
Where("fork_id=?", forkID).
Find(&repos)
}
// GetRepositoriesByForkID returns all repositories with given fork ID.
func GetRepositoriesByForkID(forkID int64) ([]*repo_model.Repository, error) {
return getRepositoriesByForkID(db.GetEngine(db.DefaultContext), forkID)
}
func updateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) {
repo.LowerName = strings.ToLower(repo.Name)
@ -740,7 +613,7 @@ func updateRepository(ctx context.Context, repo *repo_model.Repository, visibili
return err
}
forkRepos, err := getRepositoriesByForkID(e, repo.ID)
forkRepos, err := repo_model.GetRepositoriesByForkID(ctx, repo.ID)
if err != nil {
return fmt.Errorf("getRepositoriesByForkID: %v", err)
}
@ -775,58 +648,6 @@ func UpdateRepository(repo *repo_model.Repository, visibilityChanged bool) (err
return committer.Commit()
}
// 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(&repo_model.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
}
// UpdateRepositoryUnits updates a repository's units
func UpdateRepositoryUnits(repo *repo_model.Repository, units []repo_model.RepoUnit, deleteUnitTypes []unit.Type) (err error) {
ctx, committer, err := db.TxContext()
if err != nil {
return err
}
defer committer.Close()
// Delete existing settings of units before adding again
for _, u := range units {
deleteUnitTypes = append(deleteUnitTypes, u.Type)
}
if _, err = db.GetEngine(ctx).Where("repo_id = ?", repo.ID).In("type", deleteUnitTypes).Delete(new(repo_model.RepoUnit)); err != nil {
return err
}
if len(units) > 0 {
if err = db.Insert(ctx, units); err != nil {
return err
}
}
return committer.Commit()
}
// DeleteRepository deletes a repository for a user or organization.
// make sure if you call this func to close open sessions (sqlite will otherwise get a deadlock)
func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
@ -927,11 +748,11 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
&repo_model.PushMirror{RepoID: repoID},
&Release{RepoID: repoID},
&repo_model.RepoIndexerStatus{RepoID: repoID},
&RepoRedirect{RedirectRepoID: repoID},
&repo_model.Redirect{RedirectRepoID: repoID},
&repo_model.RepoUnit{RepoID: repoID},
&Star{RepoID: repoID},
&repo_model.Star{RepoID: repoID},
&Task{RepoID: repoID},
&Watch{RepoID: repoID},
&repo_model.Watch{RepoID: repoID},
&webhook.Webhook{RepoID: repoID},
); err != nil {
return fmt.Errorf("deleteBeans: %v", err)
@ -964,7 +785,7 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
}
if len(repo.Topics) > 0 {
if err := removeTopicsFromRepo(sess, repo.ID); err != nil {
if err := repo_model.RemoveTopicsFromRepo(ctx, repo.ID); err != nil {
return err
}
}
@ -1261,76 +1082,6 @@ func CheckRepoStats(ctx context.Context) error {
return nil
}
// SetArchiveRepoState sets if a repo is archived
func SetArchiveRepoState(repo *repo_model.Repository, isArchived bool) (err error) {
repo.IsArchived = isArchived
_, err = db.GetEngine(db.DefaultContext).Where("id = ?", repo.ID).Cols("is_archived").NoAutoTime().Update(repo)
return
}
// ___________ __
// \_ _____/__________| | __
// | __)/ _ \_ __ \ |/ /
// | \( <_> ) | \/ <
// \___ / \____/|__| |__|_ \
// \/ \/
// GetForkedRepo checks if given user has already forked a repository with given ID.
func GetForkedRepo(ownerID, repoID int64) *repo_model.Repository {
repo := new(repo_model.Repository)
has, _ := db.GetEngine(db.DefaultContext).
Where("owner_id=? AND fork_id=?", ownerID, repoID).
Get(repo)
if has {
return repo
}
return nil
}
// HasForkedRepo checks if given user has already forked a repository with given ID.
func HasForkedRepo(ownerID, repoID int64) bool {
has, _ := db.GetEngine(db.DefaultContext).
Table("repository").
Where("owner_id=? AND fork_id=?", ownerID, repoID).
Exist()
return has
}
// GetForks returns all the forks of the repository
func GetForks(repo *repo_model.Repository, listOptions db.ListOptions) ([]*repo_model.Repository, error) {
if listOptions.Page == 0 {
forks := make([]*repo_model.Repository, 0, repo.NumForks)
return forks, db.GetEngine(db.DefaultContext).Find(&forks, &repo_model.Repository{ForkID: repo.ID})
}
sess := db.GetPaginatedSession(&listOptions)
forks := make([]*repo_model.Repository, 0, listOptions.PageSize)
return forks, sess.Find(&forks, &repo_model.Repository{ForkID: repo.ID})
}
// GetUserFork return user forked repository from this repository, if not forked return nil
func GetUserFork(repoID, userID int64) (*repo_model.Repository, error) {
var forkedRepo repo_model.Repository
has, err := db.GetEngine(db.DefaultContext).Where("fork_id = ?", repoID).And("owner_id = ?", userID).Get(&forkedRepo)
if err != nil {
return nil, err
}
if !has {
return nil, nil
}
return &forkedRepo, nil
}
func updateRepositoryCols(e db.Engine, repo *repo_model.Repository, cols ...string) error {
_, err := e.ID(repo.ID).Cols(cols...).Update(repo)
return err
}
// UpdateRepositoryCols updates repository's columns
func UpdateRepositoryCols(repo *repo_model.Repository, cols ...string) error {
return updateRepositoryCols(db.GetEngine(db.DefaultContext), repo, cols...)
}
func updateUserStarNumbers(users []user_model.User) error {
ctx, committer, err := db.TxContext()
if err != nil {
@ -1370,28 +1121,6 @@ func DoctorUserStarNum() (err error) {
return
}
// IterateRepository iterate repositories
func IterateRepository(f func(repo *repo_model.Repository) error) error {
var start int
batchSize := setting.Database.IterateBufferSize
for {
repos := make([]*repo_model.Repository, 0, batchSize)
if err := db.GetEngine(db.DefaultContext).Limit(batchSize, start).Find(&repos); err != nil {
return err
}
if len(repos) == 0 {
return nil
}
start += len(repos)
for _, repo := range repos {
if err := f(repo); err != nil {
return err
}
}
}
}
// LinkedRepository returns the linked repo if any
func LinkedRepository(a *repo_model.Attachment) (*repo_model.Repository, unit.Type, error) {
if a.IssueID != 0 {