Skip to content

Some repository refactors #17950

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/migrate_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func migrateAvatars(dstStorage storage.ObjectStorage) error {
}

func migrateRepoAvatars(dstStorage storage.ObjectStorage) error {
return models.IterateRepository(func(repo *repo_model.Repository) error {
return repo_model.IterateRepository(func(repo *repo_model.Repository) error {
_, err := storage.Copy(dstStorage, repo.CustomAvatarRelativePath(), storage.RepoAvatars, repo.CustomAvatarRelativePath())
return err
})
Expand Down
2 changes: 1 addition & 1 deletion integrations/delete_user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func assertUserDeleted(t *testing.T, userID int64) {
unittest.AssertNotExistsBean(t, &models.OrgUser{UID: userID})
unittest.AssertNotExistsBean(t, &models.IssueUser{UID: userID})
unittest.AssertNotExistsBean(t, &models.TeamUser{UID: userID})
unittest.AssertNotExistsBean(t, &models.Star{UID: userID})
unittest.AssertNotExistsBean(t, &repo_model.Star{UID: userID})
}

func TestUserDeleteAccount(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion integrations/pull_update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func createOutdatedPR(t *testing.T, actor, forkOrg *user_model.User) *models.Pul
assert.NoError(t, err)
assert.NotEmpty(t, baseRepo)

headRepo, err := repo_service.ForkRepository(actor, forkOrg, models.ForkRepoOptions{
headRepo, err := repo_service.ForkRepository(actor, forkOrg, repo_service.ForkRepoOptions{
BaseRepo: baseRepo,
Name: "repo-pr-update",
Description: "desc",
Expand Down
6 changes: 3 additions & 3 deletions integrations/repo_watch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"net/url"
"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"
)
Expand All @@ -18,8 +18,8 @@ func TestRepoWatch(t *testing.T) {
// Test round-trip auto-watch
setting.Service.AutoWatchOnChanges = true
session := loginUser(t, "user2")
unittest.AssertNotExistsBean(t, &models.Watch{UserID: 2, RepoID: 3})
unittest.AssertNotExistsBean(t, &repo_model.Watch{UserID: 2, RepoID: 3})
testEditFile(t, session, "user3", "repo3", "master", "README.md", "Hello, World (Edited for watch)\n")
unittest.AssertExistsAndLoadBean(t, &models.Watch{UserID: 2, RepoID: 3, Mode: models.RepoWatchModeAuto})
unittest.AssertExistsAndLoadBean(t, &repo_model.Watch{UserID: 2, RepoID: 3, Mode: repo_model.WatchModeAuto})
})
}
125 changes: 125 additions & 0 deletions models/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

"code.gitea.io/gitea/models/db"
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/base"
"code.gitea.io/gitea/modules/git"
Expand Down Expand Up @@ -414,3 +415,127 @@ func DeleteOldActions(olderThan time.Duration) (err error) {
_, err = db.GetEngine(db.DefaultContext).Where("created_unix < ?", time.Now().Add(-olderThan).Unix()).Delete(&Action{})
return
}

func notifyWatchers(ctx context.Context, actions ...*Action) error {
var watchers []*repo_model.Watch
var repo *repo_model.Repository
var err error
var permCode []bool
var permIssue []bool
var permPR []bool

e := db.GetEngine(ctx)

for _, act := range actions {
repoChanged := repo == nil || repo.ID != act.RepoID

if repoChanged {
// Add feeds for user self and all watchers.
watchers, err = repo_model.GetWatchers(ctx, act.RepoID)
if err != nil {
return fmt.Errorf("get watchers: %v", err)
}
}

// Add feed for actioner.
act.UserID = act.ActUserID
if _, err = e.Insert(act); err != nil {
return fmt.Errorf("insert new actioner: %v", err)
}

if repoChanged {
act.loadRepo()
repo = act.Repo

// check repo owner exist.
if err := act.Repo.GetOwner(ctx); err != nil {
return fmt.Errorf("can't get repo owner: %v", err)
}
} else if act.Repo == nil {
act.Repo = repo
}

// Add feed for organization
if act.Repo.Owner.IsOrganization() && act.ActUserID != act.Repo.Owner.ID {
act.ID = 0
act.UserID = act.Repo.Owner.ID
if _, err = e.InsertOne(act); err != nil {
return fmt.Errorf("insert new actioner: %v", err)
}
}

if repoChanged {
permCode = make([]bool, len(watchers))
permIssue = make([]bool, len(watchers))
permPR = make([]bool, len(watchers))
for i, watcher := range watchers {
user, err := user_model.GetUserByIDEngine(e, watcher.UserID)
if err != nil {
permCode[i] = false
permIssue[i] = false
permPR[i] = false
continue
}
perm, err := getUserRepoPermission(ctx, repo, user)
if err != nil {
permCode[i] = false
permIssue[i] = false
permPR[i] = false
continue
}
permCode[i] = perm.CanRead(unit.TypeCode)
permIssue[i] = perm.CanRead(unit.TypeIssues)
permPR[i] = perm.CanRead(unit.TypePullRequests)
}
}

for i, watcher := range watchers {
if act.ActUserID == watcher.UserID {
continue
}
act.ID = 0
act.UserID = watcher.UserID
act.Repo.Units = nil

switch act.OpType {
case ActionCommitRepo, ActionPushTag, ActionDeleteTag, ActionPublishRelease, ActionDeleteBranch:
if !permCode[i] {
continue
}
case ActionCreateIssue, ActionCommentIssue, ActionCloseIssue, ActionReopenIssue:
if !permIssue[i] {
continue
}
case ActionCreatePullRequest, ActionCommentPull, ActionMergePullRequest, ActionClosePullRequest, ActionReopenPullRequest:
if !permPR[i] {
continue
}
}

if _, err = e.InsertOne(act); err != nil {
return fmt.Errorf("insert new action: %v", err)
}
}
}
return nil
}

// NotifyWatchers creates batch of actions for every watcher.
func NotifyWatchers(actions ...*Action) error {
return notifyWatchers(db.DefaultContext, actions...)
}

// NotifyWatchersActions creates batch of actions for every watcher.
func NotifyWatchersActions(acts []*Action) error {
ctx, committer, err := db.TxContext()
if err != nil {
return err
}
defer committer.Close()
for _, act := range acts {
if err := notifyWatchers(ctx, act); err != nil {
return err
}
}
return committer.Commit()
}
37 changes: 37 additions & 0 deletions models/action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,40 @@ func TestGetFeeds2(t *testing.T) {
assert.NoError(t, err)
assert.Len(t, actions, 0)
}

func TestNotifyWatchers(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

action := &Action{
ActUserID: 8,
RepoID: 1,
OpType: ActionStarRepo,
}
assert.NoError(t, NotifyWatchers(action))

// One watchers are inactive, thus action is only created for user 8, 1, 4, 11
unittest.AssertExistsAndLoadBean(t, &Action{
ActUserID: action.ActUserID,
UserID: 8,
RepoID: action.RepoID,
OpType: action.OpType,
})
unittest.AssertExistsAndLoadBean(t, &Action{
ActUserID: action.ActUserID,
UserID: 1,
RepoID: action.RepoID,
OpType: action.OpType,
})
unittest.AssertExistsAndLoadBean(t, &Action{
ActUserID: action.ActUserID,
UserID: 4,
RepoID: action.RepoID,
OpType: action.OpType,
})
unittest.AssertExistsAndLoadBean(t, &Action{
ActUserID: action.ActUserID,
UserID: 11,
RepoID: action.RepoID,
OpType: action.OpType,
})
}
63 changes: 0 additions & 63 deletions models/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,6 @@ func (err ErrUserNotAllowedCreateOrg) Error() string {
return "user is not allowed to create organizations"
}

// ErrReachLimitOfRepo represents a "ReachLimitOfRepo" kind of error.
type ErrReachLimitOfRepo struct {
Limit int
}

// IsErrReachLimitOfRepo checks if an error is a ErrReachLimitOfRepo.
func IsErrReachLimitOfRepo(err error) bool {
_, ok := err.(ErrReachLimitOfRepo)
return ok
}

func (err ErrReachLimitOfRepo) Error() string {
return fmt.Sprintf("user has reached maximum limit of repositories [limit: %d]", err.Limit)
}

// __ __.__ __ .__
// / \ / \__| | _|__|
// \ \/\/ / | |/ / |
Expand Down Expand Up @@ -322,38 +307,6 @@ func (err ErrRepoTransferInProgress) Error() string {
return fmt.Sprintf("repository is already being transferred [uname: %s, name: %s]", err.Uname, err.Name)
}

// ErrRepoAlreadyExist represents a "RepoAlreadyExist" kind of error.
type ErrRepoAlreadyExist struct {
Uname string
Name string
}

// IsErrRepoAlreadyExist checks if an error is a ErrRepoAlreadyExist.
func IsErrRepoAlreadyExist(err error) bool {
_, ok := err.(ErrRepoAlreadyExist)
return ok
}

func (err ErrRepoAlreadyExist) Error() string {
return fmt.Sprintf("repository already exists [uname: %s, name: %s]", err.Uname, err.Name)
}

// ErrRepoFilesAlreadyExist represents a "RepoFilesAlreadyExist" kind of error.
type ErrRepoFilesAlreadyExist struct {
Uname string
Name string
}

// IsErrRepoFilesAlreadyExist checks if an error is a ErrRepoAlreadyExist.
func IsErrRepoFilesAlreadyExist(err error) bool {
_, ok := err.(ErrRepoFilesAlreadyExist)
return ok
}

func (err ErrRepoFilesAlreadyExist) Error() string {
return fmt.Sprintf("repository files already exist [uname: %s, name: %s]", err.Uname, err.Name)
}

// ErrForkAlreadyExist represents a "ForkAlreadyExist" kind of error.
type ErrForkAlreadyExist struct {
Uname string
Expand All @@ -371,22 +324,6 @@ func (err ErrForkAlreadyExist) Error() string {
return fmt.Sprintf("repository is already forked by user [uname: %s, repo path: %s, fork path: %s]", err.Uname, err.RepoName, err.ForkName)
}

// ErrRepoRedirectNotExist represents a "RepoRedirectNotExist" kind of error.
type ErrRepoRedirectNotExist struct {
OwnerID int64
RepoName string
}

// IsErrRepoRedirectNotExist check if an error is an ErrRepoRedirectNotExist.
func IsErrRepoRedirectNotExist(err error) bool {
_, ok := err.(ErrRepoRedirectNotExist)
return ok
}

func (err ErrRepoRedirectNotExist) Error() string {
return fmt.Sprintf("repository redirect does not exist [uid: %d, name: %s]", err.OwnerID, err.RepoName)
}

// ErrInvalidCloneAddr represents a "InvalidCloneAddr" kind of error.
type ErrInvalidCloneAddr struct {
Host string
Expand Down
5 changes: 3 additions & 2 deletions models/issue_watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package models

import (
"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/timeutil"
)
Expand Down Expand Up @@ -80,11 +81,11 @@ func CheckIssueWatch(user *user_model.User, issue *Issue) (bool, error) {
if exist {
return iw.IsWatching, nil
}
w, err := getWatch(db.GetEngine(db.DefaultContext), user.ID, issue.RepoID)
w, err := repo_model.GetWatch(db.DefaultContext, user.ID, issue.RepoID)
if err != nil {
return false, err
}
return isWatchMode(w.Mode) || IsUserParticipantsOfIssue(user, issue), nil
return repo_model.IsWatchMode(w.Mode) || IsUserParticipantsOfIssue(user, issue), nil
}

// GetIssueWatchersIDs returns IDs of subscribers or explicit unsubscribers to a given issue id
Expand Down
2 changes: 1 addition & 1 deletion models/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ func createOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, n
toNotify[id] = struct{}{}
}
if !(issue.IsPull && HasWorkInProgressPrefix(issue.Title)) {
repoWatches, err := getRepoWatchersIDs(e, issue.RepoID)
repoWatches, err := repo_model.GetRepoWatchersIDs(ctx, issue.RepoID)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion models/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ func removeOrgUser(ctx context.Context, orgID, userID int64) error {
return fmt.Errorf("GetUserRepositories [%d]: %v", userID, err)
}
for _, repoID := range repoIDs {
if err = watchRepo(sess, userID, repoID, false); err != nil {
if err = repo_model.WatchRepoCtx(ctx, userID, repoID, false); err != nil {
return err
}
}
Expand Down
8 changes: 4 additions & 4 deletions models/org_team.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ func (t *Team) addRepository(ctx context.Context, repo *repo_model.Repository) (
return fmt.Errorf("getMembers: %v", err)
}
for _, u := range t.Members {
if err = watchRepo(e, u.ID, repo.ID, true); err != nil {
if err = repo_model.WatchRepoCtx(ctx, u.ID, repo.ID, true); err != nil {
return fmt.Errorf("watchRepo: %v", err)
}
}
Expand Down Expand Up @@ -341,7 +341,7 @@ func (t *Team) removeAllRepositories(ctx context.Context) (err error) {
continue
}

if err = watchRepo(e, user.ID, repo.ID, false); err != nil {
if err = repo_model.WatchRepoCtx(ctx, user.ID, repo.ID, false); err != nil {
return err
}

Expand Down Expand Up @@ -399,7 +399,7 @@ func (t *Team) removeRepository(ctx context.Context, repo *repo_model.Repository
continue
}

if err = watchRepo(e, teamUser.UID, repo.ID, false); err != nil {
if err = repo_model.WatchRepoCtx(ctx, teamUser.UID, repo.ID, false); err != nil {
return err
}

Expand Down Expand Up @@ -857,7 +857,7 @@ func AddTeamMember(team *Team, userID int64) error {
return err
}
if setting.Service.AutoWatchNewRepos {
if err = watchRepo(sess, userID, repo.ID, true); err != nil {
if err = repo_model.WatchRepoCtx(ctx, userID, repo.ID, true); err != nil {
return err
}
}
Expand Down
Loading