Changes
76 changed files (+1755/-1673)
-
-
@@ -17,6 +17,7 @@ import (asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/auth" "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/git" "code.gitea.io/gitea/modules/graceful"
-
@@ -722,9 +723,9 @@ func runRepoSyncReleases(_ *cli.Context) error {log.Trace("Synchronizing repository releases (this may take a while)") for page := 1; ; page++ { repos, count, err := models.SearchRepositoryByName(&models.SearchRepoOptions{ repos, count, err := repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: models.RepositoryListDefaultPageSize, PageSize: repo_model.RepositoryListDefaultPageSize, Page: page, }, Private: true,
-
-
-
@@ -393,7 +393,7 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) {// check readable repositories by doer/actor if opts.Actor == nil || !opts.Actor.IsAdmin { cond = cond.And(builder.In("repo_id", AccessibleRepoIDsQuery(opts.Actor))) cond = cond.And(builder.In("repo_id", repo_model.AccessibleRepoIDsQuery(opts.Actor))) } if opts.RequestedRepo != nil {
-
-
-
@@ -190,6 +190,13 @@ func GetDeployKeyByRepo(ctx context.Context, keyID, repoID int64) (*DeployKey, ereturn key, nil } // IsDeployKeyExistByKeyID return true if there is at least one deploykey with the key id func IsDeployKeyExistByKeyID(ctx context.Context, keyID int64) (bool, error) { return db.GetEngine(ctx). Where("key_id = ?", keyID). Get(new(DeployKey)) } // UpdateDeployKeyCols updates deploy key information in the specified columns. func UpdateDeployKeyCols(key *DeployKey, cols ...string) error { _, err := db.GetEngine(db.DefaultContext).ID(key.ID).Cols(cols...).Update(key)
-
-
-
@@ -271,11 +271,6 @@ func MaxBatchInsertSize(bean interface{}) int {return 999 / len(t.ColumnsSeq()) } // Count returns records number according struct's fields as database query conditions func Count(bean interface{}) (int64, error) { return x.Count(bean) } // IsTableNotEmpty returns true if table has at least one record func IsTableNotEmpty(tableName string) (bool, error) { return x.Table(tableName).Exist()
-
-
-
@@ -1343,6 +1343,48 @@ func (opts *IssuesOptions) setupSessionNoLimit(sess *xorm.Session) {} } // teamUnitsRepoCond returns query condition for those repo id in the special org team with special units access func teamUnitsRepoCond(id string, userID, orgID, teamID int64, units ...unit.Type) builder.Cond { return builder.In(id, builder.Select("repo_id").From("team_repo").Where( builder.Eq{ "team_id": teamID, }.And( builder.Or( // Check if the user is member of the team. builder.In( "team_id", builder.Select("team_id").From("team_user").Where( builder.Eq{ "uid": userID, }, ), ), // Check if the user is in the owner team of the organisation. builder.Exists(builder.Select("team_id").From("team_user"). Where(builder.Eq{ "org_id": orgID, "team_id": builder.Select("id").From("team").Where( builder.Eq{ "org_id": orgID, "lower_name": strings.ToLower(organization.OwnerTeamName), }), "uid": userID, }), ), )).And( builder.In( "team_id", builder.Select("team_id").From("team_unit").Where( builder.Eq{ "`team_unit`.org_id": orgID, }.And( builder.In("`team_unit`.type", units), ), ), ), ), )) } // issuePullAccessibleRepoCond userID must not be zero, this condition require join repository table func issuePullAccessibleRepoCond(repoIDstr string, userID int64, org *organization.Organization, team *organization.Team, isPull bool) builder.Cond { cond := builder.NewCond()
-
@@ -1356,19 +1398,19 @@ func issuePullAccessibleRepoCond(repoIDstr string, userID int64, org *organizati} else { cond = cond.And( builder.Or( userOrgUnitRepoCond(repoIDstr, userID, org.ID, unitType), // team member repos userOrgPublicUnitRepoCond(userID, org.ID), // user org public non-member repos, TODO: check repo has issues repo_model.UserOrgUnitRepoCond(repoIDstr, userID, org.ID, unitType), // team member repos repo_model.UserOrgPublicUnitRepoCond(userID, org.ID), // user org public non-member repos, TODO: check repo has issues ), ) } } else { cond = cond.And( builder.Or( userOwnedRepoCond(userID), // owned repos userCollaborationRepoCond(repoIDstr, userID), // collaboration repos userAssignedRepoCond(repoIDstr, userID), // user has been assigned accessible public repos userMentionedRepoCond(repoIDstr, userID), // user has been mentioned accessible public repos userCreateIssueRepoCond(repoIDstr, userID, isPull), // user has created issue/pr accessible public repos repo_model.UserOwnedRepoCond(userID), // owned repos repo_model.UserCollaborationRepoCond(repoIDstr, userID), // collaboration repos repo_model.UserAssignedRepoCond(repoIDstr, userID), // user has been assigned accessible public repos repo_model.UserMentionedRepoCond(repoIDstr, userID), // user has been mentioned accessible public repos repo_model.UserCreateIssueRepoCond(repoIDstr, userID, isPull), // user has created issue/pr accessible public repos ), ) }
-
@@ -1434,7 +1476,7 @@ func GetRepoIDsForIssuesOptions(opts *IssuesOptions, user *user_model.User) ([]iopts.setupSessionNoLimit(sess) accessCond := accessibleRepositoryCondition(user) accessCond := repo_model.AccessibleRepositoryCondition(user) if err := sess.Where(accessCond). Distinct("issue.repo_id"). Table("issue").
-
-
-
@@ -75,7 +75,7 @@ func (issues IssueList) loadRepositories(ctx context.Context) ([]*repo_model.Rep} } } return valuesRepository(repoMaps), nil return repo_model.ValuesRepository(repoMaps), nil } // LoadRepositories loads issues' all repositories
-
-
-
@@ -26,7 +26,7 @@ func init() {} func newIssueUsers(ctx context.Context, repo *repo_model.Repository, issue *Issue) error { assignees, err := getRepoAssignees(ctx, repo) assignees, err := repo_model.GetRepoAssignees(ctx, repo) if err != nil { return fmt.Errorf("getAssignees: %v", err) }
-
-
-
@@ -142,7 +142,7 @@ func LFSObjectAccessible(user *user_model.User, oid string) (bool, error) {count, err := db.GetEngine(db.DefaultContext).Count(&LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}}) return count > 0, err } cond := accessibleRepositoryCondition(user) cond := repo_model.AccessibleRepositoryCondition(user) count, err := db.GetEngine(db.DefaultContext).Where(cond).Join("INNER", "repository", "`lfs_meta_object`.repository_id = `repository`.id").Count(&LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}}) return count > 0, err }
-
@@ -173,7 +173,7 @@ func LFSAutoAssociate(metas []*LFSMetaObject, user *user_model.User, repoID int6newMetas := make([]*LFSMetaObject, 0, len(metas)) cond := builder.In( "`lfs_meta_object`.repository_id", builder.Select("`repository`.id").From("repository").Where(accessibleRepositoryCondition(user)), builder.Select("`repository`.id").From("repository").Where(repo_model.AccessibleRepositoryCondition(user)), ) err = sess.Cols("oid").Where(cond).In("oid", oids...).GroupBy("oid").Find(&newMetas) if err != nil {
-
@@ -246,3 +246,12 @@ func CopyLFS(ctx context.Context, newRepo, oldRepo *repo_model.Repository) errorreturn nil } // GetRepoLFSSize return a repository's lfs files size func GetRepoLFSSize(ctx context.Context, repoID int64) (int64, error) { lfsSize, err := db.GetEngine(ctx).Where("repository_id = ?", repoID).SumInt(new(LFSMetaObject), "size") if err != nil { return 0, fmt.Errorf("updateSize: GetLFSMetaObjects: %v", err) } return lfsSize, nil }
-
-
-
@@ -266,10 +266,10 @@ func createOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, nreturn err } if issue.IsPull && !checkRepoUnitUser(ctx, issue.Repo, user, unit.TypePullRequests) { if issue.IsPull && !CheckRepoUnitUser(ctx, issue.Repo, user, unit.TypePullRequests) { continue } if !issue.IsPull && !checkRepoUnitUser(ctx, issue.Repo, user, unit.TypeIssues) { if !issue.IsPull && !CheckRepoUnitUser(ctx, issue.Repo, user, unit.TypeIssues) { continue }
-
@@ -510,9 +510,9 @@ func (nl NotificationList) getPendingRepoIDs() []int64 {} // LoadRepos loads repositories from database func (nl NotificationList) LoadRepos() (RepositoryList, []int, error) { func (nl NotificationList) LoadRepos() (repo_model.RepositoryList, []int, error) { if len(nl) == 0 { return RepositoryList{}, []int{}, nil return repo_model.RepositoryList{}, []int{}, nil } repoIDs := nl.getPendingRepoIDs()
-
@@ -548,7 +548,7 @@ func (nl NotificationList) LoadRepos() (RepositoryList, []int, error) {failed := []int{} reposList := make(RepositoryList, 0, len(repoIDs)) reposList := make(repo_model.RepositoryList, 0, len(repoIDs)) for i, notification := range nl { if notification.Repository == nil { notification.Repository = repos[notification.RepoID]
-
-
-
@@ -54,7 +54,7 @@ func GetUserOrgsList(user *user_model.User) ([]*MinimalOrg, error) {Join("LEFT", builder. Select("id as repo_id, owner_id as repo_owner_id"). From("repository"). Where(accessibleRepositoryCondition(user)), "`repository`.repo_owner_id = `team`.org_id"). Where(repo_model.AccessibleRepositoryCondition(user)), "`repository`.repo_owner_id = `team`.org_id"). Where("`team_user`.uid = ?", user.ID). GroupBy(groupByStr)
-
-
-
@@ -8,11 +8,7 @@ package modelsimport ( "context" "fmt" "os" "path" "strconv" "strings" "unicode/utf8" _ "image/jpeg" // Needed for jpeg support
-
@@ -47,11 +43,7 @@ func NewRepoContext() {} // CheckRepoUnitUser check whether user could visit the unit of this repository func CheckRepoUnitUser(repo *repo_model.Repository, user *user_model.User, unitType unit.Type) bool { return checkRepoUnitUser(db.DefaultContext, repo, user, unitType) } func checkRepoUnitUser(ctx context.Context, repo *repo_model.Repository, user *user_model.User, unitType unit.Type) bool { func CheckRepoUnitUser(ctx context.Context, repo *repo_model.Repository, user *user_model.User, unitType unit.Type) bool { if user != nil && user.IsAdmin { return true }
-
@@ -64,241 +56,6 @@ func checkRepoUnitUser(ctx context.Context, repo *repo_model.Repository, user *ureturn perm.CanRead(unitType) } func getRepoAssignees(ctx context.Context, repo *repo_model.Repository) (_ []*user_model.User, err error) { if err = repo.GetOwner(ctx); err != nil { return nil, err } e := db.GetEngine(ctx) userIDs := make([]int64, 0, 10) if err = e.Table("access"). Where("repo_id = ? AND mode >= ?", repo.ID, perm.AccessModeWrite). Select("user_id"). Find(&userIDs); err != nil { return nil, err } additionalUserIDs := make([]int64, 0, 10) if err = e.Table("team_user"). Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id"). Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id"). Where("`team_repo`.repo_id = ? AND `team_unit`.access_mode >= ?", repo.ID, perm.AccessModeWrite). Distinct("`team_user`.uid"). Select("`team_user`.uid"). Find(&additionalUserIDs); err != nil { return nil, err } uidMap := map[int64]bool{} i := 0 for _, uid := range userIDs { if uidMap[uid] { continue } uidMap[uid] = true userIDs[i] = uid i++ } userIDs = userIDs[:i] userIDs = append(userIDs, additionalUserIDs...) for _, uid := range additionalUserIDs { if uidMap[uid] { continue } userIDs[i] = uid i++ } userIDs = userIDs[:i] // Leave a seat for owner itself to append later, but if owner is an organization // and just waste 1 unit is cheaper than re-allocate memory once. users := make([]*user_model.User, 0, len(userIDs)+1) if len(userIDs) > 0 { if err = e.In("id", userIDs).Find(&users); err != nil { return nil, err } } if !repo.Owner.IsOrganization() && !uidMap[repo.OwnerID] { users = append(users, repo.Owner) } return users, nil } // GetRepoAssignees returns all users that have write access and can be assigned to issues // of the repository, func GetRepoAssignees(repo *repo_model.Repository) (_ []*user_model.User, err error) { return getRepoAssignees(db.DefaultContext, repo) } func getReviewers(ctx context.Context, repo *repo_model.Repository, doerID, posterID int64) ([]*user_model.User, error) { // Get the owner of the repository - this often already pre-cached and if so saves complexity for the following queries if err := repo.GetOwner(ctx); err != nil { return nil, err } cond := builder.And(builder.Neq{"`user`.id": posterID}) if repo.IsPrivate || repo.Owner.Visibility == api.VisibleTypePrivate { // This a private repository: // Anyone who can read the repository is a requestable reviewer cond = cond.And(builder.In("`user`.id", builder.Select("user_id").From("access").Where( builder.Eq{"repo_id": repo.ID}. And(builder.Gte{"mode": perm.AccessModeRead}), ), )) if repo.Owner.Type == user_model.UserTypeIndividual && repo.Owner.ID != posterID { // as private *user* repos don't generate an entry in the `access` table, // the owner of a private repo needs to be explicitly added. cond = cond.Or(builder.Eq{"`user`.id": repo.Owner.ID}) } } else { // This is a "public" repository: // Any user that has read access, is a watcher or organization member can be requested to review cond = cond.And(builder.And(builder.In("`user`.id", builder.Select("user_id").From("access"). Where(builder.Eq{"repo_id": repo.ID}. And(builder.Gte{"mode": perm.AccessModeRead})), ).Or(builder.In("`user`.id", builder.Select("user_id").From("watch"). Where(builder.Eq{"repo_id": repo.ID}. And(builder.In("mode", repo_model.WatchModeNormal, repo_model.WatchModeAuto))), ).Or(builder.In("`user`.id", builder.Select("uid").From("org_user"). Where(builder.Eq{"org_id": repo.OwnerID}), ))))) } users := make([]*user_model.User, 0, 8) return users, db.GetEngine(ctx).Where(cond).OrderBy("name").Find(&users) } // GetReviewers get all users can be requested to review: // * for private repositories this returns all users that have read access or higher to the repository. // * for public repositories this returns all users that have read access or higher to the repository, // all repo watchers and all organization members. // TODO: may be we should have a busy choice for users to block review request to them. func GetReviewers(repo *repo_model.Repository, doerID, posterID int64) ([]*user_model.User, error) { return getReviewers(db.DefaultContext, repo, doerID, posterID) } // GetReviewerTeams get all teams can be requested to review func GetReviewerTeams(repo *repo_model.Repository) ([]*organization.Team, error) { if err := repo.GetOwner(db.DefaultContext); err != nil { return nil, err } if !repo.Owner.IsOrganization() { return nil, nil } teams, err := organization.GetTeamsWithAccessToRepo(db.DefaultContext, repo.OwnerID, repo.ID, perm.AccessModeRead) if err != nil { return nil, err } return teams, err } // UpdateRepoSize updates the repository size, calculating it using util.GetDirectorySize func UpdateRepoSize(ctx context.Context, repo *repo_model.Repository) error { size, err := util.GetDirectorySize(repo.RepoPath()) if err != nil { return fmt.Errorf("updateSize: %v", err) } lfsSize, err := db.GetEngine(ctx).Where("repository_id = ?", repo.ID).SumInt(new(LFSMetaObject), "size") if err != nil { return fmt.Errorf("updateSize: GetLFSMetaObjects: %v", err) } repo.Size = size + lfsSize _, err = db.GetEngine(ctx).ID(repo.ID).Cols("size").NoAutoTime().Update(repo) return err } // CanUserForkRepo returns true if specified user can fork repository. func CanUserForkRepo(user *user_model.User, repo *repo_model.Repository) (bool, error) { if user == nil { return false, nil } if repo.OwnerID != user.ID && !repo_model.HasForkedRepo(user.ID, repo.ID) { return true, nil } ownedOrgs, err := organization.GetOrgsCanCreateRepoByUserID(user.ID) if err != nil { return false, err } for _, org := range ownedOrgs { if repo.OwnerID != org.ID && !repo_model.HasForkedRepo(org.ID, repo.ID) { return true, nil } } return false, nil } // FindUserOrgForks returns the forked repositories for one user from a repository func FindUserOrgForks(ctx context.Context, repoID, userID int64) ([]*repo_model.Repository, error) { cond := builder.And( builder.Eq{"fork_id": repoID}, builder.In("owner_id", builder.Select("org_id"). From("org_user"). Where(builder.Eq{"uid": userID}), ), ) var repos []*repo_model.Repository return repos, db.GetEngine(ctx).Table("repository").Where(cond).Find(&repos) } // GetForksByUserAndOrgs return forked repos of the user and owned orgs func GetForksByUserAndOrgs(ctx context.Context, user *user_model.User, repo *repo_model.Repository) ([]*repo_model.Repository, error) { var repoList []*repo_model.Repository if user == nil { return repoList, nil } forkedRepo, err := repo_model.GetUserFork(ctx, repo.ID, user.ID) if err != nil { return repoList, err } if forkedRepo != nil { repoList = append(repoList, forkedRepo) } orgForks, err := FindUserOrgForks(ctx, repo.ID, user.ID) if err != nil { return nil, err } repoList = append(repoList, orgForks...) return repoList, nil } // CanUserDelete returns true if user could delete the repository func CanUserDelete(repo *repo_model.Repository, user *user_model.User) (bool, error) { if user.IsAdmin || user.ID == repo.OwnerID { return true, nil } if err := repo.GetOwner(db.DefaultContext); err != nil { return false, err } if repo.Owner.IsOrganization() { isOwner, err := organization.OrgFromUser(repo.Owner).IsOwnedBy(user.ID) if err != nil { return false, err } else if isOwner { return true, nil } } return false, nil } // CreateRepoOptions contains the create repository options type CreateRepoOptions struct { Name string
-
@@ -441,126 +198,6 @@ func CreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_return nil } // CheckDaemonExportOK creates/removes git-daemon-export-ok for git-daemon... func CheckDaemonExportOK(ctx context.Context, repo *repo_model.Repository) error { if err := repo.GetOwner(ctx); err != nil { return err } // Create/Remove git-daemon-export-ok for git-daemon... daemonExportFile := path.Join(repo.RepoPath(), `git-daemon-export-ok`) isExist, err := util.IsExist(daemonExportFile) if err != nil { log.Error("Unable to check if %s exists. Error: %v", daemonExportFile, err) return err } isPublic := !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePublic if !isPublic && isExist { if err = util.Remove(daemonExportFile); err != nil { log.Error("Failed to remove %s: %v", daemonExportFile, err) } } else if isPublic && !isExist { if f, err := os.Create(daemonExportFile); err != nil { log.Error("Failed to create %s: %v", daemonExportFile, err) } else { f.Close() } } return nil } // IncrementRepoForkNum increment repository fork number func IncrementRepoForkNum(ctx context.Context, repoID int64) error { _, err := db.GetEngine(ctx).Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", repoID) return err } // DecrementRepoForkNum decrement repository fork number func DecrementRepoForkNum(ctx context.Context, repoID int64) error { _, err := db.GetEngine(ctx).Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repoID) return err } // UpdateRepositoryCtx updates a repository with db context func UpdateRepositoryCtx(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) { repo.LowerName = strings.ToLower(repo.Name) if utf8.RuneCountInString(repo.Description) > 255 { repo.Description = string([]rune(repo.Description)[:255]) } if utf8.RuneCountInString(repo.Website) > 255 { repo.Website = string([]rune(repo.Website)[:255]) } e := db.GetEngine(ctx) if _, err = e.ID(repo.ID).AllCols().Update(repo); err != nil { return fmt.Errorf("update: %v", err) } if err = UpdateRepoSize(ctx, repo); err != nil { log.Error("Failed to update size for repository: %v", err) } if visibilityChanged { if err = repo.GetOwner(ctx); err != nil { return fmt.Errorf("getOwner: %v", err) } if repo.Owner.IsOrganization() { // Organization repository need to recalculate access table when visibility is changed. if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil { return fmt.Errorf("recalculateTeamAccesses: %v", err) } } // If repo has become private, we need to set its actions to private. if repo.IsPrivate { _, err = e.Where("repo_id = ?", repo.ID).Cols("is_private").Update(&Action{ IsPrivate: true, }) if err != nil { return err } } // Create/Remove git-daemon-export-ok for git-daemon... if err := CheckDaemonExportOK(ctx, repo); err != nil { return err } forkRepos, err := repo_model.GetRepositoriesByForkID(ctx, repo.ID) if err != nil { return fmt.Errorf("GetRepositoriesByForkID: %v", err) } for i := range forkRepos { forkRepos[i].IsPrivate = repo.IsPrivate || repo.Owner.Visibility == api.VisibleTypePrivate if err = UpdateRepositoryCtx(ctx, forkRepos[i], true); err != nil { return fmt.Errorf("updateRepository[%d]: %v", forkRepos[i].ID, err) } } } return nil } // UpdateRepository updates a repository func UpdateRepository(repo *repo_model.Repository, visibilityChanged bool) (err error) { ctx, committer, err := db.TxContext() if err != nil { return err } defer committer.Close() if err = UpdateRepositoryCtx(ctx, repo, visibilityChanged); err != nil { return fmt.Errorf("updateRepository: %v", 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 {
-
@@ -1052,14 +689,14 @@ func CheckRepoStats(ctx context.Context) error {continue } rawResult, err := db.GetEngine(db.DefaultContext).Query("SELECT COUNT(*) FROM `repository` WHERE fork_id=?", repo.ID) rawResult, err := e.Query("SELECT COUNT(*) FROM `repository` WHERE fork_id=?", repo.ID) if err != nil { log.Error("Select count of forks[%d]: %v", repo.ID, err) continue } repo.NumForks = int(parseCountResult(rawResult)) if err = UpdateRepository(repo, false); err != nil { if _, err = e.ID(repo.ID).Cols("num_forks").Update(repo); err != nil { log.Error("UpdateRepository[%d]: %v", id, err) continue }
-
@@ -1130,30 +767,6 @@ func DoctorUserStarNum() (err error) {return } // LinkedRepository returns the linked repo if any func LinkedRepository(a *repo_model.Attachment) (*repo_model.Repository, unit.Type, error) { if a.IssueID != 0 { iss, err := GetIssueByID(a.IssueID) if err != nil { return nil, unit.TypeIssues, err } repo, err := repo_model.GetRepositoryByID(iss.RepoID) unitType := unit.TypeIssues if iss.IsPull { unitType = unit.TypePullRequests } return repo, unitType, err } else if a.ReleaseID != 0 { rel, err := GetReleaseByID(db.DefaultContext, a.ReleaseID) if err != nil { return nil, unit.TypeReleases, err } repo, err := repo_model.GetRepositoryByID(rel.RepoID) return repo, unit.TypeReleases, err } return nil, -1, nil } // DeleteDeployKey delete deploy keys func DeleteDeployKey(ctx context.Context, doer *user_model.User, id int64) error { key, err := asymkey_model.GetDeployKeyByID(ctx, id)
-
@@ -1164,8 +777,6 @@ func DeleteDeployKey(ctx context.Context, doer *user_model.User, id int64) errorreturn fmt.Errorf("GetDeployKeyByID: %v", err) } sess := db.GetEngine(ctx) // Check if user has access to delete this key. if !doer.IsAdmin { repo, err := repo_model.GetRepositoryByIDCtx(ctx, key.RepoID)
-
@@ -1184,14 +795,14 @@ func DeleteDeployKey(ctx context.Context, doer *user_model.User, id int64) error} } if _, err = sess.ID(key.ID).Delete(new(asymkey_model.DeployKey)); err != nil { if _, err := db.DeleteByBean(ctx, &asymkey_model.DeployKey{ ID: key.ID, }); err != nil { return fmt.Errorf("delete deploy key [%d]: %v", key.ID, err) } // Check if this is the last reference to same key content. has, err := sess. Where("key_id = ?", key.KeyID). Get(new(asymkey_model.DeployKey)) has, err := asymkey_model.IsDeployKeyExistByKeyID(ctx, key.KeyID) if err != nil { return err } else if !has {
-
-
-
@@ -2,12 +2,13 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo package repo_test import ( "testing" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert"
-
@@ -16,7 +17,7 @@ import (func TestIncreaseDownloadCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) attachment, err := GetAttachmentByUUID(db.DefaultContext, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11") attachment, err := repo_model.GetAttachmentByUUID(db.DefaultContext, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11") assert.NoError(t, err) assert.Equal(t, int64(0), attachment.DownloadCount)
-
@@ -24,7 +25,7 @@ func TestIncreaseDownloadCount(t *testing.T) {err = attachment.IncreaseDownloadCount() assert.NoError(t, err) attachment, err = GetAttachmentByUUID(db.DefaultContext, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11") attachment, err = repo_model.GetAttachmentByUUID(db.DefaultContext, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11") assert.NoError(t, err) assert.Equal(t, int64(1), attachment.DownloadCount) }
-
@@ -33,11 +34,11 @@ func TestGetByCommentOrIssueID(t *testing.T) {assert.NoError(t, unittest.PrepareTestDatabase()) // count of attachments from issue ID attachments, err := GetAttachmentsByIssueID(db.DefaultContext, 1) attachments, err := repo_model.GetAttachmentsByIssueID(db.DefaultContext, 1) assert.NoError(t, err) assert.Len(t, attachments, 1) attachments, err = GetAttachmentsByCommentID(db.DefaultContext, 1) attachments, err = repo_model.GetAttachmentsByCommentID(db.DefaultContext, 1) assert.NoError(t, err) assert.Len(t, attachments, 2) }
-
@@ -45,33 +46,33 @@ func TestGetByCommentOrIssueID(t *testing.T) {func TestDeleteAttachments(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) count, err := DeleteAttachmentsByIssue(4, false) count, err := repo_model.DeleteAttachmentsByIssue(4, false) assert.NoError(t, err) assert.Equal(t, 2, count) count, err = DeleteAttachmentsByComment(2, false) count, err = repo_model.DeleteAttachmentsByComment(2, false) assert.NoError(t, err) assert.Equal(t, 2, count) err = DeleteAttachment(&Attachment{ID: 8}, false) err = repo_model.DeleteAttachment(&repo_model.Attachment{ID: 8}, false) assert.NoError(t, err) attachment, err := GetAttachmentByUUID(db.DefaultContext, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18") attachment, err := repo_model.GetAttachmentByUUID(db.DefaultContext, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18") assert.Error(t, err) assert.True(t, IsErrAttachmentNotExist(err)) assert.True(t, repo_model.IsErrAttachmentNotExist(err)) assert.Nil(t, attachment) } func TestGetAttachmentByID(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) attach, err := GetAttachmentByID(db.DefaultContext, 1) attach, err := repo_model.GetAttachmentByID(db.DefaultContext, 1) assert.NoError(t, err) assert.Equal(t, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", attach.UUID) } func TestAttachment_DownloadURL(t *testing.T) { attach := &Attachment{ attach := &repo_model.Attachment{ UUID: "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", ID: 1, }
-
@@ -81,20 +82,20 @@ func TestAttachment_DownloadURL(t *testing.T) {func TestUpdateAttachment(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) attach, err := GetAttachmentByID(db.DefaultContext, 1) attach, err := repo_model.GetAttachmentByID(db.DefaultContext, 1) assert.NoError(t, err) assert.Equal(t, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", attach.UUID) attach.Name = "new_name" assert.NoError(t, UpdateAttachment(db.DefaultContext, attach)) assert.NoError(t, repo_model.UpdateAttachment(db.DefaultContext, attach)) unittest.AssertExistsAndLoadBean(t, &Attachment{Name: "new_name"}) unittest.AssertExistsAndLoadBean(t, &repo_model.Attachment{Name: "new_name"}) } func TestGetAttachmentsByUUIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) attachList, err := GetAttachmentsByUUIDs(db.DefaultContext, []string{"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17", "not-existing-uuid"}) attachList, err := repo_model.GetAttachmentsByUUIDs(db.DefaultContext, []string{"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a17", "not-existing-uuid"}) assert.NoError(t, err) assert.Len(t, attachList, 2) assert.Equal(t, "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", attachList[0].UUID)
-
-
-
@@ -2,12 +2,13 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo package repo_test import ( "testing" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert"
-
@@ -16,10 +17,10 @@ import (func TestRepository_GetCollaborators(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(repoID int64) { repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository) collaborators, err := GetCollaborators(db.DefaultContext, repo.ID, db.ListOptions{}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}).(*repo_model.Repository) collaborators, err := repo_model.GetCollaborators(db.DefaultContext, repo.ID, db.ListOptions{}) assert.NoError(t, err) expectedLen, err := db.GetEngine(db.DefaultContext).Count(&Collaboration{RepoID: repoID}) expectedLen, err := db.GetEngine(db.DefaultContext).Count(&repo_model.Collaboration{RepoID: repoID}) assert.NoError(t, err) assert.Len(t, collaborators, int(expectedLen)) for _, collaborator := range collaborators {
-
@@ -37,8 +38,8 @@ func TestRepository_IsCollaborator(t *testing.T) {assert.NoError(t, unittest.PrepareTestDatabase()) test := func(repoID, userID int64, expected bool) { repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository) actual, err := IsCollaborator(db.DefaultContext, repo.ID, userID) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}).(*repo_model.Repository) actual, err := repo_model.IsCollaborator(db.DefaultContext, repo.ID, userID) assert.NoError(t, err) assert.Equal(t, expected, actual) }
-
-
-
@@ -8,6 +8,8 @@ import ("context" "code.gitea.io/gitea/models/db" user_model "code.gitea.io/gitea/models/user" "xorm.io/builder" ) // GetRepositoriesByForkID returns all repositories with given fork ID.
-
@@ -63,3 +65,51 @@ func GetForks(repo *Repository, listOptions db.ListOptions) ([]*Repository, erroforks := make([]*Repository, 0, listOptions.PageSize) return forks, sess.Find(&forks, &Repository{ForkID: repo.ID}) } // IncrementRepoForkNum increment repository fork number func IncrementRepoForkNum(ctx context.Context, repoID int64) error { _, err := db.GetEngine(ctx).Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", repoID) return err } // DecrementRepoForkNum decrement repository fork number func DecrementRepoForkNum(ctx context.Context, repoID int64) error { _, err := db.GetEngine(ctx).Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repoID) return err } // FindUserOrgForks returns the forked repositories for one user from a repository func FindUserOrgForks(ctx context.Context, repoID, userID int64) ([]*Repository, error) { cond := builder.And( builder.Eq{"fork_id": repoID}, builder.In("owner_id", builder.Select("org_id"). From("org_user"). Where(builder.Eq{"uid": userID}), ), ) var repos []*Repository return repos, db.GetEngine(ctx).Table("repository").Where(cond).Find(&repos) } // GetForksByUserAndOrgs return forked repos of the user and owned orgs func GetForksByUserAndOrgs(ctx context.Context, user *user_model.User, repo *Repository) ([]*Repository, error) { var repoList []*Repository if user == nil { return repoList, nil } forkedRepo, err := GetUserFork(ctx, repo.ID, user.ID) if err != nil { return repoList, err } if forkedRepo != nil { repoList = append(repoList, forkedRepo) } orgForks, err := FindUserOrgForks(ctx, repo.ID, user.ID) if err != nil { return nil, err } repoList = append(repoList, orgForks...) return repoList, nil }
-
-
-
@@ -2,12 +2,13 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo package repo_test import ( "testing" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert"
-
@@ -17,17 +18,17 @@ func TestGetUserFork(t *testing.T) {assert.NoError(t, unittest.PrepareTestDatabase()) // User13 has repo 11 forked from repo10 repo, err := GetRepositoryByID(10) repo, err := repo_model.GetRepositoryByID(10) assert.NoError(t, err) assert.NotNil(t, repo) repo, err = GetUserFork(db.DefaultContext, repo.ID, 13) repo, err = repo_model.GetUserFork(db.DefaultContext, repo.ID, 13) assert.NoError(t, err) assert.NotNil(t, repo) repo, err = GetRepositoryByID(9) repo, err = repo_model.GetRepositoryByID(9) assert.NoError(t, err) assert.NotNil(t, repo) repo, err = GetUserFork(db.DefaultContext, repo.ID, 13) repo, err = repo_model.GetUserFork(db.DefaultContext, repo.ID, 13) assert.NoError(t, err) assert.Nil(t, repo) }
-
-
-
@@ -2,31 +2,22 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo package repo_test import ( "path/filepath" "testing" _ "code.gitea.io/gitea/models" // register table model _ "code.gitea.io/gitea/models/perm/access" // register table model _ "code.gitea.io/gitea/models/repo" // register table model _ "code.gitea.io/gitea/models/user" // register table model "code.gitea.io/gitea/models/unittest" ) func TestMain(m *testing.M) { unittest.MainTest(m, &unittest.TestOptions{ GiteaRootPath: filepath.Join("..", ".."), FixtureFiles: []string{ "attachment.yml", "repo_archiver.yml", "repository.yml", "repo_unit.yml", "repo_indexer_status.yml", "repo_redirect.yml", "watch.yml", "star.yml", "topic.yml", "repo_topic.yml", "user.yml", "collaboration.yml", }, }) }
-
-
-
@@ -123,8 +123,8 @@ func MirrorsIterate(limit int, f func(idx int, bean interface{}) error) error {} // InsertMirror inserts a mirror to database func InsertMirror(mirror *Mirror) error { _, err := db.GetEngine(db.DefaultContext).Insert(mirror) func InsertMirror(ctx context.Context, mirror *Mirror) error { _, err := db.GetEngine(ctx).Insert(mirror) return err }
-
@@ -168,3 +168,12 @@ func (repos MirrorRepositoryList) loadAttributes(ctx context.Context) error {func (repos MirrorRepositoryList) LoadAttributes() error { return repos.loadAttributes(db.DefaultContext) } // GetUserMirrorRepositories returns a list of mirror repositories of given user. func GetUserMirrorRepositories(userID int64) ([]*Repository, error) { repos := make([]*Repository, 0, 10) return repos, db.GetEngine(db.DefaultContext). Where("owner_id = ?", userID). And("is_mirror = ?", true). Find(&repos) }
-
-
-
@@ -2,12 +2,13 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo package repo_test import ( "testing" "time" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/timeutil"
-
@@ -19,20 +20,20 @@ func TestPushMirrorsIterate(t *testing.T) {now := timeutil.TimeStampNow() InsertPushMirror(&PushMirror{ repo_model.InsertPushMirror(&repo_model.PushMirror{ RemoteName: "test-1", LastUpdateUnix: now, Interval: 1, }) long, _ := time.ParseDuration("24h") InsertPushMirror(&PushMirror{ repo_model.InsertPushMirror(&repo_model.PushMirror{ RemoteName: "test-2", LastUpdateUnix: now, Interval: long, }) InsertPushMirror(&PushMirror{ repo_model.InsertPushMirror(&repo_model.PushMirror{ RemoteName: "test-3", LastUpdateUnix: now, Interval: 0,
-
@@ -40,8 +41,8 @@ func TestPushMirrorsIterate(t *testing.T) {time.Sleep(1 * time.Millisecond) PushMirrorsIterate(1, func(idx int, bean interface{}) error { m, ok := bean.(*PushMirror) repo_model.PushMirrorsIterate(1, func(idx int, bean interface{}) error { m, ok := bean.(*repo_model.PushMirror) assert.True(t, ok) assert.Equal(t, "test-1", m.RemoteName) assert.Equal(t, m.RemoteName, m.GetRemoteName())
-
-
-
@@ -2,12 +2,13 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo package repo_test import ( "testing" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert"
-
@@ -16,27 +17,27 @@ import (func TestLookupRedirect(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repoID, err := LookupRedirect(2, "oldrepo1") repoID, err := repo_model.LookupRedirect(2, "oldrepo1") assert.NoError(t, err) assert.EqualValues(t, 1, repoID) _, err = LookupRedirect(unittest.NonexistentID, "doesnotexist") assert.True(t, IsErrRedirectNotExist(err)) _, err = repo_model.LookupRedirect(unittest.NonexistentID, "doesnotexist") assert.True(t, repo_model.IsErrRedirectNotExist(err)) } func TestNewRedirect(t *testing.T) { // redirect to a completely new name assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) assert.NoError(t, NewRedirect(db.DefaultContext, repo.OwnerID, repo.ID, repo.Name, "newreponame")) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) assert.NoError(t, repo_model.NewRedirect(db.DefaultContext, repo.OwnerID, repo.ID, repo.Name, "newreponame")) unittest.AssertExistsAndLoadBean(t, &Redirect{ unittest.AssertExistsAndLoadBean(t, &repo_model.Redirect{ OwnerID: repo.OwnerID, LowerName: repo.LowerName, RedirectRepoID: repo.ID, }) unittest.AssertExistsAndLoadBean(t, &Redirect{ unittest.AssertExistsAndLoadBean(t, &repo_model.Redirect{ OwnerID: repo.OwnerID, LowerName: "oldrepo1", RedirectRepoID: repo.ID,
-
@@ -47,15 +48,15 @@ func TestNewRedirect2(t *testing.T) {// redirect to previously used name assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) assert.NoError(t, NewRedirect(db.DefaultContext, repo.OwnerID, repo.ID, repo.Name, "oldrepo1")) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) assert.NoError(t, repo_model.NewRedirect(db.DefaultContext, repo.OwnerID, repo.ID, repo.Name, "oldrepo1")) unittest.AssertExistsAndLoadBean(t, &Redirect{ unittest.AssertExistsAndLoadBean(t, &repo_model.Redirect{ OwnerID: repo.OwnerID, LowerName: repo.LowerName, RedirectRepoID: repo.ID, }) unittest.AssertNotExistsBean(t, &Redirect{ unittest.AssertNotExistsBean(t, &repo_model.Redirect{ OwnerID: repo.OwnerID, LowerName: "oldrepo1", RedirectRepoID: repo.ID,
-
@@ -66,10 +67,10 @@ func TestNewRedirect3(t *testing.T) {// redirect for a previously-unredirected repo assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 2}).(*Repository) assert.NoError(t, NewRedirect(db.DefaultContext, repo.OwnerID, repo.ID, repo.Name, "newreponame")) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository) assert.NoError(t, repo_model.NewRedirect(db.DefaultContext, repo.OwnerID, repo.ID, repo.Name, "newreponame")) unittest.AssertExistsAndLoadBean(t, &Redirect{ unittest.AssertExistsAndLoadBean(t, &repo_model.Redirect{ OwnerID: repo.OwnerID, LowerName: repo.LowerName, RedirectRepoID: repo.ID,
-
-
-
@@ -5,18 +5,21 @@package repo import ( "context" "fmt" "strings" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/setting" ) "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" // GetUserMirrorRepositories returns a list of mirror repositories of given user. func GetUserMirrorRepositories(userID int64) ([]*Repository, error) { repos := make([]*Repository, 0, 10) return repos, db.GetEngine(db.DefaultContext). Where("owner_id = ?", userID). And("is_mirror = ?", true). Find(&repos) } "xorm.io/builder" ) // IterateRepository iterate repositories func IterateRepository(f func(repo *Repository) error) error {
-
@@ -45,3 +48,643 @@ func IterateRepository(f func(repo *Repository) error) error {func FindReposMapByIDs(repoIDs []int64, res map[int64]*Repository) error { return db.GetEngine(db.DefaultContext).In("id", repoIDs).Find(&res) } // RepositoryListDefaultPageSize is the default number of repositories // to load in memory when running administrative tasks on all (or almost // all) of them. // The number should be low enough to avoid filling up all RAM with // repository data... const RepositoryListDefaultPageSize = 64 // RepositoryList contains a list of repositories type RepositoryList []*Repository func (repos RepositoryList) Len() int { return len(repos) } func (repos RepositoryList) Less(i, j int) bool { return repos[i].FullName() < repos[j].FullName() } func (repos RepositoryList) Swap(i, j int) { repos[i], repos[j] = repos[j], repos[i] } // ValuesRepository converts a repository map to a list // FIXME: Remove in favor of maps.values when MIN_GO_VERSION >= 1.18 func ValuesRepository(m map[int64]*Repository) []*Repository { values := make([]*Repository, 0, len(m)) for _, v := range m { values = append(values, v) } return values } // RepositoryListOfMap make list from values of map func RepositoryListOfMap(repoMap map[int64]*Repository) RepositoryList { return RepositoryList(ValuesRepository(repoMap)) } func (repos RepositoryList) loadAttributes(ctx context.Context) error { if len(repos) == 0 { return nil } set := make(map[int64]struct{}) repoIDs := make([]int64, len(repos)) for i := range repos { set[repos[i].OwnerID] = struct{}{} repoIDs[i] = repos[i].ID } // Load owners. users := make(map[int64]*user_model.User, len(set)) if err := db.GetEngine(ctx). Where("id > 0"). In("id", container.KeysInt64(set)). Find(&users); err != nil { return fmt.Errorf("find users: %v", err) } for i := range repos { repos[i].Owner = users[repos[i].OwnerID] } // Load primary language. stats := make(LanguageStatList, 0, len(repos)) if err := db.GetEngine(ctx). Where("`is_primary` = ? AND `language` != ?", true, "other"). In("`repo_id`", repoIDs). Find(&stats); err != nil { return fmt.Errorf("find primary languages: %v", err) } stats.LoadAttributes() for i := range repos { for _, st := range stats { if st.RepoID == repos[i].ID { repos[i].PrimaryLanguage = st break } } } return nil } // LoadAttributes loads the attributes for the given RepositoryList func (repos RepositoryList) LoadAttributes() error { return repos.loadAttributes(db.DefaultContext) } // SearchRepoOptions holds the search options type SearchRepoOptions struct { db.ListOptions Actor *user_model.User Keyword string OwnerID int64 PriorityOwnerID int64 TeamID int64 OrderBy db.SearchOrderBy Private bool // Include private repositories in results StarredByID int64 WatchedByID int64 AllPublic bool // Include also all public repositories of users and public organisations AllLimited bool // Include also all public repositories of limited organisations // None -> include public and private // True -> include just private // False -> include just public IsPrivate util.OptionalBool // None -> include collaborative AND non-collaborative // True -> include just collaborative // False -> include just non-collaborative Collaborate util.OptionalBool // None -> include forks AND non-forks // True -> include just forks // False -> include just non-forks Fork util.OptionalBool // None -> include templates AND non-templates // True -> include just templates // False -> include just non-templates Template util.OptionalBool // None -> include mirrors AND non-mirrors // True -> include just mirrors // False -> include just non-mirrors Mirror util.OptionalBool // None -> include archived AND non-archived // True -> include just archived // False -> include just non-archived Archived util.OptionalBool // only search topic name TopicOnly bool // only search repositories with specified primary language Language string // include description in keyword search IncludeDescription bool // None -> include has milestones AND has no milestone // True -> include just has milestones // False -> include just has no milestone HasMilestones util.OptionalBool // LowerNames represents valid lower names to restrict to LowerNames []string } // SearchOrderBy is used to sort the result type SearchOrderBy string func (s SearchOrderBy) String() string { return string(s) } // Strings for sorting result const ( SearchOrderByAlphabetically SearchOrderBy = "name ASC" SearchOrderByAlphabeticallyReverse SearchOrderBy = "name DESC" SearchOrderByLeastUpdated SearchOrderBy = "updated_unix ASC" SearchOrderByRecentUpdated SearchOrderBy = "updated_unix DESC" SearchOrderByOldest SearchOrderBy = "created_unix ASC" SearchOrderByNewest SearchOrderBy = "created_unix DESC" SearchOrderBySize SearchOrderBy = "size ASC" SearchOrderBySizeReverse SearchOrderBy = "size DESC" SearchOrderByID SearchOrderBy = "id ASC" SearchOrderByIDReverse SearchOrderBy = "id DESC" SearchOrderByStars SearchOrderBy = "num_stars ASC" SearchOrderByStarsReverse SearchOrderBy = "num_stars DESC" SearchOrderByForks SearchOrderBy = "num_forks ASC" SearchOrderByForksReverse SearchOrderBy = "num_forks DESC" ) // UserOwnedRepoCond returns user ownered repositories func UserOwnedRepoCond(userID int64) builder.Cond { return builder.Eq{ "repository.owner_id": userID, } } // UserAssignedRepoCond return user as assignee repositories list func UserAssignedRepoCond(id string, userID int64) builder.Cond { return builder.And( builder.Eq{ "repository.is_private": false, }, builder.In(id, builder.Select("issue.repo_id").From("issue_assignees"). InnerJoin("issue", "issue.id = issue_assignees.issue_id"). Where(builder.Eq{ "issue_assignees.assignee_id": userID, }), ), ) } // UserCreateIssueRepoCond return user created issues repositories list func UserCreateIssueRepoCond(id string, userID int64, isPull bool) builder.Cond { return builder.And( builder.Eq{ "repository.is_private": false, }, builder.In(id, builder.Select("issue.repo_id").From("issue"). Where(builder.Eq{ "issue.poster_id": userID, "issue.is_pull": isPull, }), ), ) } // UserMentionedRepoCond return user metinoed repositories list func UserMentionedRepoCond(id string, userID int64) builder.Cond { return builder.And( builder.Eq{ "repository.is_private": false, }, builder.In(id, builder.Select("issue.repo_id").From("issue_user"). InnerJoin("issue", "issue.id = issue_user.issue_id"). Where(builder.Eq{ "issue_user.is_mentioned": true, "issue_user.uid": userID, }), ), ) } // UserCollaborationRepoCond returns user as collabrators repositories list func UserCollaborationRepoCond(idStr string, userID int64) builder.Cond { return builder.In(idStr, builder.Select("repo_id"). From("`access`"). Where(builder.And( builder.Eq{"`access`.user_id": userID}, builder.Gt{"`access`.mode": int(perm.AccessModeNone)}, )), ) } // userOrgTeamRepoCond selects repos that the given user has access to through team membership func userOrgTeamRepoCond(idStr string, userID int64) builder.Cond { return builder.In(idStr, userOrgTeamRepoBuilder(userID)) } // userOrgTeamRepoBuilder returns repo ids where user's teams can access. func userOrgTeamRepoBuilder(userID int64) *builder.Builder { return builder.Select("`team_repo`.repo_id"). From("team_repo"). Join("INNER", "team_user", "`team_user`.team_id = `team_repo`.team_id"). Where(builder.Eq{"`team_user`.uid": userID}) } // userOrgTeamUnitRepoBuilder returns repo ids where user's teams can access the special unit. func userOrgTeamUnitRepoBuilder(userID int64, unitType unit.Type) *builder.Builder { return userOrgTeamRepoBuilder(userID). Join("INNER", "team_unit", "`team_unit`.team_id = `team_repo`.team_id"). Where(builder.Eq{"`team_unit`.`type`": unitType}) } // UserOrgUnitRepoCond selects repos that the given user has access to through org and the special unit func UserOrgUnitRepoCond(idStr string, userID, orgID int64, unitType unit.Type) builder.Cond { return builder.In(idStr, userOrgTeamUnitRepoBuilder(userID, unitType). And(builder.Eq{"`team_unit`.org_id": orgID}), ) } // userOrgPublicRepoCond returns the condition that one user could access all public repositories in organizations func userOrgPublicRepoCond(userID int64) builder.Cond { return builder.And( builder.Eq{"`repository`.is_private": false}, builder.In("`repository`.owner_id", builder.Select("`org_user`.org_id"). From("org_user"). Where(builder.Eq{"`org_user`.uid": userID}), ), ) } // userOrgPublicRepoCondPrivate returns the condition that one user could access all public repositories in private organizations func userOrgPublicRepoCondPrivate(userID int64) builder.Cond { return builder.And( builder.Eq{"`repository`.is_private": false}, builder.In("`repository`.owner_id", builder.Select("`org_user`.org_id"). From("org_user"). Join("INNER", "`user`", "`user`.id = `org_user`.org_id"). Where(builder.Eq{ "`org_user`.uid": userID, "`user`.`type`": user_model.UserTypeOrganization, "`user`.visibility": structs.VisibleTypePrivate, }), ), ) } // UserOrgPublicUnitRepoCond returns the condition that one user could access all public repositories in the special organization func UserOrgPublicUnitRepoCond(userID, orgID int64) builder.Cond { return userOrgPublicRepoCond(userID). And(builder.Eq{"`repository`.owner_id": orgID}) } // SearchRepositoryCondition creates a query condition according search repository options func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { cond := builder.NewCond() if opts.Private { if opts.Actor != nil && !opts.Actor.IsAdmin && opts.Actor.ID != opts.OwnerID { // OK we're in the context of a User cond = cond.And(AccessibleRepositoryCondition(opts.Actor)) } } else { // Not looking at private organisations and users // We should be able to see all non-private repositories that // isn't in a private or limited organisation. cond = cond.And( builder.Eq{"is_private": false}, builder.NotIn("owner_id", builder.Select("id").From("`user`").Where( builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}), ))) } if opts.IsPrivate != util.OptionalBoolNone { cond = cond.And(builder.Eq{"is_private": opts.IsPrivate.IsTrue()}) } if opts.Template != util.OptionalBoolNone { cond = cond.And(builder.Eq{"is_template": opts.Template == util.OptionalBoolTrue}) } // Restrict to starred repositories if opts.StarredByID > 0 { cond = cond.And(builder.In("id", builder.Select("repo_id").From("star").Where(builder.Eq{"uid": opts.StarredByID}))) } // Restrict to watched repositories if opts.WatchedByID > 0 { cond = cond.And(builder.In("id", builder.Select("repo_id").From("watch").Where(builder.Eq{"user_id": opts.WatchedByID}))) } // Restrict repositories to those the OwnerID owns or contributes to as per opts.Collaborate if opts.OwnerID > 0 { accessCond := builder.NewCond() if opts.Collaborate != util.OptionalBoolTrue { accessCond = builder.Eq{"owner_id": opts.OwnerID} } if opts.Collaborate != util.OptionalBoolFalse { // A Collaboration is: collaborateCond := builder.And( // 1. Repository we don't own builder.Neq{"owner_id": opts.OwnerID}, // 2. But we can see because of: builder.Or( // A. We have access UserCollaborationRepoCond("`repository`.id", opts.OwnerID), // B. We are in a team for userOrgTeamRepoCond("`repository`.id", opts.OwnerID), // C. Public repositories in organizations that we are member of userOrgPublicRepoCondPrivate(opts.OwnerID), ), ) if !opts.Private { collaborateCond = collaborateCond.And(builder.Expr("owner_id NOT IN (SELECT org_id FROM org_user WHERE org_user.uid = ? AND org_user.is_public = ?)", opts.OwnerID, false)) } accessCond = accessCond.Or(collaborateCond) } if opts.AllPublic { accessCond = accessCond.Or(builder.Eq{"is_private": false}.And(builder.In("owner_id", builder.Select("`user`.id").From("`user`").Where(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})))) } if opts.AllLimited { accessCond = accessCond.Or(builder.Eq{"is_private": false}.And(builder.In("owner_id", builder.Select("`user`.id").From("`user`").Where(builder.Eq{"`user`.visibility": structs.VisibleTypeLimited})))) } cond = cond.And(accessCond) } if opts.TeamID > 0 { cond = cond.And(builder.In("`repository`.id", builder.Select("`team_repo`.repo_id").From("team_repo").Where(builder.Eq{"`team_repo`.team_id": opts.TeamID}))) } if opts.Keyword != "" { // separate keyword subQueryCond := builder.NewCond() for _, v := range strings.Split(opts.Keyword, ",") { if opts.TopicOnly { subQueryCond = subQueryCond.Or(builder.Eq{"topic.name": strings.ToLower(v)}) } else { subQueryCond = subQueryCond.Or(builder.Like{"topic.name", strings.ToLower(v)}) } } subQuery := builder.Select("repo_topic.repo_id").From("repo_topic"). Join("INNER", "topic", "topic.id = repo_topic.topic_id"). Where(subQueryCond). GroupBy("repo_topic.repo_id") keywordCond := builder.In("id", subQuery) if !opts.TopicOnly { likes := builder.NewCond() for _, v := range strings.Split(opts.Keyword, ",") { likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)}) // If the string looks like "org/repo", match against that pattern too if opts.TeamID == 0 && strings.Count(opts.Keyword, "/") == 1 { pieces := strings.Split(opts.Keyword, "/") ownerName := pieces[0] repoName := pieces[1] likes = likes.Or(builder.And(builder.Like{"owner_name", strings.ToLower(ownerName)}, builder.Like{"lower_name", strings.ToLower(repoName)})) } if opts.IncludeDescription { likes = likes.Or(builder.Like{"LOWER(description)", strings.ToLower(v)}) } } keywordCond = keywordCond.Or(likes) } cond = cond.And(keywordCond) } if opts.Language != "" { cond = cond.And(builder.In("id", builder. Select("repo_id"). From("language_stat"). Where(builder.Eq{"language": opts.Language}).And(builder.Eq{"is_primary": true}))) } if opts.Fork != util.OptionalBoolNone { cond = cond.And(builder.Eq{"is_fork": opts.Fork == util.OptionalBoolTrue}) } if opts.Mirror != util.OptionalBoolNone { cond = cond.And(builder.Eq{"is_mirror": opts.Mirror == util.OptionalBoolTrue}) } if opts.Actor != nil && opts.Actor.IsRestricted { cond = cond.And(AccessibleRepositoryCondition(opts.Actor)) } if opts.Archived != util.OptionalBoolNone { cond = cond.And(builder.Eq{"is_archived": opts.Archived == util.OptionalBoolTrue}) } switch opts.HasMilestones { case util.OptionalBoolTrue: cond = cond.And(builder.Gt{"num_milestones": 0}) case util.OptionalBoolFalse: cond = cond.And(builder.Eq{"num_milestones": 0}.Or(builder.IsNull{"num_milestones"})) } return cond } // SearchRepository returns repositories based on search options, // it returns results in given range and number of total results. func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) { cond := SearchRepositoryCondition(opts) return SearchRepositoryByCondition(opts, cond, true) } // SearchRepositoryByCondition search repositories by condition func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) { ctx := db.DefaultContext sess, count, err := searchRepositoryByCondition(ctx, opts, cond) if err != nil { return nil, 0, err } defaultSize := 50 if opts.PageSize > 0 { defaultSize = opts.PageSize } repos := make(RepositoryList, 0, defaultSize) if err := sess.Find(&repos); err != nil { return nil, 0, fmt.Errorf("Repo: %v", err) } if opts.PageSize <= 0 { count = int64(len(repos)) } if loadAttributes { if err := repos.loadAttributes(ctx); err != nil { return nil, 0, fmt.Errorf("LoadAttributes: %v", err) } } return repos, count, nil } func searchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, cond builder.Cond) (db.Engine, int64, error) { if opts.Page <= 0 { opts.Page = 1 } if len(opts.OrderBy) == 0 { opts.OrderBy = db.SearchOrderByAlphabetically } args := make([]interface{}, 0) if opts.PriorityOwnerID > 0 { opts.OrderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_id = ? THEN 0 ELSE owner_id END, %s", opts.OrderBy)) args = append(args, opts.PriorityOwnerID) } else if strings.Count(opts.Keyword, "/") == 1 { // With "owner/repo" search times, prioritise results which match the owner field orgName := strings.Split(opts.Keyword, "/")[0] opts.OrderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_name LIKE ? THEN 0 ELSE 1 END, %s", opts.OrderBy)) args = append(args, orgName) } sess := db.GetEngine(ctx) var count int64 if opts.PageSize > 0 { var err error count, err = sess. Where(cond). Count(new(Repository)) if err != nil { return nil, 0, fmt.Errorf("Count: %v", err) } } sess = sess.Where(cond).OrderBy(opts.OrderBy.String(), args...) if opts.PageSize > 0 { sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) } return sess, count, nil } // AccessibleRepositoryCondition takes a user a returns a condition for checking if a repository is accessible func AccessibleRepositoryCondition(user *user_model.User) builder.Cond { cond := builder.NewCond() if user == nil || !user.IsRestricted || user.ID <= 0 { orgVisibilityLimit := []structs.VisibleType{structs.VisibleTypePrivate} if user == nil || user.ID <= 0 { orgVisibilityLimit = append(orgVisibilityLimit, structs.VisibleTypeLimited) } // 1. Be able to see all non-private repositories that either: cond = cond.Or(builder.And( builder.Eq{"`repository`.is_private": false}, // 2. Aren't in an private organisation or limited organisation if we're not logged in builder.NotIn("`repository`.owner_id", builder.Select("id").From("`user`").Where( builder.And( builder.Eq{"type": user_model.UserTypeOrganization}, builder.In("visibility", orgVisibilityLimit)), )))) } if user != nil { cond = cond.Or( // 2. Be able to see all repositories that we have access to UserCollaborationRepoCond("`repository`.id", user.ID), // 3. Repositories that we directly own builder.Eq{"`repository`.owner_id": user.ID}, // 4. Be able to see all repositories that we are in a team userOrgTeamRepoCond("`repository`.id", user.ID), // 5. Be able to see all public repos in private organizations that we are an org_user of userOrgPublicRepoCond(user.ID), ) } return cond } // SearchRepositoryByName takes keyword and part of repository name to search, // it returns results in given range and number of total results. func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, error) { opts.IncludeDescription = false return SearchRepository(opts) } // SearchRepositoryIDs takes keyword and part of repository name to search, // it returns results in given range and number of total results. func SearchRepositoryIDs(opts *SearchRepoOptions) ([]int64, int64, error) { opts.IncludeDescription = false cond := SearchRepositoryCondition(opts) sess, count, err := searchRepositoryByCondition(db.DefaultContext, opts, cond) if err != nil { return nil, 0, err } defaultSize := 50 if opts.PageSize > 0 { defaultSize = opts.PageSize } ids := make([]int64, 0, defaultSize) err = sess.Select("id").Table("repository").Find(&ids) if opts.PageSize <= 0 { count = int64(len(ids)) } return ids, count, err } // AccessibleRepoIDsQuery queries accessible repository ids. Usable as a subquery wherever repo ids need to be filtered. func AccessibleRepoIDsQuery(user *user_model.User) *builder.Builder { // NB: Please note this code needs to still work if user is nil return builder.Select("id").From("repository").Where(AccessibleRepositoryCondition(user)) } // FindUserAccessibleRepoIDs find all accessible repositories' ID by user's id func FindUserAccessibleRepoIDs(user *user_model.User) ([]int64, error) { repoIDs := make([]int64, 0, 10) if err := db.GetEngine(db.DefaultContext). Table("repository"). Cols("id"). Where(AccessibleRepositoryCondition(user)). Find(&repoIDs); err != nil { return nil, fmt.Errorf("FindUserAccesibleRepoIDs: %v", err) } return repoIDs, nil } // GetUserRepositories returns a list of repositories of given user. func GetUserRepositories(opts *SearchRepoOptions) (RepositoryList, int64, error) { if len(opts.OrderBy) == 0 { opts.OrderBy = "updated_unix DESC" } cond := builder.NewCond() cond = cond.And(builder.Eq{"owner_id": opts.Actor.ID}) if !opts.Private { cond = cond.And(builder.Eq{"is_private": false}) } if opts.LowerNames != nil && len(opts.LowerNames) > 0 { cond = cond.And(builder.In("lower_name", opts.LowerNames)) } sess := db.GetEngine(db.DefaultContext) count, err := sess.Where(cond).Count(new(Repository)) if err != nil { return nil, 0, fmt.Errorf("Count: %v", err) } sess = sess.Where(cond).OrderBy(opts.OrderBy.String()) repos := make(RepositoryList, 0, opts.PageSize) return repos, count, db.SetSessionPagination(sess, opts).Find(&repos) }
-
-
-
@@ -2,13 +2,14 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package models package repo_test import ( "strings" "testing" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/util"
-
@@ -19,7 +20,7 @@ func TestSearchRepository(t *testing.T) {assert.NoError(t, unittest.PrepareTestDatabase()) // test search public repository on explore page repos, count, err := SearchRepositoryByName(&SearchRepoOptions{ repos, count, err := repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10,
-
@@ -34,7 +35,7 @@ func TestSearchRepository(t *testing.T) {} assert.Equal(t, int64(1), count) repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10,
-
@@ -48,7 +49,7 @@ func TestSearchRepository(t *testing.T) {assert.Len(t, repos, 2) // test search private repository on explore page repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10,
-
@@ -64,7 +65,7 @@ func TestSearchRepository(t *testing.T) {} assert.Equal(t, int64(1), count) repos, count, err = SearchRepositoryByName(&SearchRepoOptions{ repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10,
-
@@ -79,14 +80,14 @@ func TestSearchRepository(t *testing.T) {assert.Len(t, repos, 3) // Test non existing owner repos, count, err = SearchRepositoryByName(&SearchRepoOptions{OwnerID: unittest.NonexistentID}) repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID}) assert.NoError(t, err) assert.Empty(t, repos) assert.Equal(t, int64(0), count) // Test search within description repos, count, err = SearchRepository(&SearchRepoOptions{ repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10,
-
@@ -103,7 +104,7 @@ func TestSearchRepository(t *testing.T) {assert.Equal(t, int64(1), count) // Test NOT search within description repos, count, err = SearchRepository(&SearchRepoOptions{ repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: 1, PageSize: 10,
-
@@ -119,164 +120,164 @@ func TestSearchRepository(t *testing.T) {testCases := []struct { name string opts *SearchRepoOptions opts *repo_model.SearchRepoOptions count int }{ { name: "PublicRepositoriesByName", opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, Collaborate: util.OptionalBoolFalse}, count: 7, }, { name: "PublicAndPrivateRepositoriesByName", opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, Collaborate: util.OptionalBoolFalse}, count: 14, }, { name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFirstPage", opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, count: 14, }, { name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitSecondPage", opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 2, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 2, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, count: 14, }, { name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitThirdPage", opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, count: 14, }, { name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFourthPage", opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: util.OptionalBoolFalse}, count: 14, }, { name: "PublicRepositoriesOfUser", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Collaborate: util.OptionalBoolFalse}, count: 2, }, { name: "PublicRepositoriesOfUser2", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Collaborate: util.OptionalBoolFalse}, count: 0, }, { name: "PublicRepositoriesOfUser3", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Collaborate: util.OptionalBoolFalse}, count: 2, }, { name: "PublicAndPrivateRepositoriesOfUser", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, Collaborate: util.OptionalBoolFalse}, count: 4, }, { name: "PublicAndPrivateRepositoriesOfUser2", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, Collaborate: util.OptionalBoolFalse}, count: 0, }, { name: "PublicAndPrivateRepositoriesOfUser3", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true, Collaborate: util.OptionalBoolFalse}, count: 4, }, { name: "PublicRepositoriesOfUserIncludingCollaborative", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15}, count: 5, }, { name: "PublicRepositoriesOfUser2IncludingCollaborative", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18}, count: 1, }, { name: "PublicRepositoriesOfUser3IncludingCollaborative", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20}, count: 3, }, { name: "PublicAndPrivateRepositoriesOfUserIncludingCollaborative", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true}, count: 9, }, { name: "PublicAndPrivateRepositoriesOfUser2IncludingCollaborative", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true}, count: 4, }, { name: "PublicAndPrivateRepositoriesOfUser3IncludingCollaborative", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true}, count: 7, }, { name: "PublicRepositoriesOfOrganization", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Collaborate: util.OptionalBoolFalse}, count: 1, }, { name: "PublicAndPrivateRepositoriesOfOrganization", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Private: true, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Private: true, Collaborate: util.OptionalBoolFalse}, count: 2, }, { name: "AllPublic/PublicRepositoriesByName", opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, AllPublic: true, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, AllPublic: true, Collaborate: util.OptionalBoolFalse}, count: 7, }, { name: "AllPublic/PublicAndPrivateRepositoriesByName", opts: &SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, AllPublic: true, Collaborate: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, AllPublic: true, Collaborate: util.OptionalBoolFalse}, count: 14, }, { name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse}, count: 28, }, { name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse}, count: 33, }, { name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName", opts: &SearchRepoOptions{Keyword: "test", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true}, opts: &repo_model.SearchRepoOptions{Keyword: "test", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true}, count: 15, }, { name: "AllPublic/PublicAndPrivateRepositoriesOfUser2IncludingCollaborativeByName", opts: &SearchRepoOptions{Keyword: "test", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, AllPublic: true}, opts: &repo_model.SearchRepoOptions{Keyword: "test", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, AllPublic: true}, count: 13, }, { name: "AllPublic/PublicRepositoriesOfOrganization", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse, Template: util.OptionalBoolFalse}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse, Template: util.OptionalBoolFalse}, count: 28, }, { name: "AllTemplates", opts: &SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Template: util.OptionalBoolTrue}, opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Template: util.OptionalBoolTrue}, count: 2, }, { name: "OwnerSlashRepoSearch", opts: &SearchRepoOptions{Keyword: "user/repo2", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, OwnerID: 0}, opts: &repo_model.SearchRepoOptions{Keyword: "user/repo2", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, OwnerID: 0}, count: 3, }, { name: "OwnerSlashSearch", opts: &SearchRepoOptions{Keyword: "user20/", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, OwnerID: 0}, opts: &repo_model.SearchRepoOptions{Keyword: "user20/", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, OwnerID: 0}, count: 4, }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { repos, count, err := SearchRepositoryByName(testCase.opts) repos, count, err := repo_model.SearchRepositoryByName(testCase.opts) assert.NoError(t, err) assert.Equal(t, int64(testCase.count), count)
-
@@ -354,29 +355,29 @@ func TestSearchRepositoryByTopicName(t *testing.T) {testCases := []struct { name string opts *SearchRepoOptions opts *repo_model.SearchRepoOptions count int }{ { name: "AllPublic/SearchPublicRepositoriesFromTopicAndName", opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql"}, opts: &repo_model.SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql"}, count: 2, }, { name: "AllPublic/OnlySearchPublicRepositoriesFromTopic", opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql", TopicOnly: true}, opts: &repo_model.SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql", TopicOnly: true}, count: 1, }, { name: "AllPublic/OnlySearchMultipleKeywordPublicRepositoriesFromTopic", opts: &SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql,golang", TopicOnly: true}, opts: &repo_model.SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql,golang", TopicOnly: true}, count: 2, }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { _, count, err := SearchRepositoryByName(testCase.opts) _, count, err := repo_model.SearchRepositoryByName(testCase.opts) assert.NoError(t, err) assert.Equal(t, int64(testCase.count), count) })
-
-
-
@@ -2,12 +2,13 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo package repo_test import ( "testing" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/util"
-
@@ -15,18 +16,18 @@ import () var ( countRepospts = CountRepositoryOptions{OwnerID: 10} countReposptsPublic = CountRepositoryOptions{OwnerID: 10, Private: util.OptionalBoolFalse} countReposptsPrivate = CountRepositoryOptions{OwnerID: 10, Private: util.OptionalBoolTrue} countRepospts = repo_model.CountRepositoryOptions{OwnerID: 10} countReposptsPublic = repo_model.CountRepositoryOptions{OwnerID: 10, Private: util.OptionalBoolFalse} countReposptsPrivate = repo_model.CountRepositoryOptions{OwnerID: 10, Private: util.OptionalBoolTrue} ) func TestGetRepositoryCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) ctx := db.DefaultContext count, err1 := CountRepositories(ctx, countRepospts) privateCount, err2 := CountRepositories(ctx, countReposptsPrivate) publicCount, err3 := CountRepositories(ctx, countReposptsPublic) count, err1 := repo_model.CountRepositories(ctx, countRepospts) privateCount, err2 := repo_model.CountRepositories(ctx, countReposptsPrivate) publicCount, err3 := repo_model.CountRepositories(ctx, countReposptsPublic) assert.NoError(t, err1) assert.NoError(t, err2) assert.NoError(t, err3)
-
@@ -37,7 +38,7 @@ func TestGetRepositoryCount(t *testing.T) {func TestGetPublicRepositoryCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) count, err := CountRepositories(db.DefaultContext, countReposptsPublic) count, err := repo_model.CountRepositories(db.DefaultContext, countReposptsPublic) assert.NoError(t, err) assert.Equal(t, int64(1), count) }
-
@@ -45,14 +46,14 @@ func TestGetPublicRepositoryCount(t *testing.T) {func TestGetPrivateRepositoryCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) count, err := CountRepositories(db.DefaultContext, countReposptsPrivate) count, err := repo_model.CountRepositories(db.DefaultContext, countReposptsPrivate) assert.NoError(t, err) assert.Equal(t, int64(2), count) } func TestRepoAPIURL(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 10}).(*Repository) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10}).(*repo_model.Repository) assert.Equal(t, "https://try.gitea.io/api/v1/repos/user12/repo10", repo.APIURL()) }
-
-
-
@@ -2,12 +2,13 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo package repo_test import ( "testing" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert"
-
@@ -17,26 +18,26 @@ func TestStarRepo(t *testing.T) {assert.NoError(t, unittest.PrepareTestDatabase()) const userID = 2 const repoID = 1 unittest.AssertNotExistsBean(t, &Star{UID: userID, RepoID: repoID}) assert.NoError(t, StarRepo(userID, repoID, true)) unittest.AssertExistsAndLoadBean(t, &Star{UID: userID, RepoID: repoID}) assert.NoError(t, StarRepo(userID, repoID, true)) unittest.AssertExistsAndLoadBean(t, &Star{UID: userID, RepoID: repoID}) assert.NoError(t, StarRepo(userID, repoID, false)) unittest.AssertNotExistsBean(t, &Star{UID: userID, RepoID: repoID}) unittest.AssertNotExistsBean(t, &repo_model.Star{UID: userID, RepoID: repoID}) assert.NoError(t, repo_model.StarRepo(userID, repoID, true)) unittest.AssertExistsAndLoadBean(t, &repo_model.Star{UID: userID, RepoID: repoID}) assert.NoError(t, repo_model.StarRepo(userID, repoID, true)) unittest.AssertExistsAndLoadBean(t, &repo_model.Star{UID: userID, RepoID: repoID}) assert.NoError(t, repo_model.StarRepo(userID, repoID, false)) unittest.AssertNotExistsBean(t, &repo_model.Star{UID: userID, RepoID: repoID}) } func TestIsStaring(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) assert.True(t, IsStaring(db.DefaultContext, 2, 4)) assert.False(t, IsStaring(db.DefaultContext, 3, 4)) assert.True(t, repo_model.IsStaring(db.DefaultContext, 2, 4)) assert.False(t, repo_model.IsStaring(db.DefaultContext, 3, 4)) } func TestRepository_GetStargazers(t *testing.T) { // repo with stargazers assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 4}).(*Repository) gazers, err := GetStargazers(repo, db.ListOptions{Page: 0}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}).(*repo_model.Repository) gazers, err := repo_model.GetStargazers(repo, db.ListOptions{Page: 0}) assert.NoError(t, err) if assert.Len(t, gazers, 1) { assert.Equal(t, int64(2), gazers[0].ID)
-
@@ -46,8 +47,8 @@ func TestRepository_GetStargazers(t *testing.T) {func TestRepository_GetStargazers2(t *testing.T) { // repo with stargazers assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 3}).(*Repository) gazers, err := GetStargazers(repo, db.ListOptions{Page: 0}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}).(*repo_model.Repository) gazers, err := repo_model.GetStargazers(repo, db.ListOptions{Page: 0}) assert.NoError(t, err) assert.Len(t, gazers, 0) }
-
-
-
@@ -2,12 +2,13 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo package repo_test import ( "testing" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert"
-
@@ -19,47 +20,47 @@ func TestAddTopic(t *testing.T) {assert.NoError(t, unittest.PrepareTestDatabase()) topics, _, err := FindTopics(&FindTopicOptions{}) topics, _, err := repo_model.FindTopics(&repo_model.FindTopicOptions{}) assert.NoError(t, err) assert.Len(t, topics, totalNrOfTopics) topics, total, err := FindTopics(&FindTopicOptions{ topics, total, err := repo_model.FindTopics(&repo_model.FindTopicOptions{ ListOptions: db.ListOptions{Page: 1, PageSize: 2}, }) assert.NoError(t, err) assert.Len(t, topics, 2) assert.EqualValues(t, 6, total) topics, _, err = FindTopics(&FindTopicOptions{ topics, _, err = repo_model.FindTopics(&repo_model.FindTopicOptions{ RepoID: 1, }) assert.NoError(t, err) assert.Len(t, topics, repo1NrOfTopics) assert.NoError(t, SaveTopics(2, "golang")) assert.NoError(t, repo_model.SaveTopics(2, "golang")) repo2NrOfTopics := 1 topics, _, err = FindTopics(&FindTopicOptions{}) topics, _, err = repo_model.FindTopics(&repo_model.FindTopicOptions{}) assert.NoError(t, err) assert.Len(t, topics, totalNrOfTopics) topics, _, err = FindTopics(&FindTopicOptions{ topics, _, err = repo_model.FindTopics(&repo_model.FindTopicOptions{ RepoID: 2, }) assert.NoError(t, err) assert.Len(t, topics, repo2NrOfTopics) assert.NoError(t, SaveTopics(2, "golang", "gitea")) assert.NoError(t, repo_model.SaveTopics(2, "golang", "gitea")) repo2NrOfTopics = 2 totalNrOfTopics++ topic, err := GetTopicByName("gitea") topic, err := repo_model.GetTopicByName("gitea") assert.NoError(t, err) assert.EqualValues(t, 1, topic.RepoCount) topics, _, err = FindTopics(&FindTopicOptions{}) topics, _, err = repo_model.FindTopics(&repo_model.FindTopicOptions{}) assert.NoError(t, err) assert.Len(t, topics, totalNrOfTopics) topics, _, err = FindTopics(&FindTopicOptions{ topics, _, err = repo_model.FindTopics(&repo_model.FindTopicOptions{ RepoID: 2, }) assert.NoError(t, err)
-
@@ -67,14 +68,14 @@ func TestAddTopic(t *testing.T) {} func TestTopicValidator(t *testing.T) { assert.True(t, ValidateTopic("12345")) assert.True(t, ValidateTopic("2-test")) assert.True(t, ValidateTopic("test-3")) assert.True(t, ValidateTopic("first")) assert.True(t, ValidateTopic("second-test-topic")) assert.True(t, ValidateTopic("third-project-topic-with-max-length")) assert.False(t, ValidateTopic("$fourth-test,topic")) assert.False(t, ValidateTopic("-fifth-test-topic")) assert.False(t, ValidateTopic("sixth-go-project-topic-with-excess-length")) assert.True(t, repo_model.ValidateTopic("12345")) assert.True(t, repo_model.ValidateTopic("2-test")) assert.True(t, repo_model.ValidateTopic("test-3")) assert.True(t, repo_model.ValidateTopic("first")) assert.True(t, repo_model.ValidateTopic("second-test-topic")) assert.True(t, repo_model.ValidateTopic("third-project-topic-with-max-length")) assert.False(t, repo_model.ValidateTopic("$fourth-test,topic")) assert.False(t, repo_model.ValidateTopic("-fifth-test-topic")) assert.False(t, repo_model.ValidateTopic("sixth-go-project-topic-with-excess-length")) }
-
-
-
@@ -172,3 +172,11 @@ func ChangeRepositoryName(doer *user_model.User, repo *Repository, newRepoName sreturn committer.Commit() } // UpdateRepoSize updates the repository size, calculating it using util.GetDirectorySize func UpdateRepoSize(ctx context.Context, repoID, size int64) error { _, err := db.GetEngine(ctx).ID(repoID).Cols("size").NoAutoTime().Update(&Repository{ Size: size, }) return err }
-
-
-
@@ -5,7 +5,14 @@package repo import ( "context" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" user_model "code.gitea.io/gitea/models/user" api "code.gitea.io/gitea/modules/structs" "xorm.io/builder" ) // GetStarredRepos returns the repos starred by a particular user
-
@@ -48,3 +55,118 @@ func GetWatchedRepos(userID int64, private bool, listOptions db.ListOptions) ([]total, err := sess.FindAndCount(&repos) return repos, total, err } // GetRepoAssignees returns all users that have write access and can be assigned to issues // of the repository, func GetRepoAssignees(ctx context.Context, repo *Repository) (_ []*user_model.User, err error) { if err = repo.GetOwner(ctx); err != nil { return nil, err } e := db.GetEngine(ctx) userIDs := make([]int64, 0, 10) if err = e.Table("access"). Where("repo_id = ? AND mode >= ?", repo.ID, perm.AccessModeWrite). Select("user_id"). Find(&userIDs); err != nil { return nil, err } additionalUserIDs := make([]int64, 0, 10) if err = e.Table("team_user"). Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id"). Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id"). Where("`team_repo`.repo_id = ? AND `team_unit`.access_mode >= ?", repo.ID, perm.AccessModeWrite). Distinct("`team_user`.uid"). Select("`team_user`.uid"). Find(&additionalUserIDs); err != nil { return nil, err } uidMap := map[int64]bool{} i := 0 for _, uid := range userIDs { if uidMap[uid] { continue } uidMap[uid] = true userIDs[i] = uid i++ } userIDs = userIDs[:i] userIDs = append(userIDs, additionalUserIDs...) for _, uid := range additionalUserIDs { if uidMap[uid] { continue } userIDs[i] = uid i++ } userIDs = userIDs[:i] // Leave a seat for owner itself to append later, but if owner is an organization // and just waste 1 unit is cheaper than re-allocate memory once. users := make([]*user_model.User, 0, len(userIDs)+1) if len(userIDs) > 0 { if err = e.In("id", userIDs).Find(&users); err != nil { return nil, err } } if !repo.Owner.IsOrganization() && !uidMap[repo.OwnerID] { users = append(users, repo.Owner) } return users, nil } // GetReviewers get all users can be requested to review: // * for private repositories this returns all users that have read access or higher to the repository. // * for public repositories this returns all users that have read access or higher to the repository, // all repo watchers and all organization members. // TODO: may be we should have a busy choice for users to block review request to them. func GetReviewers(ctx context.Context, repo *Repository, doerID, posterID int64) ([]*user_model.User, error) { // Get the owner of the repository - this often already pre-cached and if so saves complexity for the following queries if err := repo.GetOwner(ctx); err != nil { return nil, err } cond := builder.And(builder.Neq{"`user`.id": posterID}) if repo.IsPrivate || repo.Owner.Visibility == api.VisibleTypePrivate { // This a private repository: // Anyone who can read the repository is a requestable reviewer cond = cond.And(builder.In("`user`.id", builder.Select("user_id").From("access").Where( builder.Eq{"repo_id": repo.ID}. And(builder.Gte{"mode": perm.AccessModeRead}), ), )) if repo.Owner.Type == user_model.UserTypeIndividual && repo.Owner.ID != posterID { // as private *user* repos don't generate an entry in the `access` table, // the owner of a private repo needs to be explicitly added. cond = cond.Or(builder.Eq{"`user`.id": repo.Owner.ID}) } } else { // This is a "public" repository: // Any user that has read access, is a watcher or organization member can be requested to review cond = cond.And(builder.And(builder.In("`user`.id", builder.Select("user_id").From("access"). Where(builder.Eq{"repo_id": repo.ID}. And(builder.Gte{"mode": perm.AccessModeRead})), ).Or(builder.In("`user`.id", builder.Select("user_id").From("watch"). Where(builder.Eq{"repo_id": repo.ID}. And(builder.In("mode", WatchModeNormal, WatchModeAuto))), ).Or(builder.In("`user`.id", builder.Select("uid").From("org_user"). Where(builder.Eq{"org_id": repo.OwnerID}), ))))) } users := make([]*user_model.User, 0, 8) return users, db.GetEngine(ctx).Where(cond).OrderBy("name").Find(&users) }
-
-
-
@@ -0,0 +1,74 @@// Copyright 2017 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_test import ( "testing" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert" ) func TestRepoAssignees(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository) users, err := repo_model.GetRepoAssignees(db.DefaultContext, repo2) assert.NoError(t, err) assert.Len(t, users, 1) assert.Equal(t, users[0].ID, int64(2)) repo21 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 21}).(*repo_model.Repository) users, err = repo_model.GetRepoAssignees(db.DefaultContext, repo21) assert.NoError(t, err) assert.Len(t, users, 3) assert.Equal(t, users[0].ID, int64(15)) assert.Equal(t, users[1].ID, int64(18)) assert.Equal(t, users[2].ID, int64(16)) } func TestRepoGetReviewers(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // test public repo repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) ctx := db.DefaultContext reviewers, err := repo_model.GetReviewers(ctx, repo1, 2, 2) assert.NoError(t, err) assert.Len(t, reviewers, 4) // should include doer if doer is not PR poster. reviewers, err = repo_model.GetReviewers(ctx, repo1, 11, 2) assert.NoError(t, err) assert.Len(t, reviewers, 4) // should not include PR poster, if PR poster would be otherwise eligible reviewers, err = repo_model.GetReviewers(ctx, repo1, 11, 4) assert.NoError(t, err) assert.Len(t, reviewers, 3) // test private user repo repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository) reviewers, err = repo_model.GetReviewers(ctx, repo2, 2, 4) assert.NoError(t, err) assert.Len(t, reviewers, 1) assert.EqualValues(t, reviewers[0].ID, 2) // test private org repo repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}).(*repo_model.Repository) reviewers, err = repo_model.GetReviewers(ctx, repo3, 2, 1) assert.NoError(t, err) assert.Len(t, reviewers, 2) reviewers, err = repo_model.GetReviewers(ctx, repo3, 2, 2) assert.NoError(t, err) assert.Len(t, reviewers, 1) }
-
-
-
@@ -2,12 +2,13 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo package repo_test import ( "testing" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting"
-
@@ -17,20 +18,20 @@ import (func TestIsWatching(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) assert.True(t, IsWatching(1, 1)) assert.True(t, IsWatching(4, 1)) assert.True(t, IsWatching(11, 1)) assert.True(t, repo_model.IsWatching(1, 1)) assert.True(t, repo_model.IsWatching(4, 1)) assert.True(t, repo_model.IsWatching(11, 1)) assert.False(t, IsWatching(1, 5)) assert.False(t, IsWatching(8, 1)) assert.False(t, IsWatching(unittest.NonexistentID, unittest.NonexistentID)) assert.False(t, repo_model.IsWatching(1, 5)) assert.False(t, repo_model.IsWatching(8, 1)) assert.False(t, repo_model.IsWatching(unittest.NonexistentID, unittest.NonexistentID)) } func TestGetWatchers(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) watches, err := GetWatchers(db.DefaultContext, repo.ID) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) watches, err := repo_model.GetWatchers(db.DefaultContext, repo.ID) assert.NoError(t, err) // One watchers are inactive, thus minus 1 assert.Len(t, watches, repo.NumWatches-1)
-
@@ -38,7 +39,7 @@ func TestGetWatchers(t *testing.T) {assert.EqualValues(t, repo.ID, watch.RepoID) } watches, err = GetWatchers(db.DefaultContext, unittest.NonexistentID) watches, err = repo_model.GetWatchers(db.DefaultContext, unittest.NonexistentID) assert.NoError(t, err) assert.Len(t, watches, 0) }
-
@@ -46,16 +47,16 @@ func TestGetWatchers(t *testing.T) {func TestRepository_GetWatchers(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) watchers, err := GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) watchers, err := repo_model.GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, repo.NumWatches) for _, watcher := range watchers { unittest.AssertExistsAndLoadBean(t, &Watch{UserID: watcher.ID, RepoID: repo.ID}) unittest.AssertExistsAndLoadBean(t, &repo_model.Watch{UserID: watcher.ID, RepoID: repo.ID}) } repo = unittest.AssertExistsAndLoadBean(t, &Repository{ID: 9}).(*Repository) watchers, err = GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 9}).(*repo_model.Repository) watchers, err = repo_model.GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, 0) }
-
@@ -63,8 +64,8 @@ func TestRepository_GetWatchers(t *testing.T) {func TestWatchIfAuto(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) watchers, err := GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) watchers, err := repo_model.GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, repo.NumWatches)
-
@@ -73,46 +74,46 @@ func TestWatchIfAuto(t *testing.T) {prevCount := repo.NumWatches // Must not add watch assert.NoError(t, WatchIfAuto(db.DefaultContext, 8, 1, true)) watchers, err = GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 8, 1, true)) watchers, err = repo_model.GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) // Should not add watch assert.NoError(t, WatchIfAuto(db.DefaultContext, 10, 1, true)) watchers, err = GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 10, 1, true)) watchers, err = repo_model.GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) setting.Service.AutoWatchOnChanges = true // Must not add watch assert.NoError(t, WatchIfAuto(db.DefaultContext, 8, 1, true)) watchers, err = GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 8, 1, true)) watchers, err = repo_model.GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) // Should not add watch assert.NoError(t, WatchIfAuto(db.DefaultContext, 12, 1, false)) watchers, err = GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 12, 1, false)) watchers, err = repo_model.GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) // Should add watch assert.NoError(t, WatchIfAuto(db.DefaultContext, 12, 1, true)) watchers, err = GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 12, 1, true)) watchers, err = repo_model.GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount+1) // Should remove watch, inhibit from adding auto assert.NoError(t, WatchRepo(db.DefaultContext, 12, 1, false)) watchers, err = GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, repo_model.WatchRepo(db.DefaultContext, 12, 1, false)) watchers, err = repo_model.GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) // Must not add watch assert.NoError(t, WatchIfAuto(db.DefaultContext, 12, 1, true)) watchers, err = GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, repo_model.WatchIfAuto(db.DefaultContext, 12, 1, true)) watchers, err = repo_model.GetRepoWatchers(repo.ID, db.ListOptions{Page: 1}) assert.NoError(t, err) assert.Len(t, watchers, prevCount) }
-
@@ -120,20 +121,20 @@ func TestWatchIfAuto(t *testing.T) {func TestWatchRepoMode(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) unittest.AssertCount(t, &Watch{UserID: 12, RepoID: 1}, 0) unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 0) assert.NoError(t, WatchRepoMode(12, 1, WatchModeAuto)) unittest.AssertCount(t, &Watch{UserID: 12, RepoID: 1}, 1) unittest.AssertCount(t, &Watch{UserID: 12, RepoID: 1, Mode: WatchModeAuto}, 1) assert.NoError(t, repo_model.WatchRepoMode(12, 1, repo_model.WatchModeAuto)) unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 1) unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1, Mode: repo_model.WatchModeAuto}, 1) assert.NoError(t, WatchRepoMode(12, 1, WatchModeNormal)) unittest.AssertCount(t, &Watch{UserID: 12, RepoID: 1}, 1) unittest.AssertCount(t, &Watch{UserID: 12, RepoID: 1, Mode: WatchModeNormal}, 1) assert.NoError(t, repo_model.WatchRepoMode(12, 1, repo_model.WatchModeNormal)) unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 1) unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1, Mode: repo_model.WatchModeNormal}, 1) assert.NoError(t, WatchRepoMode(12, 1, WatchModeDont)) unittest.AssertCount(t, &Watch{UserID: 12, RepoID: 1}, 1) unittest.AssertCount(t, &Watch{UserID: 12, RepoID: 1, Mode: WatchModeDont}, 1) assert.NoError(t, repo_model.WatchRepoMode(12, 1, repo_model.WatchModeDont)) unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 1) unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1, Mode: repo_model.WatchModeDont}, 1) assert.NoError(t, WatchRepoMode(12, 1, WatchModeNone)) unittest.AssertCount(t, &Watch{UserID: 12, RepoID: 1}, 0) assert.NoError(t, repo_model.WatchRepoMode(12, 1, repo_model.WatchModeNone)) unittest.AssertCount(t, &repo_model.Watch{UserID: 12, RepoID: 1}, 0) }
-
-
-
@@ -2,12 +2,13 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package repo package repo_test import ( "path/filepath" "testing" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting"
-
@@ -17,7 +18,7 @@ import (func TestRepository_WikiCloneLink(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) cloneLink := repo.WikiCloneLink() assert.Equal(t, "ssh://sshuser@try.gitea.io:3000/user2/repo1.wiki.git", cloneLink.SSH) assert.Equal(t, "https://try.gitea.io/user2/repo1.wiki.git", cloneLink.HTTPS)
-
@@ -26,20 +27,20 @@ func TestRepository_WikiCloneLink(t *testing.T) {func TestWikiPath(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) expected := filepath.Join(setting.RepoRootPath, "user2/repo1.wiki.git") assert.Equal(t, expected, WikiPath("user2", "repo1")) assert.Equal(t, expected, repo_model.WikiPath("user2", "repo1")) } func TestRepository_WikiPath(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) expected := filepath.Join(setting.RepoRootPath, "user2/repo1.wiki.git") assert.Equal(t, expected, repo.WikiPath()) } func TestRepository_HasWiki(t *testing.T) { unittest.PrepareTestEnv(t) repo1 := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) assert.True(t, repo1.HasWiki()) repo2 := unittest.AssertExistsAndLoadBean(t, &Repository{ID: 2}).(*Repository) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository) assert.False(t, repo2.HasWiki()) }
-
-
models/repo_generate.go (deleted)
-
@@ -1,118 +0,0 @@// Copyright 2019 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 models import ( "bufio" "bytes" "context" "strings" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/log" "github.com/gobwas/glob" ) // GenerateRepoOptions contains the template units to generate type GenerateRepoOptions struct { Name string DefaultBranch string Description string Private bool GitContent bool Topics bool GitHooks bool Webhooks bool Avatar bool IssueLabels bool } // IsValid checks whether at least one option is chosen for generation func (gro GenerateRepoOptions) IsValid() bool { return gro.GitContent || gro.Topics || gro.GitHooks || gro.Webhooks || gro.Avatar || gro.IssueLabels // or other items as they are added } // GiteaTemplate holds information about a .gitea/template file type GiteaTemplate struct { Path string Content []byte globs []glob.Glob } // Globs parses the .gitea/template globs or returns them if they were already parsed func (gt GiteaTemplate) Globs() []glob.Glob { if gt.globs != nil { return gt.globs } gt.globs = make([]glob.Glob, 0) scanner := bufio.NewScanner(bytes.NewReader(gt.Content)) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line == "" || strings.HasPrefix(line, "#") { continue } g, err := glob.Compile(line, '/') if err != nil { log.Info("Invalid glob expression '%s' (skipped): %v", line, err) continue } gt.globs = append(gt.globs, g) } return gt.globs } // GenerateWebhooks generates webhooks from a template repository func GenerateWebhooks(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error { templateWebhooks, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{RepoID: templateRepo.ID}) if err != nil { return err } for _, templateWebhook := range templateWebhooks { generateWebhook := &webhook.Webhook{ RepoID: generateRepo.ID, URL: templateWebhook.URL, HTTPMethod: templateWebhook.HTTPMethod, ContentType: templateWebhook.ContentType, Secret: templateWebhook.Secret, HookEvent: templateWebhook.HookEvent, IsActive: templateWebhook.IsActive, Type: templateWebhook.Type, OrgID: templateWebhook.OrgID, Events: templateWebhook.Events, Meta: templateWebhook.Meta, } if err := webhook.CreateWebhook(ctx, generateWebhook); err != nil { return err } } return nil } // GenerateIssueLabels generates issue labels from a template repository func GenerateIssueLabels(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error { templateLabels, err := GetLabelsByRepoID(ctx, templateRepo.ID, "", db.ListOptions{}) if err != nil { return err } for _, templateLabel := range templateLabels { generateLabel := &Label{ RepoID: generateRepo.ID, Name: templateLabel.Name, Description: templateLabel.Description, Color: templateLabel.Color, } if err := db.Insert(ctx, generateLabel); err != nil { return err } } return nil }
-
-
models/repo_list.go (deleted)
-
@@ -1,704 +0,0 @@// Copyright 2017 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 models import ( "context" "fmt" "strings" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "xorm.io/builder" ) // RepositoryListDefaultPageSize is the default number of repositories // to load in memory when running administrative tasks on all (or almost // all) of them. // The number should be low enough to avoid filling up all RAM with // repository data... const RepositoryListDefaultPageSize = 64 // RepositoryList contains a list of repositories type RepositoryList []*repo_model.Repository func (repos RepositoryList) Len() int { return len(repos) } func (repos RepositoryList) Less(i, j int) bool { return repos[i].FullName() < repos[j].FullName() } func (repos RepositoryList) Swap(i, j int) { repos[i], repos[j] = repos[j], repos[i] } // FIXME: Remove in favor of maps.values when MIN_GO_VERSION >= 1.18 func valuesRepository(m map[int64]*repo_model.Repository) []*repo_model.Repository { values := make([]*repo_model.Repository, 0, len(m)) for _, v := range m { values = append(values, v) } return values } // RepositoryListOfMap make list from values of map func RepositoryListOfMap(repoMap map[int64]*repo_model.Repository) RepositoryList { return RepositoryList(valuesRepository(repoMap)) } func (repos RepositoryList) loadAttributes(ctx context.Context) error { if len(repos) == 0 { return nil } set := make(map[int64]struct{}) repoIDs := make([]int64, len(repos)) for i := range repos { set[repos[i].OwnerID] = struct{}{} repoIDs[i] = repos[i].ID } // Load owners. users := make(map[int64]*user_model.User, len(set)) if err := db.GetEngine(ctx). Where("id > 0"). In("id", container.KeysInt64(set)). Find(&users); err != nil { return fmt.Errorf("find users: %v", err) } for i := range repos { repos[i].Owner = users[repos[i].OwnerID] } // Load primary language. stats := make(repo_model.LanguageStatList, 0, len(repos)) if err := db.GetEngine(ctx). Where("`is_primary` = ? AND `language` != ?", true, "other"). In("`repo_id`", repoIDs). Find(&stats); err != nil { return fmt.Errorf("find primary languages: %v", err) } stats.LoadAttributes() for i := range repos { for _, st := range stats { if st.RepoID == repos[i].ID { repos[i].PrimaryLanguage = st break } } } return nil } // LoadAttributes loads the attributes for the given RepositoryList func (repos RepositoryList) LoadAttributes() error { return repos.loadAttributes(db.DefaultContext) } // SearchRepoOptions holds the search options type SearchRepoOptions struct { db.ListOptions Actor *user_model.User Keyword string OwnerID int64 PriorityOwnerID int64 TeamID int64 OrderBy db.SearchOrderBy Private bool // Include private repositories in results StarredByID int64 WatchedByID int64 AllPublic bool // Include also all public repositories of users and public organisations AllLimited bool // Include also all public repositories of limited organisations // None -> include public and private // True -> include just private // False -> include just public IsPrivate util.OptionalBool // None -> include collaborative AND non-collaborative // True -> include just collaborative // False -> include just non-collaborative Collaborate util.OptionalBool // None -> include forks AND non-forks // True -> include just forks // False -> include just non-forks Fork util.OptionalBool // None -> include templates AND non-templates // True -> include just templates // False -> include just non-templates Template util.OptionalBool // None -> include mirrors AND non-mirrors // True -> include just mirrors // False -> include just non-mirrors Mirror util.OptionalBool // None -> include archived AND non-archived // True -> include just archived // False -> include just non-archived Archived util.OptionalBool // only search topic name TopicOnly bool // only search repositories with specified primary language Language string // include description in keyword search IncludeDescription bool // None -> include has milestones AND has no milestone // True -> include just has milestones // False -> include just has no milestone HasMilestones util.OptionalBool // LowerNames represents valid lower names to restrict to LowerNames []string } // SearchOrderBy is used to sort the result type SearchOrderBy string func (s SearchOrderBy) String() string { return string(s) } // Strings for sorting result const ( SearchOrderByAlphabetically SearchOrderBy = "name ASC" SearchOrderByAlphabeticallyReverse SearchOrderBy = "name DESC" SearchOrderByLeastUpdated SearchOrderBy = "updated_unix ASC" SearchOrderByRecentUpdated SearchOrderBy = "updated_unix DESC" SearchOrderByOldest SearchOrderBy = "created_unix ASC" SearchOrderByNewest SearchOrderBy = "created_unix DESC" SearchOrderBySize SearchOrderBy = "size ASC" SearchOrderBySizeReverse SearchOrderBy = "size DESC" SearchOrderByID SearchOrderBy = "id ASC" SearchOrderByIDReverse SearchOrderBy = "id DESC" SearchOrderByStars SearchOrderBy = "num_stars ASC" SearchOrderByStarsReverse SearchOrderBy = "num_stars DESC" SearchOrderByForks SearchOrderBy = "num_forks ASC" SearchOrderByForksReverse SearchOrderBy = "num_forks DESC" ) // userOwnedRepoCond returns user ownered repositories func userOwnedRepoCond(userID int64) builder.Cond { return builder.Eq{ "repository.owner_id": userID, } } // userAssignedRepoCond return user as assignee repositories list func userAssignedRepoCond(id string, userID int64) builder.Cond { return builder.And( builder.Eq{ "repository.is_private": false, }, builder.In(id, builder.Select("issue.repo_id").From("issue_assignees"). InnerJoin("issue", "issue.id = issue_assignees.issue_id"). Where(builder.Eq{ "issue_assignees.assignee_id": userID, }), ), ) } // userCreateIssueRepoCond return user created issues repositories list func userCreateIssueRepoCond(id string, userID int64, isPull bool) builder.Cond { return builder.And( builder.Eq{ "repository.is_private": false, }, builder.In(id, builder.Select("issue.repo_id").From("issue"). Where(builder.Eq{ "issue.poster_id": userID, "issue.is_pull": isPull, }), ), ) } // userMentionedRepoCond return user metinoed repositories list func userMentionedRepoCond(id string, userID int64) builder.Cond { return builder.And( builder.Eq{ "repository.is_private": false, }, builder.In(id, builder.Select("issue.repo_id").From("issue_user"). InnerJoin("issue", "issue.id = issue_user.issue_id"). Where(builder.Eq{ "issue_user.is_mentioned": true, "issue_user.uid": userID, }), ), ) } // teamUnitsRepoCond returns query condition for those repo id in the special org team with special units access func teamUnitsRepoCond(id string, userID, orgID, teamID int64, units ...unit.Type) builder.Cond { return builder.In(id, builder.Select("repo_id").From("team_repo").Where( builder.Eq{ "team_id": teamID, }.And( builder.Or( // Check if the user is member of the team. builder.In( "team_id", builder.Select("team_id").From("team_user").Where( builder.Eq{ "uid": userID, }, ), ), // Check if the user is in the owner team of the organisation. builder.Exists(builder.Select("team_id").From("team_user"). Where(builder.Eq{ "org_id": orgID, "team_id": builder.Select("id").From("team").Where( builder.Eq{ "org_id": orgID, "lower_name": strings.ToLower(organization.OwnerTeamName), }), "uid": userID, }), ), )).And( builder.In( "team_id", builder.Select("team_id").From("team_unit").Where( builder.Eq{ "`team_unit`.org_id": orgID, }.And( builder.In("`team_unit`.type", units), ), ), ), ), )) } // userCollaborationRepoCond returns user as collabrators repositories list func userCollaborationRepoCond(idStr string, userID int64) builder.Cond { return builder.In(idStr, builder.Select("repo_id"). From("`access`"). Where(builder.And( builder.Eq{"`access`.user_id": userID}, builder.Gt{"`access`.mode": int(perm.AccessModeNone)}, )), ) } // userOrgTeamRepoCond selects repos that the given user has access to through team membership func userOrgTeamRepoCond(idStr string, userID int64) builder.Cond { return builder.In(idStr, userOrgTeamRepoBuilder(userID)) } // userOrgTeamRepoBuilder returns repo ids where user's teams can access. func userOrgTeamRepoBuilder(userID int64) *builder.Builder { return builder.Select("`team_repo`.repo_id"). From("team_repo"). Join("INNER", "team_user", "`team_user`.team_id = `team_repo`.team_id"). Where(builder.Eq{"`team_user`.uid": userID}) } // userOrgTeamUnitRepoBuilder returns repo ids where user's teams can access the special unit. func userOrgTeamUnitRepoBuilder(userID int64, unitType unit.Type) *builder.Builder { return userOrgTeamRepoBuilder(userID). Join("INNER", "team_unit", "`team_unit`.team_id = `team_repo`.team_id"). Where(builder.Eq{"`team_unit`.`type`": unitType}) } // userOrgUnitRepoCond selects repos that the given user has access to through org and the special unit func userOrgUnitRepoCond(idStr string, userID, orgID int64, unitType unit.Type) builder.Cond { return builder.In(idStr, userOrgTeamUnitRepoBuilder(userID, unitType). And(builder.Eq{"`team_unit`.org_id": orgID}), ) } // userOrgPublicRepoCond returns the condition that one user could access all public repositories in organizations func userOrgPublicRepoCond(userID int64) builder.Cond { return builder.And( builder.Eq{"`repository`.is_private": false}, builder.In("`repository`.owner_id", builder.Select("`org_user`.org_id"). From("org_user"). Where(builder.Eq{"`org_user`.uid": userID}), ), ) } // userOrgPublicRepoCondPrivate returns the condition that one user could access all public repositories in private organizations func userOrgPublicRepoCondPrivate(userID int64) builder.Cond { return builder.And( builder.Eq{"`repository`.is_private": false}, builder.In("`repository`.owner_id", builder.Select("`org_user`.org_id"). From("org_user"). Join("INNER", "`user`", "`user`.id = `org_user`.org_id"). Where(builder.Eq{ "`org_user`.uid": userID, "`user`.`type`": user_model.UserTypeOrganization, "`user`.visibility": structs.VisibleTypePrivate, }), ), ) } // userOrgPublicUnitRepoCond returns the condition that one user could access all public repositories in the special organization func userOrgPublicUnitRepoCond(userID, orgID int64) builder.Cond { return userOrgPublicRepoCond(userID). And(builder.Eq{"`repository`.owner_id": orgID}) } // SearchRepositoryCondition creates a query condition according search repository options func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { cond := builder.NewCond() if opts.Private { if opts.Actor != nil && !opts.Actor.IsAdmin && opts.Actor.ID != opts.OwnerID { // OK we're in the context of a User cond = cond.And(accessibleRepositoryCondition(opts.Actor)) } } else { // Not looking at private organisations and users // We should be able to see all non-private repositories that // isn't in a private or limited organisation. cond = cond.And( builder.Eq{"is_private": false}, builder.NotIn("owner_id", builder.Select("id").From("`user`").Where( builder.Or(builder.Eq{"visibility": structs.VisibleTypeLimited}, builder.Eq{"visibility": structs.VisibleTypePrivate}), ))) } if opts.IsPrivate != util.OptionalBoolNone { cond = cond.And(builder.Eq{"is_private": opts.IsPrivate.IsTrue()}) } if opts.Template != util.OptionalBoolNone { cond = cond.And(builder.Eq{"is_template": opts.Template == util.OptionalBoolTrue}) } // Restrict to starred repositories if opts.StarredByID > 0 { cond = cond.And(builder.In("id", builder.Select("repo_id").From("star").Where(builder.Eq{"uid": opts.StarredByID}))) } // Restrict to watched repositories if opts.WatchedByID > 0 { cond = cond.And(builder.In("id", builder.Select("repo_id").From("watch").Where(builder.Eq{"user_id": opts.WatchedByID}))) } // Restrict repositories to those the OwnerID owns or contributes to as per opts.Collaborate if opts.OwnerID > 0 { accessCond := builder.NewCond() if opts.Collaborate != util.OptionalBoolTrue { accessCond = builder.Eq{"owner_id": opts.OwnerID} } if opts.Collaborate != util.OptionalBoolFalse { // A Collaboration is: collaborateCond := builder.And( // 1. Repository we don't own builder.Neq{"owner_id": opts.OwnerID}, // 2. But we can see because of: builder.Or( // A. We have access userCollaborationRepoCond("`repository`.id", opts.OwnerID), // B. We are in a team for userOrgTeamRepoCond("`repository`.id", opts.OwnerID), // C. Public repositories in organizations that we are member of userOrgPublicRepoCondPrivate(opts.OwnerID), ), ) if !opts.Private { collaborateCond = collaborateCond.And(builder.Expr("owner_id NOT IN (SELECT org_id FROM org_user WHERE org_user.uid = ? AND org_user.is_public = ?)", opts.OwnerID, false)) } accessCond = accessCond.Or(collaborateCond) } if opts.AllPublic { accessCond = accessCond.Or(builder.Eq{"is_private": false}.And(builder.In("owner_id", builder.Select("`user`.id").From("`user`").Where(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})))) } if opts.AllLimited { accessCond = accessCond.Or(builder.Eq{"is_private": false}.And(builder.In("owner_id", builder.Select("`user`.id").From("`user`").Where(builder.Eq{"`user`.visibility": structs.VisibleTypeLimited})))) } cond = cond.And(accessCond) } if opts.TeamID > 0 { cond = cond.And(builder.In("`repository`.id", builder.Select("`team_repo`.repo_id").From("team_repo").Where(builder.Eq{"`team_repo`.team_id": opts.TeamID}))) } if opts.Keyword != "" { // separate keyword subQueryCond := builder.NewCond() for _, v := range strings.Split(opts.Keyword, ",") { if opts.TopicOnly { subQueryCond = subQueryCond.Or(builder.Eq{"topic.name": strings.ToLower(v)}) } else { subQueryCond = subQueryCond.Or(builder.Like{"topic.name", strings.ToLower(v)}) } } subQuery := builder.Select("repo_topic.repo_id").From("repo_topic"). Join("INNER", "topic", "topic.id = repo_topic.topic_id"). Where(subQueryCond). GroupBy("repo_topic.repo_id") keywordCond := builder.In("id", subQuery) if !opts.TopicOnly { likes := builder.NewCond() for _, v := range strings.Split(opts.Keyword, ",") { likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)}) // If the string looks like "org/repo", match against that pattern too if opts.TeamID == 0 && strings.Count(opts.Keyword, "/") == 1 { pieces := strings.Split(opts.Keyword, "/") ownerName := pieces[0] repoName := pieces[1] likes = likes.Or(builder.And(builder.Like{"owner_name", strings.ToLower(ownerName)}, builder.Like{"lower_name", strings.ToLower(repoName)})) } if opts.IncludeDescription { likes = likes.Or(builder.Like{"LOWER(description)", strings.ToLower(v)}) } } keywordCond = keywordCond.Or(likes) } cond = cond.And(keywordCond) } if opts.Language != "" { cond = cond.And(builder.In("id", builder. Select("repo_id"). From("language_stat"). Where(builder.Eq{"language": opts.Language}).And(builder.Eq{"is_primary": true}))) } if opts.Fork != util.OptionalBoolNone { cond = cond.And(builder.Eq{"is_fork": opts.Fork == util.OptionalBoolTrue}) } if opts.Mirror != util.OptionalBoolNone { cond = cond.And(builder.Eq{"is_mirror": opts.Mirror == util.OptionalBoolTrue}) } if opts.Actor != nil && opts.Actor.IsRestricted { cond = cond.And(accessibleRepositoryCondition(opts.Actor)) } if opts.Archived != util.OptionalBoolNone { cond = cond.And(builder.Eq{"is_archived": opts.Archived == util.OptionalBoolTrue}) } switch opts.HasMilestones { case util.OptionalBoolTrue: cond = cond.And(builder.Gt{"num_milestones": 0}) case util.OptionalBoolFalse: cond = cond.And(builder.Eq{"num_milestones": 0}.Or(builder.IsNull{"num_milestones"})) } return cond } // SearchRepository returns repositories based on search options, // it returns results in given range and number of total results. func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) { cond := SearchRepositoryCondition(opts) return SearchRepositoryByCondition(opts, cond, true) } // SearchRepositoryByCondition search repositories by condition func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) { ctx := db.DefaultContext sess, count, err := searchRepositoryByCondition(ctx, opts, cond) if err != nil { return nil, 0, err } defaultSize := 50 if opts.PageSize > 0 { defaultSize = opts.PageSize } repos := make(RepositoryList, 0, defaultSize) if err := sess.Find(&repos); err != nil { return nil, 0, fmt.Errorf("Repo: %v", err) } if opts.PageSize <= 0 { count = int64(len(repos)) } if loadAttributes { if err := repos.loadAttributes(ctx); err != nil { return nil, 0, fmt.Errorf("LoadAttributes: %v", err) } } return repos, count, nil } func searchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, cond builder.Cond) (db.Engine, int64, error) { if opts.Page <= 0 { opts.Page = 1 } if len(opts.OrderBy) == 0 { opts.OrderBy = db.SearchOrderByAlphabetically } args := make([]interface{}, 0) if opts.PriorityOwnerID > 0 { opts.OrderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_id = ? THEN 0 ELSE owner_id END, %s", opts.OrderBy)) args = append(args, opts.PriorityOwnerID) } else if strings.Count(opts.Keyword, "/") == 1 { // With "owner/repo" search times, prioritise results which match the owner field orgName := strings.Split(opts.Keyword, "/")[0] opts.OrderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_name LIKE ? THEN 0 ELSE 1 END, %s", opts.OrderBy)) args = append(args, orgName) } sess := db.GetEngine(ctx) var count int64 if opts.PageSize > 0 { var err error count, err = sess. Where(cond). Count(new(repo_model.Repository)) if err != nil { return nil, 0, fmt.Errorf("Count: %v", err) } } sess = sess.Where(cond).OrderBy(opts.OrderBy.String(), args...) if opts.PageSize > 0 { sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) } return sess, count, nil } // accessibleRepositoryCondition takes a user a returns a condition for checking if a repository is accessible func accessibleRepositoryCondition(user *user_model.User) builder.Cond { cond := builder.NewCond() if user == nil || !user.IsRestricted || user.ID <= 0 { orgVisibilityLimit := []structs.VisibleType{structs.VisibleTypePrivate} if user == nil || user.ID <= 0 { orgVisibilityLimit = append(orgVisibilityLimit, structs.VisibleTypeLimited) } // 1. Be able to see all non-private repositories that either: cond = cond.Or(builder.And( builder.Eq{"`repository`.is_private": false}, // 2. Aren't in an private organisation or limited organisation if we're not logged in builder.NotIn("`repository`.owner_id", builder.Select("id").From("`user`").Where( builder.And( builder.Eq{"type": user_model.UserTypeOrganization}, builder.In("visibility", orgVisibilityLimit)), )))) } if user != nil { cond = cond.Or( // 2. Be able to see all repositories that we have access to userCollaborationRepoCond("`repository`.id", user.ID), // 3. Repositories that we directly own builder.Eq{"`repository`.owner_id": user.ID}, // 4. Be able to see all repositories that we are in a team userOrgTeamRepoCond("`repository`.id", user.ID), // 5. Be able to see all public repos in private organizations that we are an org_user of userOrgPublicRepoCond(user.ID), ) } return cond } // SearchRepositoryByName takes keyword and part of repository name to search, // it returns results in given range and number of total results. func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, error) { opts.IncludeDescription = false return SearchRepository(opts) } // SearchRepositoryIDs takes keyword and part of repository name to search, // it returns results in given range and number of total results. func SearchRepositoryIDs(opts *SearchRepoOptions) ([]int64, int64, error) { opts.IncludeDescription = false cond := SearchRepositoryCondition(opts) sess, count, err := searchRepositoryByCondition(db.DefaultContext, opts, cond) if err != nil { return nil, 0, err } defaultSize := 50 if opts.PageSize > 0 { defaultSize = opts.PageSize } ids := make([]int64, 0, defaultSize) err = sess.Select("id").Table("repository").Find(&ids) if opts.PageSize <= 0 { count = int64(len(ids)) } return ids, count, err } // AccessibleRepoIDsQuery queries accessible repository ids. Usable as a subquery wherever repo ids need to be filtered. func AccessibleRepoIDsQuery(user *user_model.User) *builder.Builder { // NB: Please note this code needs to still work if user is nil return builder.Select("id").From("repository").Where(accessibleRepositoryCondition(user)) } // FindUserAccessibleRepoIDs find all accessible repositories' ID by user's id func FindUserAccessibleRepoIDs(user *user_model.User) ([]int64, error) { repoIDs := make([]int64, 0, 10) if err := db.GetEngine(db.DefaultContext). Table("repository"). Cols("id"). Where(accessibleRepositoryCondition(user)). Find(&repoIDs); err != nil { return nil, fmt.Errorf("FindUserAccesibleRepoIDs: %v", err) } return repoIDs, nil } // GetUserRepositories returns a list of repositories of given user. func GetUserRepositories(opts *SearchRepoOptions) (RepositoryList, int64, error) { if len(opts.OrderBy) == 0 { opts.OrderBy = "updated_unix DESC" } cond := builder.NewCond() cond = cond.And(builder.Eq{"owner_id": opts.Actor.ID}) if !opts.Private { cond = cond.And(builder.Eq{"is_private": false}) } if opts.LowerNames != nil && len(opts.LowerNames) > 0 { cond = cond.And(builder.In("lower_name", opts.LowerNames)) } sess := db.GetEngine(db.DefaultContext) count, err := sess.Where(cond).Count(new(repo_model.Repository)) if err != nil { return nil, 0, fmt.Errorf("Count: %v", err) } sess = sess.Where(cond).OrderBy(opts.OrderBy.String()) repos := make(RepositoryList, 0, opts.PageSize) return repos, count, db.SetSessionPagination(sess, opts).Find(&repos) }
-
-
-
@@ -84,127 +84,8 @@ func TestMetas(t *testing.T) {assert.Equal(t, ",owners,team1,", metas["teams"]) } func TestUpdateRepositoryVisibilityChanged(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // Get sample repo and change visibility repo, err := repo_model.GetRepositoryByID(9) assert.NoError(t, err) repo.IsPrivate = true // Update it err = UpdateRepository(repo, true) assert.NoError(t, err) // Check visibility of action has become private act := Action{} _, err = db.GetEngine(db.DefaultContext).ID(3).Get(&act) assert.NoError(t, err) assert.True(t, act.IsPrivate) } func TestDoctorUserStarNum(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, DoctorUserStarNum()) } func TestRepoGetReviewers(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // test public repo repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) reviewers, err := GetReviewers(repo1, 2, 2) assert.NoError(t, err) assert.Len(t, reviewers, 4) // should include doer if doer is not PR poster. reviewers, err = GetReviewers(repo1, 11, 2) assert.NoError(t, err) assert.Len(t, reviewers, 4) // should not include PR poster, if PR poster would be otherwise eligible reviewers, err = GetReviewers(repo1, 11, 4) assert.NoError(t, err) assert.Len(t, reviewers, 3) // test private user repo repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository) reviewers, err = GetReviewers(repo2, 2, 4) assert.NoError(t, err) assert.Len(t, reviewers, 1) assert.EqualValues(t, reviewers[0].ID, 2) // test private org repo repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}).(*repo_model.Repository) reviewers, err = GetReviewers(repo3, 2, 1) assert.NoError(t, err) assert.Len(t, reviewers, 2) reviewers, err = GetReviewers(repo3, 2, 2) assert.NoError(t, err) assert.Len(t, reviewers, 1) } func TestRepoGetReviewerTeams(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository) teams, err := GetReviewerTeams(repo2) assert.NoError(t, err) assert.Empty(t, teams) repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}).(*repo_model.Repository) teams, err = GetReviewerTeams(repo3) assert.NoError(t, err) assert.Len(t, teams, 2) } func TestLinkedRepository(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testCases := []struct { name string attachID int64 expectedRepo *repo_model.Repository expectedUnitType unit.Type }{ {"LinkedIssue", 1, &repo_model.Repository{ID: 1}, unit.TypeIssues}, {"LinkedComment", 3, &repo_model.Repository{ID: 1}, unit.TypePullRequests}, {"LinkedRelease", 9, &repo_model.Repository{ID: 1}, unit.TypeReleases}, {"Notlinked", 10, nil, -1}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { attach, err := repo_model.GetAttachmentByID(db.DefaultContext, tc.attachID) assert.NoError(t, err) repo, unitType, err := LinkedRepository(attach) assert.NoError(t, err) if tc.expectedRepo != nil { assert.Equal(t, tc.expectedRepo.ID, repo.ID) } assert.Equal(t, tc.expectedUnitType, unitType) }) } } func TestRepoAssignees(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository) users, err := GetRepoAssignees(repo2) assert.NoError(t, err) assert.Len(t, users, 1) assert.Equal(t, users[0].ID, int64(2)) repo21 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 21}).(*repo_model.Repository) users, err = GetRepoAssignees(repo21) assert.NoError(t, err) assert.Len(t, users, 3) assert.Equal(t, users[0].ID, int64(15)) assert.Equal(t, users[1].ID, int64(18)) assert.Equal(t, users[2].ID, int64(16)) }
-
-
-
@@ -397,6 +397,14 @@ func CreateWebhook(ctx context.Context, w *Webhook) error {return db.Insert(ctx, w) } // CreateWebhooks creates multiple web hooks func CreateWebhooks(ctx context.Context, ws []*Webhook) error { for i := 0; i < len(ws); i++ { ws[i].Type = strings.TrimSpace(ws[i].Type) } return db.Insert(ctx, ws) } // getWebhook uses argument bean as query condition, // ID must be specified and do not assign unnecessary fields. func getWebhook(bean *Webhook) (*Webhook, error) {
-
-
-
@@ -26,6 +26,7 @@ import (code_indexer "code.gitea.io/gitea/modules/indexer/code" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup/markdown" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util"
-
@@ -551,14 +552,14 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {ctx.Data["CanWriteIssues"] = ctx.Repo.CanWrite(unit_model.TypeIssues) ctx.Data["CanWritePulls"] = ctx.Repo.CanWrite(unit_model.TypePullRequests) canSignedUserFork, err := models.CanUserForkRepo(ctx.Doer, ctx.Repo.Repository) canSignedUserFork, err := repo_module.CanUserForkRepo(ctx.Doer, ctx.Repo.Repository) if err != nil { ctx.ServerError("CanUserForkRepo", err) return } ctx.Data["CanSignedUserFork"] = canSignedUserFork userAndOrgForks, err := models.GetForksByUserAndOrgs(ctx, ctx.Doer, ctx.Repo.Repository) userAndOrgForks, err := repo_model.GetForksByUserAndOrgs(ctx, ctx.Doer, ctx.Repo.Repository) if err != nil { ctx.ServerError("GetForksByUserAndOrgs", err) return
-
-
-
@@ -291,8 +291,8 @@ func populateIssueIndexer(ctx context.Context) {return default: } repos, _, err := models.SearchRepositoryByName(&models.SearchRepoOptions{ ListOptions: db.ListOptions{Page: page, PageSize: models.RepositoryListDefaultPageSize}, repos, _, err := repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{Page: page, PageSize: repo_model.RepositoryListDefaultPageSize}, OrderBy: db.SearchOrderByID, Private: true, Collaborate: util.OptionalBoolFalse,
-
-
-
@@ -7,15 +7,20 @@ package repositoryimport ( "context" "fmt" "os" "path" "strings" "unicode/utf8" "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" )
-
@@ -108,7 +113,7 @@ func CreateRepository(doer, u *user_model.User, opts models.CreateRepoOptions) (} } if err := models.CheckDaemonExportOK(ctx, repo); err != nil { if err := CheckDaemonExportOK(ctx, repo); err != nil { return fmt.Errorf("checkDaemonExportOK: %v", err) }
-
@@ -133,3 +138,111 @@ func CreateRepository(doer, u *user_model.User, opts models.CreateRepoOptions) (return repo, nil } // UpdateRepoSize updates the repository size, calculating it using util.GetDirectorySize func UpdateRepoSize(ctx context.Context, repo *repo_model.Repository) error { size, err := util.GetDirectorySize(repo.RepoPath()) if err != nil { return fmt.Errorf("updateSize: %v", err) } lfsSize, err := models.GetRepoLFSSize(ctx, repo.ID) if err != nil { return fmt.Errorf("updateSize: GetLFSMetaObjects: %v", err) } return repo_model.UpdateRepoSize(ctx, repo.ID, size+lfsSize) } // CheckDaemonExportOK creates/removes git-daemon-export-ok for git-daemon... func CheckDaemonExportOK(ctx context.Context, repo *repo_model.Repository) error { if err := repo.GetOwner(ctx); err != nil { return err } // Create/Remove git-daemon-export-ok for git-daemon... daemonExportFile := path.Join(repo.RepoPath(), `git-daemon-export-ok`) isExist, err := util.IsExist(daemonExportFile) if err != nil { log.Error("Unable to check if %s exists. Error: %v", daemonExportFile, err) return err } isPublic := !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePublic if !isPublic && isExist { if err = util.Remove(daemonExportFile); err != nil { log.Error("Failed to remove %s: %v", daemonExportFile, err) } } else if isPublic && !isExist { if f, err := os.Create(daemonExportFile); err != nil { log.Error("Failed to create %s: %v", daemonExportFile, err) } else { f.Close() } } return nil } // UpdateRepository updates a repository with db context func UpdateRepository(ctx context.Context, repo *repo_model.Repository, visibilityChanged bool) (err error) { repo.LowerName = strings.ToLower(repo.Name) if utf8.RuneCountInString(repo.Description) > 255 { repo.Description = string([]rune(repo.Description)[:255]) } if utf8.RuneCountInString(repo.Website) > 255 { repo.Website = string([]rune(repo.Website)[:255]) } e := db.GetEngine(ctx) if _, err = e.ID(repo.ID).AllCols().Update(repo); err != nil { return fmt.Errorf("update: %v", err) } if err = UpdateRepoSize(ctx, repo); err != nil { log.Error("Failed to update size for repository: %v", err) } if visibilityChanged { if err = repo.GetOwner(ctx); err != nil { return fmt.Errorf("getOwner: %v", err) } if repo.Owner.IsOrganization() { // Organization repository need to recalculate access table when visibility is changed. if err = access_model.RecalculateTeamAccesses(ctx, repo, 0); err != nil { return fmt.Errorf("recalculateTeamAccesses: %v", err) } } // If repo has become private, we need to set its actions to private. if repo.IsPrivate { _, err = e.Where("repo_id = ?", repo.ID).Cols("is_private").Update(&models.Action{ IsPrivate: true, }) if err != nil { return err } } // Create/Remove git-daemon-export-ok for git-daemon... if err := CheckDaemonExportOK(db.WithEngine(ctx, e), repo); err != nil { return err } forkRepos, err := repo_model.GetRepositoriesByForkID(ctx, repo.ID) if err != nil { return fmt.Errorf("getRepositoriesByForkID: %v", err) } for i := range forkRepos { forkRepos[i].IsPrivate = repo.IsPrivate || repo.Owner.Visibility == api.VisibleTypePrivate if err = UpdateRepository(ctx, forkRepos[i], true); err != nil { return fmt.Errorf("updateRepository[%d]: %v", forkRepos[i].ID, err) } } } return nil }
-
-
-
@@ -12,6 +12,7 @@ import ("code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/structs"
-
@@ -147,3 +148,23 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) {} assert.NoError(t, organization.DeleteOrganization(db.DefaultContext, org), "DeleteOrganization") } func TestUpdateRepositoryVisibilityChanged(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // Get sample repo and change visibility repo, err := repo_model.GetRepositoryByID(9) assert.NoError(t, err) repo.IsPrivate = true // Update it err = UpdateRepository(db.DefaultContext, repo, true) assert.NoError(t, err) // Check visibility of action has become private act := models.Action{} _, err = db.GetEngine(db.DefaultContext).ID(3).Get(&act) assert.NoError(t, err) assert.True(t, act.IsPrivate) }
-
-
-
@@ -0,0 +1,33 @@// Copyright 2022 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 repository import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" ) // CanUserDelete returns true if user could delete the repository func CanUserDelete(repo *repo_model.Repository, user *user_model.User) (bool, error) { if user.IsAdmin || user.ID == repo.OwnerID { return true, nil } if err := repo.GetOwner(db.DefaultContext); err != nil { return false, err } if repo.Owner.IsOrganization() { isOwner, err := organization.OrgFromUser(repo.Owner).IsOwnedBy(user.ID) if err != nil { return false, err } return isOwner, nil } return false, nil }
-
-
-
@@ -0,0 +1,31 @@// Copyright 2019 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 repository import ( "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" ) // CanUserForkRepo returns true if specified user can fork repository. func CanUserForkRepo(user *user_model.User, repo *repo_model.Repository) (bool, error) { if user == nil { return false, nil } if repo.OwnerID != user.ID && !repo_model.HasForkedRepo(user.ID, repo.ID) { return true, nil } ownedOrgs, err := organization.GetOrgsCanCreateRepoByUserID(user.ID) if err != nil { return false, err } for _, org := range ownedOrgs { if repo.OwnerID != org.ID && !repo_model.HasForkedRepo(org.ID, repo.ID) { return true, nil } } return false, nil }
-
-
-
@@ -5,6 +5,8 @@package repository import ( "bufio" "bytes" "context" "fmt" "os"
-
@@ -20,6 +22,7 @@ import ("code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/util" "github.com/gobwas/glob" "github.com/huandu/xstrings" )
-
@@ -78,7 +81,38 @@ func generateExpansion(src string, templateRepo, generateRepo *repo_model.Reposi}) } func checkGiteaTemplate(tmpDir string) (*models.GiteaTemplate, error) { // GiteaTemplate holds information about a .gitea/template file type GiteaTemplate struct { Path string Content []byte globs []glob.Glob } // Globs parses the .gitea/template globs or returns them if they were already parsed func (gt GiteaTemplate) Globs() []glob.Glob { if gt.globs != nil { return gt.globs } gt.globs = make([]glob.Glob, 0) scanner := bufio.NewScanner(bytes.NewReader(gt.Content)) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line == "" || strings.HasPrefix(line, "#") { continue } g, err := glob.Compile(line, '/') if err != nil { log.Info("Invalid glob expression '%s' (skipped): %v", line, err) continue } gt.globs = append(gt.globs, g) } return gt.globs } func checkGiteaTemplate(tmpDir string) (*GiteaTemplate, error) { gtPath := filepath.Join(tmpDir, ".gitea", "template") if _, err := os.Stat(gtPath); os.IsNotExist(err) { return nil, nil
-
@@ -91,7 +125,7 @@ func checkGiteaTemplate(tmpDir string) (*models.GiteaTemplate, error) {return nil, err } gt := &models.GiteaTemplate{ gt := &GiteaTemplate{ Path: gtPath, Content: content, }
-
@@ -227,7 +261,7 @@ func generateGitContent(ctx context.Context, repo, templateRepo, generateRepo *rif err = gitRepo.SetDefaultBranch(repo.DefaultBranch); err != nil { return fmt.Errorf("setDefaultBranch: %v", err) } if err = models.UpdateRepositoryCtx(ctx, repo, false); err != nil { if err = UpdateRepository(ctx, repo, false); err != nil { return fmt.Errorf("updateRepository: %v", err) }
-
@@ -240,7 +274,7 @@ func GenerateGitContent(ctx context.Context, templateRepo, generateRepo *repo_moreturn err } if err := models.UpdateRepoSize(ctx, generateRepo); err != nil { if err := UpdateRepoSize(ctx, generateRepo); err != nil { return fmt.Errorf("failed to update size for repository: %v", err) }
-
@@ -250,8 +284,27 @@ func GenerateGitContent(ctx context.Context, templateRepo, generateRepo *repo_moreturn nil } // GenerateRepoOptions contains the template units to generate type GenerateRepoOptions struct { Name string DefaultBranch string Description string Private bool GitContent bool Topics bool GitHooks bool Webhooks bool Avatar bool IssueLabels bool } // IsValid checks whether at least one option is chosen for generation func (gro GenerateRepoOptions) IsValid() bool { return gro.GitContent || gro.Topics || gro.GitHooks || gro.Webhooks || gro.Avatar || gro.IssueLabels // or other items as they are added } // GenerateRepository generates a repository from a template func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts models.GenerateRepoOptions) (_ *repo_model.Repository, err error) { func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts GenerateRepoOptions) (_ *repo_model.Repository, err error) { generateRepo := &repo_model.Repository{ OwnerID: owner.ID, Owner: owner,
-
@@ -288,7 +341,7 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templreturn generateRepo, err } if err = models.CheckDaemonExportOK(ctx, generateRepo); err != nil { if err = CheckDaemonExportOK(ctx, generateRepo); err != nil { return generateRepo, fmt.Errorf("checkDaemonExportOK: %v", err) }
-
-
-
@@ -2,7 +2,7 @@// Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package models package repository import ( "testing"
-
-
-
@@ -444,7 +444,7 @@ func initRepository(ctx context.Context, repoPath string, u *user_model.User, re} } if err = models.UpdateRepositoryCtx(ctx, repo, false); err != nil { if err = UpdateRepository(ctx, repo, false); err != nil { return fmt.Errorf("updateRepository: %v", err) }
-
-
-
@@ -116,7 +116,7 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,repo.Owner = u } if err = models.CheckDaemonExportOK(ctx, repo); err != nil { if err = CheckDaemonExportOK(ctx, repo); err != nil { return repo, fmt.Errorf("checkDaemonExportOK: %v", err) }
-
@@ -168,9 +168,11 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,} } if err = models.UpdateRepoSize(ctx, repo); err != nil { log.Error("Failed to update size for repository: %v", err) ctx, committer, err := db.TxContext() if err != nil { return nil, err } defer committer.Close() if opts.Mirror { mirrorModel := repo_model.Mirror{
-
@@ -203,17 +205,24 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,} } if err = repo_model.InsertMirror(&mirrorModel); err != nil { if err = repo_model.InsertMirror(ctx, &mirrorModel); err != nil { return repo, fmt.Errorf("InsertOne: %v", err) } repo.IsMirror = true err = models.UpdateRepository(repo, false) if err = UpdateRepository(ctx, repo, false); err != nil { return nil, err } } else { repo, err = CleanUpMigrateInfo(ctx, repo) if err = UpdateRepoSize(ctx, repo); err != nil { log.Error("Failed to update size for repository: %v", err) } if repo, err = CleanUpMigrateInfo(ctx, repo); err != nil { return nil, err } } return repo, err return repo, committer.Commit() } // cleanUpMigrateGitConfig removes mirror info which prevents "push --all".
-
@@ -253,7 +262,7 @@ func CleanUpMigrateInfo(ctx context.Context, repo *repo_model.Repository) (*repo} } return repo, models.UpdateRepository(repo, false) return repo, UpdateRepository(ctx, repo, false) } // SyncReleasesWithTags synchronizes release table with repository tags
-
-
-
@@ -312,7 +312,7 @@ func GetReviewers(ctx *context.APIContext) {// "200": // "$ref": "#/responses/UserList" reviewers, err := models.GetReviewers(ctx.Repo.Repository, ctx.Doer.ID, 0) reviewers, err := repo_model.GetReviewers(ctx, ctx.Repo.Repository, ctx.Doer.ID, 0) if err != nil { ctx.Error(http.StatusInternalServerError, "ListCollaborators", err) return
-
@@ -342,7 +342,7 @@ func GetAssignees(ctx *context.APIContext) {// "200": // "$ref": "#/responses/UserList" assignees, err := models.GetRepoAssignees(ctx.Repo.Repository) assignees, err := repo_model.GetRepoAssignees(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "ListCollaborators", err) return
-
-
-
@@ -17,6 +17,7 @@ import (issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context"
-
@@ -130,7 +131,7 @@ func SearchIssues(ctx *context.APIContext) {} // find repos user can access (for issue search) opts := &models.SearchRepoOptions{ opts := &repo_model.SearchRepoOptions{ Private: false, AllPublic: true, TopicOnly: false,
-
@@ -176,8 +177,8 @@ func SearchIssues(ctx *context.APIContext) {opts.TeamID = team.ID } repoCond := models.SearchRepositoryCondition(opts) repoIDs, _, err := models.SearchRepositoryIDs(opts) repoCond := repo_model.SearchRepositoryCondition(opts) repoIDs, _, err := repo_model.SearchRepositoryIDs(opts) if err != nil { ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err) return
-
-
-
@@ -123,7 +123,7 @@ func Search(ctx *context.APIContext) {// "422": // "$ref": "#/responses/validationError" opts := &models.SearchRepoOptions{ opts := &repo_model.SearchRepoOptions{ ListOptions: utils.GetListOptions(ctx), Actor: ctx.Doer, Keyword: ctx.FormTrim("q"),
-
@@ -192,7 +192,7 @@ func Search(ctx *context.APIContext) {} var err error repos, count, err := models.SearchRepository(opts) repos, count, err := repo_model.SearchRepository(opts) if err != nil { ctx.JSON(http.StatusInternalServerError, api.SearchError{ OK: false,
-
@@ -344,7 +344,7 @@ func Generate(ctx *context.APIContext) {return } opts := models.GenerateRepoOptions{ opts := repo_module.GenerateRepoOptions{ Name: form.Name, DefaultBranch: form.DefaultBranch, Description: form.Description,
-
@@ -717,7 +717,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) errrepo.DefaultBranch = *opts.DefaultBranch } if err := models.UpdateRepository(repo, visibilityChanged); err != nil { if err := repo_service.UpdateRepository(repo, visibilityChanged); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateRepository", err) return err }
-
@@ -1036,7 +1036,7 @@ func Delete(ctx *context.APIContext) {owner := ctx.Repo.Owner repo := ctx.Repo.Repository canDelete, err := models.CanUserDelete(repo, ctx.Doer) canDelete, err := repo_module.CanUserDelete(repo, ctx.Doer) if err != nil { ctx.Error(http.StatusInternalServerError, "CanUserDelete", err) return
-
-
-
@@ -7,9 +7,9 @@ package userimport ( "net/http" "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert"
-
@@ -21,7 +21,7 @@ import (func listUserRepos(ctx *context.APIContext, u *user_model.User, private bool) { opts := utils.GetListOptions(ctx) repos, count, err := models.GetUserRepositories(&models.SearchRepoOptions{ repos, count, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{ Actor: u, Private: private, ListOptions: opts,
-
@@ -103,7 +103,7 @@ func ListMyRepos(ctx *context.APIContext) {// "200": // "$ref": "#/responses/RepositoryList" opts := &models.SearchRepoOptions{ opts := &repo_model.SearchRepoOptions{ ListOptions: utils.GetListOptions(ctx), Actor: ctx.Doer, OwnerID: ctx.Doer.ID,
-
@@ -112,7 +112,7 @@ func ListMyRepos(ctx *context.APIContext) {} var err error repos, count, err := models.SearchRepository(opts) repos, count, err := repo_model.SearchRepository(opts) if err != nil { ctx.Error(http.StatusInternalServerError, "SearchRepository", err) return
-
-
-
@@ -55,7 +55,7 @@ func Code(ctx *context.Context) {// guest user or non-admin user if ctx.Doer == nil || !isAdmin { repoIDs, err = models.FindUserAccessibleRepoIDs(ctx.Doer) repoIDs, err = repo_model.FindUserAccessibleRepoIDs(ctx.Doer) if err != nil { ctx.ServerError("SearchResults", err) return
-
@@ -79,7 +79,7 @@ func Code(ctx *context.Context) {rightRepoMap := make(map[int64]*repo_model.Repository, len(repoMaps)) repoIDs = make([]int64, 0, len(repoMaps)) for id, repo := range repoMaps { if models.CheckRepoUnitUser(repo, ctx.Doer, unit.TypeCode) { if models.CheckRepoUnitUser(ctx, repo, ctx.Doer, unit.TypeCode) { rightRepoMap[id] = repo repoIDs = append(repoIDs, id) }
-
-
-
@@ -7,7 +7,6 @@ package exploreimport ( "net/http" "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/base"
-
@@ -81,7 +80,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {language := ctx.FormTrim("language") ctx.Data["Language"] = language repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: page, PageSize: opts.PageSize,
-
-
-
@@ -8,7 +8,6 @@ import ("net/http" "strings" "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo"
-
@@ -105,7 +104,7 @@ func Home(ctx *context.Context) {count int64 err error ) repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page,
-
-
-
@@ -24,6 +24,7 @@ import (user_setting "code.gitea.io/gitea/routers/web/user/setting" "code.gitea.io/gitea/services/forms" "code.gitea.io/gitea/services/org" repo_service "code.gitea.io/gitea/services/repository" user_service "code.gitea.io/gitea/services/user" )
-
@@ -117,7 +118,7 @@ func SettingsPost(ctx *context.Context) {// update forks visibility if visibilityChanged { repos, _, err := models.GetUserRepositories(&models.SearchRepoOptions{ repos, _, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{ Actor: org.AsUser(), Private: true, ListOptions: db.ListOptions{Page: 1, PageSize: org.NumRepos}, }) if err != nil {
-
@@ -126,7 +127,7 @@ func SettingsPost(ctx *context.Context) {} for _, repo := range repos { repo.OwnerName = org.Name if err := models.UpdateRepository(repo, true); err != nil { if err := repo_service.UpdateRepository(repo, true); err != nil { ctx.ServerError("UpdateRepository", err) return }
-
-
-
@@ -8,7 +8,6 @@ import ("fmt" "net/http" "code.gitea.io/gitea/models" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/context"
-
@@ -19,6 +18,7 @@ import ("code.gitea.io/gitea/modules/upload" "code.gitea.io/gitea/routers/common" "code.gitea.io/gitea/services/attachment" repo_service "code.gitea.io/gitea/services/repository" ) // UploadIssueAttachment response for Issue/PR attachments
-
@@ -95,7 +95,7 @@ func GetAttachment(ctx *context.Context) {return } repository, unitType, err := models.LinkedRepository(attach) repository, unitType, err := repo_service.LinkedRepository(attach) if err != nil { ctx.ServerError("LinkedRepository", err) return
-
-
-
@@ -457,7 +457,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {if rootRepo != nil && rootRepo.ID != ci.HeadRepo.ID && rootRepo.ID != baseRepo.ID { canRead := models.CheckRepoUnitUser(rootRepo, ctx.Doer, unit.TypeCode) canRead := models.CheckRepoUnitUser(ctx, rootRepo, ctx.Doer, unit.TypeCode) if canRead { ctx.Data["RootRepo"] = rootRepo if !fileOnly {
-
@@ -482,7 +482,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {ownForkRepo.ID != ci.HeadRepo.ID && ownForkRepo.ID != baseRepo.ID && (rootRepo == nil || ownForkRepo.ID != rootRepo.ID) { canRead := models.CheckRepoUnitUser(ownForkRepo, ctx.Doer, unit.TypeCode) canRead := models.CheckRepoUnitUser(ctx, ownForkRepo, ctx.Doer, unit.TypeCode) if canRead { ctx.Data["OwnForkRepo"] = ownForkRepo if !fileOnly {
-
-
-
@@ -49,6 +49,7 @@ import ("code.gitea.io/gitea/services/forms" issue_service "code.gitea.io/gitea/services/issue" pull_service "code.gitea.io/gitea/services/pull" repo_service "code.gitea.io/gitea/services/repository" ) const (
-
@@ -283,7 +284,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption utictx.Data["CommitStatuses"] = commitStatuses // Get assignees. ctx.Data["Assignees"], err = models.GetRepoAssignees(repo) ctx.Data["Assignees"], err = repo_model.GetRepoAssignees(ctx, repo) if err != nil { ctx.ServerError("GetAssignees", err) return
-
@@ -441,7 +442,7 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *repo_model.Rreturn } ctx.Data["Assignees"], err = models.GetRepoAssignees(repo) ctx.Data["Assignees"], err = repo_model.GetRepoAssignees(ctx, repo) if err != nil { ctx.ServerError("GetAssignees", err) return
-
@@ -522,13 +523,13 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, isposterID = 0 } reviewers, err = models.GetReviewers(repo, ctx.Doer.ID, posterID) reviewers, err = repo_model.GetReviewers(ctx, repo, ctx.Doer.ID, posterID) if err != nil { ctx.ServerError("GetReviewers", err) return } teamReviewers, err = models.GetReviewerTeams(repo) teamReviewers, err = repo_service.GetReviewerTeams(repo) if err != nil { ctx.ServerError("GetReviewerTeams", err) return
-
@@ -2160,7 +2161,7 @@ func SearchIssues(ctx *context.Context) {} // find repos user can access (for issue search) opts := &models.SearchRepoOptions{ opts := &repo_model.SearchRepoOptions{ Private: false, AllPublic: true, TopicOnly: false,
-
@@ -2206,8 +2207,8 @@ func SearchIssues(ctx *context.Context) {opts.TeamID = team.ID } repoCond := models.SearchRepositoryCondition(opts) repoIDs, _, err := models.SearchRepositoryIDs(opts) repoCond := repo_model.SearchRepositoryCondition(opts) repoIDs, _, err := repo_model.SearchRepositoryIDs(opts) if err != nil { ctx.Error(http.StatusInternalServerError, "SearchRepositoryByName", err.Error()) return
-
-
-
@@ -758,7 +758,7 @@ func ViewPullFiles(ctx *context.Context) {setCompareContext(ctx, baseCommit, commit, ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) ctx.Data["RequireTribute"] = true if ctx.Data["Assignees"], err = models.GetRepoAssignees(ctx.Repo.Repository); err != nil { if ctx.Data["Assignees"], err = repo_model.GetRepoAssignees(ctx, ctx.Repo.Repository); err != nil { ctx.ServerError("GetAssignees", err) return }
-
-
-
@@ -152,7 +152,7 @@ func Create(ctx *context.Context) {templateID := ctx.FormInt64("template_id") if templateID > 0 { templateRepo, err := repo_model.GetRepositoryByID(templateID) if err == nil && models.CheckRepoUnitUser(templateRepo, ctxUser, unit.TypeCode) { if err == nil && models.CheckRepoUnitUser(ctx, templateRepo, ctxUser, unit.TypeCode) { ctx.Data["repo_template"] = templateID ctx.Data["repo_template_name"] = templateRepo.Name }
-
@@ -223,7 +223,7 @@ func CreatePost(ctx *context.Context) {var repo *repo_model.Repository var err error if form.RepoTemplate > 0 { opts := models.GenerateRepoOptions{ opts := repo_module.GenerateRepoOptions{ Name: form.RepoName, Description: form.Description, Private: form.Private,
-
@@ -304,7 +304,7 @@ func Action(ctx *context.Context) {ctx.Repo.Repository.Description = ctx.FormString("desc") ctx.Repo.Repository.Website = ctx.FormString("site") err = models.UpdateRepository(ctx.Repo.Repository, false) err = repo_service.UpdateRepository(ctx.Repo.Repository, false) } if err != nil {
-
@@ -509,7 +509,7 @@ func InitiateDownload(ctx *context.Context) {// SearchRepo repositories via options func SearchRepo(ctx *context.Context) { opts := &models.SearchRepoOptions{ opts := &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ Page: ctx.FormInt("page"), PageSize: convert.ToCorrectPageSize(ctx.FormInt("limit")),
-
@@ -581,7 +581,7 @@ func SearchRepo(ctx *context.Context) {} var err error repos, count, err := models.SearchRepository(opts) repos, count, err := repo_model.SearchRepository(opts) if err != nil { ctx.JSON(http.StatusInternalServerError, api.SearchError{ OK: false,
-
-
-
@@ -168,7 +168,7 @@ func SettingsPost(ctx *context.Context) {} repo.IsPrivate = form.Private if err := models.UpdateRepository(repo, visibilityChanged); err != nil { if err := repo_service.UpdateRepository(repo, visibilityChanged); err != nil { ctx.ServerError("UpdateRepository", err) return }
-
@@ -491,7 +491,7 @@ func SettingsPost(ctx *context.Context) {return } if repoChanged { if err := models.UpdateRepository(repo, false); err != nil { if err := repo_service.UpdateRepository(repo, false); err != nil { ctx.ServerError("UpdateRepository", err) return }
-
@@ -510,7 +510,7 @@ func SettingsPost(ctx *context.Context) {} if changed { if err := models.UpdateRepository(repo, false); err != nil { if err := repo_service.UpdateRepository(repo, false); err != nil { ctx.ServerError("UpdateRepository", err) return }
-
@@ -530,7 +530,7 @@ func SettingsPost(ctx *context.Context) {repo.IsFsckEnabled = form.EnableHealthCheck } if err := models.UpdateRepository(repo, false); err != nil { if err := repo_service.UpdateRepository(repo, false); err != nil { ctx.ServerError("UpdateRepository", err) return }
-
-
-
@@ -34,6 +34,7 @@ import ("code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/typesniffer"
-
@@ -905,7 +906,7 @@ func renderCode(ctx *context.Context) {ctx.ServerError("UpdateRepositoryCols", err) return } if err = models.UpdateRepoSize(ctx, ctx.Repo.Repository); err != nil { if err = repo_module.UpdateRepoSize(ctx, ctx.Repo.Repository); err != nil { ctx.ServerError("UpdateRepoSize", err) return }
-
-
-
@@ -166,7 +166,7 @@ func Milestones(ctx *context.Context) {return } repoOpts := models.SearchRepoOptions{ repoOpts := repo_model.SearchRepoOptions{ Actor: ctxUser, OwnerID: ctxUser.ID, Private: true,
-
@@ -181,7 +181,7 @@ func Milestones(ctx *context.Context) {} var ( userRepoCond = models.SearchRepositoryCondition(&repoOpts) // all repo condition user could visit userRepoCond = repo_model.SearchRepositoryCondition(&repoOpts) // all repo condition user could visit repoCond = userRepoCond repoIDs []int64
-
@@ -234,7 +234,7 @@ func Milestones(ctx *context.Context) {return } showRepos, _, err := models.SearchRepositoryByCondition(&repoOpts, userRepoCond, false) showRepos, _, err := repo_model.SearchRepositoryByCondition(&repoOpts, userRepoCond, false) if err != nil { ctx.ServerError("SearchRepositoryByCondition", err) return
-
@@ -437,7 +437,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {// As team: // - Team org's owns the repository. // - Team has read permission to repository. repoOpts := &models.SearchRepoOptions{ repoOpts := &repo_model.SearchRepoOptions{ Actor: ctx.Doer, OwnerID: ctx.Doer.ID, Private: true,
-
@@ -559,7 +559,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {} // a RepositoryList showRepos := models.RepositoryListOfMap(showReposMap) showRepos := repo_model.RepositoryListOfMap(showReposMap) sort.Sort(showRepos) // maps pull request IDs to their CommitStatus. Will be posted to ctx.Data.
-
-
-
@@ -8,7 +8,7 @@ import ("net/http" "testing" "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/test"
-
@@ -26,7 +26,7 @@ func TestArchivedIssues(t *testing.T) {ctx.Req.Form.Set("state", "open") // Assume: User 30 has access to two Repos with Issues, one of the Repos being archived. repos, _, _ := models.GetUserRepositories(&models.SearchRepoOptions{Actor: ctx.Doer}) repos, _, _ := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{Actor: ctx.Doer}) assert.Len(t, repos, 2) IsArchived := make(map[int64]bool) NumIssues := make(map[int64]int)
-
-
-
@@ -7,7 +7,6 @@ package userimport ( "net/http" "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" packages_model "code.gitea.io/gitea/models/packages" container_model "code.gitea.io/gitea/models/packages/container"
-
@@ -288,7 +287,7 @@ func PackageSettings(ctx *context.Context) {ctx.Data["ContextUser"] = ctx.ContextUser ctx.Data["PackageDescriptor"] = pd repos, _, _ := models.GetUserRepositories(&models.SearchRepoOptions{ repos, _, _ := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{ Actor: pd.Owner, Private: true, })
-
-
-
@@ -195,7 +195,7 @@ func Profile(ctx *context.Context) {} case "stars": ctx.Data["PageIsProfileStarList"] = true repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page,
-
@@ -227,7 +227,7 @@ func Profile(ctx *context.Context) {return } case "watching": repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page,
-
@@ -249,7 +249,7 @@ func Profile(ctx *context.Context) {total = int(count) default: repos, count, err = models.SearchRepository(&models.SearchRepoOptions{ repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page,
-
-
-
@@ -15,7 +15,6 @@ import ("path/filepath" "strings" "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo"
-
@@ -304,7 +303,7 @@ func Repos(ctx *context.Context) {return } userRepos, _, err := models.GetUserRepositories(&models.SearchRepoOptions{ userRepos, _, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{ Actor: ctxUser, Private: true, ListOptions: db.ListOptions{
-
@@ -329,7 +328,7 @@ func Repos(ctx *context.Context) {ctx.Data["Dirs"] = repoNames ctx.Data["ReposMap"] = repos } else { repos, count64, err := models.GetUserRepositories(&models.SearchRepoOptions{Actor: ctxUser, Private: true, ListOptions: opts}) repos, count64, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{Actor: ctxUser, Private: true, ListOptions: opts}) if err != nil { ctx.ServerError("GetUserRepositories", err) return
-
-
-
@@ -1220,7 +1220,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufiooid := strings.TrimPrefix(line[1:], lfs.MetaFileOidPrefix) if len(oid) == 64 { m := &models.LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}} count, err := db.Count(m) count, err := db.CountByBean(db.DefaultContext, m) if err == nil && count > 0 { curFile.IsBin = true
-
-
-
@@ -145,7 +145,7 @@ func mailIssueCommentBatch(ctx *mailCommentContext, users []*user_model.User, vivisited[user.ID] = true // test if this user is allowed to see the issue/pull if !models.CheckRepoUnitUser(ctx.Issue.Repo, user, checkUnit) { if !models.CheckRepoUnitUser(ctx, ctx.Issue.Repo, user, checkUnit) { continue }
-
-
-
@@ -10,7 +10,6 @@ import ("strings" "time" "code.gitea.io/gitea/models" admin_model "code.gitea.io/gitea/models/admin" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo"
-
@@ -301,7 +300,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bogitRepo.Close() log.Trace("SyncMirrors [repo: %-v]: updating size of repository", m.Repo) if err := models.UpdateRepoSize(ctx, m.Repo); err != nil { if err := repo_module.UpdateRepoSize(ctx, m.Repo); err != nil { log.Error("SyncMirrors [repo: %-v]: failed to update size for mirror repository: %v", m.Repo, err) }
-
-
-
@@ -73,7 +73,7 @@ func AdoptRepository(doer, u *user_model.User, opts models.CreateRepoOptions) (*if err := adoptRepository(ctx, repoPath, doer, repo, opts); err != nil { return fmt.Errorf("createDelegateHooks: %v", err) } if err := models.CheckDaemonExportOK(ctx, repo); err != nil { if err := repo_module.CheckDaemonExportOK(ctx, repo); err != nil { return fmt.Errorf("checkDaemonExportOK: %v", err) }
-
@@ -182,7 +182,7 @@ func adoptRepository(ctx context.Context, repoPath string, u *user_model.User, r} } if err = models.UpdateRepositoryCtx(ctx, repo, false); err != nil { if err = repo_module.UpdateRepository(ctx, repo, false); err != nil { return fmt.Errorf("updateRepository: %v", err) }
-
@@ -246,7 +246,7 @@ func checkUnadoptedRepositories(userName string, repoNamesToCheck []string, unad} return err } repos, _, err := models.GetUserRepositories(&models.SearchRepoOptions{ repos, _, err := repo_model.GetUserRepositories(&repo_model.SearchRepoOptions{ Actor: ctxUser, Private: true, ListOptions: db.ListOptions{
-
-
-
@@ -17,6 +17,7 @@ import (user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/util" "xorm.io/builder"
-
@@ -89,7 +90,7 @@ func GitGcRepos(ctx context.Context, timeout time.Duration, args ...string) erro} // Now update the size of the repository if err := models.UpdateRepoSize(ctx, repo); err != nil { if err := repo_module.UpdateRepoSize(ctx, repo); err != nil { log.Error("Updating size as part of garbage collection failed for %v. Stdout: %s\nError: %v", repo, stdout, err) desc := fmt.Sprintf("Updating size as part of garbage collection failed for %s. Stdout: %s\nError: %v", repo.RepoPath(), stdout, err) if err = admin_model.CreateRepositoryNotice(desc); err != nil {
-
-
-
@@ -96,7 +96,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Forkreturn err } if err = models.IncrementRepoForkNum(txCtx, opts.BaseRepo.ID); err != nil { if err = repo_model.IncrementRepoForkNum(txCtx, opts.BaseRepo.ID); err != nil { return err }
-
@@ -116,7 +116,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Forkreturn fmt.Errorf("git clone: %v", err) } if err := models.CheckDaemonExportOK(txCtx, repo); err != nil { if err := repo_module.CheckDaemonExportOK(txCtx, repo); err != nil { return fmt.Errorf("checkDaemonExportOK: %v", err) }
-
@@ -139,7 +139,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork} // even if below operations failed, it could be ignored. And they will be retried if err := models.UpdateRepoSize(ctx, repo); err != nil { if err := repo_module.UpdateRepoSize(ctx, repo); err != nil { log.Error("Failed to update size for repository: %v", err) } if err := repo_model.CopyLanguageStat(opts.BaseRepo, repo); err != nil {
-
@@ -173,7 +173,7 @@ func ConvertForkToNormalRepository(repo *repo_model.Repository) error {return nil } if err := models.DecrementRepoForkNum(ctx, repo.ForkID); err != nil { if err := repo_model.DecrementRepoForkNum(ctx, repo.ForkID); err != nil { log.Error("Unable to decrement repo fork num for old root repo %d of repository %-v whilst converting from fork. Error: %v", repo.ForkID, repo, err) return err }
-
@@ -181,7 +181,7 @@ func ConvertForkToNormalRepository(repo *repo_model.Repository) error {repo.IsFork = false repo.ForkID = 0 if err := models.UpdateRepositoryCtx(ctx, repo, false); err != nil { if err := repo_module.UpdateRepository(ctx, repo, false); err != nil { log.Error("Unable to update repository %-v whilst converting from fork. Error: %v", repo, err) return err }
-
-
-
@@ -10,6 +10,7 @@ import ("code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository"
-
@@ -84,3 +85,29 @@ func GenerateGitHooks(ctx context.Context, templateRepo, generateRepo *repo_mode} return nil } // GenerateWebhooks generates webhooks from a template repository func GenerateWebhooks(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error { templateWebhooks, err := webhook.ListWebhooksByOpts(ctx, &webhook.ListWebhookOptions{RepoID: templateRepo.ID}) if err != nil { return err } ws := make([]*webhook.Webhook, 0, len(templateWebhooks)) for _, templateWebhook := range templateWebhooks { ws = append(ws, &webhook.Webhook{ RepoID: generateRepo.ID, URL: templateWebhook.URL, HTTPMethod: templateWebhook.HTTPMethod, ContentType: templateWebhook.ContentType, Secret: templateWebhook.Secret, HookEvent: templateWebhook.HookEvent, IsActive: templateWebhook.IsActive, Type: templateWebhook.Type, OrgID: templateWebhook.OrgID, Events: templateWebhook.Events, Meta: templateWebhook.Meta, }) } return webhook.CreateWebhooks(ctx, ws) }
-
-
-
@@ -95,7 +95,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {} defer gitRepo.Close() if err = models.UpdateRepoSize(ctx, repo); err != nil { if err = repo_module.UpdateRepoSize(ctx, repo); err != nil { log.Error("Failed to update size for repository: %v", err) }
-
-
-
@@ -14,6 +14,7 @@ import ("code.gitea.io/gitea/models/organization" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification"
-
@@ -85,3 +86,42 @@ func Init() error {admin_model.RemoveAllWithNotice(db.DefaultContext, "Clean up temporary repositories", repo_module.LocalCopyPath()) return initPushQueue() } // UpdateRepository updates a repository func UpdateRepository(repo *repo_model.Repository, visibilityChanged bool) (err error) { ctx, committer, err := db.TxContext() if err != nil { return err } defer committer.Close() if err = repo_module.UpdateRepository(ctx, repo, visibilityChanged); err != nil { return fmt.Errorf("updateRepository: %v", err) } return committer.Commit() } // LinkedRepository returns the linked repo if any func LinkedRepository(a *repo_model.Attachment) (*repo_model.Repository, unit.Type, error) { if a.IssueID != 0 { iss, err := models.GetIssueByID(a.IssueID) if err != nil { return nil, unit.TypeIssues, err } repo, err := repo_model.GetRepositoryByID(iss.RepoID) unitType := unit.TypeIssues if iss.IsPull { unitType = unit.TypePullRequests } return repo, unitType, err } else if a.ReleaseID != 0 { rel, err := models.GetReleaseByID(db.DefaultContext, a.ReleaseID) if err != nil { return nil, unit.TypeReleases, err } repo, err := repo_model.GetRepositoryByID(rel.RepoID) return repo, unit.TypeReleases, err } return nil, -1, nil }
-
-
-
@@ -0,0 +1,43 @@// Copyright 2022 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 repository import ( "testing" "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert" ) func TestLinkedRepository(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testCases := []struct { name string attachID int64 expectedRepo *repo_model.Repository expectedUnitType unit.Type }{ {"LinkedIssue", 1, &repo_model.Repository{ID: 1}, unit.TypeIssues}, {"LinkedComment", 3, &repo_model.Repository{ID: 1}, unit.TypePullRequests}, {"LinkedRelease", 9, &repo_model.Repository{ID: 1}, unit.TypeReleases}, {"Notlinked", 10, nil, -1}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { attach, err := repo_model.GetAttachmentByID(db.DefaultContext, tc.attachID) assert.NoError(t, err) repo, unitType, err := LinkedRepository(attach) assert.NoError(t, err) if tc.expectedRepo != nil { assert.Equal(t, tc.expectedRepo.ID, repo.ID) } assert.Equal(t, tc.expectedUnitType, unitType) }) } }
-
-
-
@@ -0,0 +1,24 @@// Copyright 2022 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 repository import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" repo_model "code.gitea.io/gitea/models/repo" ) // GetReviewerTeams get all teams can be requested to review func GetReviewerTeams(repo *repo_model.Repository) ([]*organization.Team, error) { if err := repo.GetOwner(db.DefaultContext); err != nil { return nil, err } if !repo.Owner.IsOrganization() { return nil, nil } return organization.GetTeamsWithAccessToRepo(db.DefaultContext, repo.OwnerID, repo.ID, perm.AccessModeRead) }
-
-
-
@@ -0,0 +1,28 @@// Copyright 2022 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 repository import ( "testing" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" "github.com/stretchr/testify/assert" ) func TestRepoGetReviewerTeams(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}).(*repo_model.Repository) teams, err := GetReviewerTeams(repo2) assert.NoError(t, err) assert.Empty(t, teams) repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}).(*repo_model.Repository) teams, err = GetReviewerTeams(repo3) assert.NoError(t, err) assert.Len(t, teams, 2) }
-
-
-
@@ -16,8 +16,27 @@ import (repo_module "code.gitea.io/gitea/modules/repository" ) // GenerateIssueLabels generates issue labels from a template repository func GenerateIssueLabels(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error { templateLabels, err := models.GetLabelsByRepoID(ctx, templateRepo.ID, "", db.ListOptions{}) if err != nil { return err } newLabels := make([]*models.Label, 0, len(templateLabels)) for _, templateLabel := range templateLabels { newLabels = append(newLabels, &models.Label{ RepoID: generateRepo.ID, Name: templateLabel.Name, Description: templateLabel.Description, Color: templateLabel.Color, }) } return db.Insert(ctx, newLabels) } // GenerateRepository generates a repository from a template func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.Repository, opts models.GenerateRepoOptions) (_ *repo_model.Repository, err error) { func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.Repository, opts repo_module.GenerateRepoOptions) (_ *repo_model.Repository, err error) { if !doer.IsAdmin && !owner.CanCreateRepo() { return nil, repo_model.ErrReachLimitOfRepo{ Limit: owner.MaxRepoCreation,
-
@@ -54,7 +73,7 @@ func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.R// Webhooks if opts.Webhooks { if err = models.GenerateWebhooks(ctx, templateRepo, generateRepo); err != nil { if err = GenerateWebhooks(ctx, templateRepo, generateRepo); err != nil { return err } }
-
@@ -68,7 +87,7 @@ func GenerateRepository(doer, owner *user_model.User, templateRepo *repo_model.R// Issue Labels if opts.IssueLabels { if err = models.GenerateIssueLabels(ctx, templateRepo, generateRepo); err != nil { if err = GenerateIssueLabels(ctx, templateRepo, generateRepo); err != nil { return err } }
-