From 6d77d6204d8b09deb2b83783e44c65bd16f8e498 Mon Sep 17 00:00:00 2001 From: Joe Chen Date: Wed, 13 Mar 2024 22:03:02 -0400 Subject: [PATCH] all: unwrap `database.ActionsStore` interface (#7686) --- internal/database/access_tokens.go | 2 +- internal/database/actions.go | 142 ++++++++++-------------- internal/database/actions_test.go | 172 ++++++++++++++--------------- internal/database/database.go | 5 +- internal/database/mirror.go | 6 +- internal/database/pull.go | 2 +- internal/database/update.go | 8 +- internal/route/repo/setting.go | 2 +- internal/route/user/home.go | 4 +- 9 files changed, 163 insertions(+), 180 deletions(-) diff --git a/internal/database/access_tokens.go b/internal/database/access_tokens.go index b127a9a99..045596bc5 100644 --- a/internal/database/access_tokens.go +++ b/internal/database/access_tokens.go @@ -58,7 +58,7 @@ type AccessTokensStore struct { } func newAccessTokensStore(db *gorm.DB) *AccessTokensStore { - return &AccessTokensStore{db} + return &AccessTokensStore{db: db} } type ErrAccessTokenAlreadyExist struct { diff --git a/internal/database/actions.go b/internal/database/actions.go index a678fdd23..8dcaeba1f 100644 --- a/internal/database/actions.go +++ b/internal/database/actions.go @@ -28,61 +28,16 @@ import ( "gogs.io/gogs/internal/tool" ) -// ActionsStore is the persistent interface for actions. -type ActionsStore interface { - // CommitRepo creates actions for pushing commits to the repository. An action - // with the type ActionDeleteBranch is created if the push deletes a branch; an - // action with the type ActionCommitRepo is created for a regular push. If the - // regular push also creates a new branch, then another action with type - // ActionCreateBranch is created. - CommitRepo(ctx context.Context, opts CommitRepoOptions) error - // ListByOrganization returns actions of the organization viewable by the actor. - // Results are paginated if `afterID` is given. - ListByOrganization(ctx context.Context, orgID, actorID, afterID int64) ([]*Action, error) - // ListByUser returns actions of the user viewable by the actor. Results are - // paginated if `afterID` is given. The `isProfile` indicates whether repository - // permissions should be considered. - ListByUser(ctx context.Context, userID, actorID, afterID int64, isProfile bool) ([]*Action, error) - // MergePullRequest creates an action for merging a pull request. - MergePullRequest(ctx context.Context, doer, owner *User, repo *Repository, pull *Issue) error - // MirrorSyncCreate creates an action for mirror synchronization of a new - // reference. - MirrorSyncCreate(ctx context.Context, owner *User, repo *Repository, refName string) error - // MirrorSyncDelete creates an action for mirror synchronization of a reference - // deletion. - MirrorSyncDelete(ctx context.Context, owner *User, repo *Repository, refName string) error - // MirrorSyncPush creates an action for mirror synchronization of pushed - // commits. - MirrorSyncPush(ctx context.Context, opts MirrorSyncPushOptions) error - // NewRepo creates an action for creating a new repository. The action type - // could be ActionCreateRepo or ActionForkRepo based on whether the repository - // is a fork. - NewRepo(ctx context.Context, doer, owner *User, repo *Repository) error - // PushTag creates an action for pushing tags to the repository. An action with - // the type ActionDeleteTag is created if the push deletes a tag. Otherwise, an - // action with the type ActionPushTag is created for a regular push. - PushTag(ctx context.Context, opts PushTagOptions) error - // RenameRepo creates an action for renaming a repository. - RenameRepo(ctx context.Context, doer, owner *User, oldRepoName string, repo *Repository) error - // TransferRepo creates an action for transferring a repository to a new owner. - TransferRepo(ctx context.Context, doer, oldOwner, newOwner *User, repo *Repository) error +// ActionsStore is the storage layer for actions. +type ActionsStore struct { + db *gorm.DB } -var Actions ActionsStore - -var _ ActionsStore = (*actionsStore)(nil) - -type actionsStore struct { - *gorm.DB +func newActionsStore(db *gorm.DB) *ActionsStore { + return &ActionsStore{db: db} } -// NewActionsStore returns a persistent interface for actions with given -// database connection. -func NewActionsStore(db *gorm.DB) ActionsStore { - return &actionsStore{DB: db} -} - -func (s *actionsStore) listByOrganization(ctx context.Context, orgID, actorID, afterID int64) *gorm.DB { +func (s *ActionsStore) listByOrganization(ctx context.Context, orgID, actorID, afterID int64) *gorm.DB { /* Equivalent SQL for PostgreSQL: @@ -102,18 +57,18 @@ func (s *actionsStore) listByOrganization(ctx context.Context, orgID, actorID, a ORDER BY id DESC LIMIT @limit */ - return s.WithContext(ctx). + return s.db.WithContext(ctx). Where("user_id = ?", orgID). - Where(s. + Where(s.db. // Not apply when afterID is not given Where("?", afterID <= 0). Or("id < ?", afterID), ). - Where("repo_id IN (?)", s. + Where("repo_id IN (?)", s.db. Select("repository.id"). Table("repository"). Joins("JOIN team_repo ON repository.id = team_repo.repo_id"). - Where("team_repo.team_id IN (?)", s. + Where("team_repo.team_id IN (?)", s.db. Select("team_id"). Table("team_user"). Where("team_user.org_id = ? AND uid = ?", orgID, actorID), @@ -124,12 +79,14 @@ func (s *actionsStore) listByOrganization(ctx context.Context, orgID, actorID, a Order("id DESC") } -func (s *actionsStore) ListByOrganization(ctx context.Context, orgID, actorID, afterID int64) ([]*Action, error) { +// ListByOrganization returns actions of the organization viewable by the actor. +// Results are paginated if `afterID` is given. +func (s *ActionsStore) ListByOrganization(ctx context.Context, orgID, actorID, afterID int64) ([]*Action, error) { actions := make([]*Action, 0, conf.UI.User.NewsFeedPagingNum) return actions, s.listByOrganization(ctx, orgID, actorID, afterID).Find(&actions).Error } -func (s *actionsStore) listByUser(ctx context.Context, userID, actorID, afterID int64, isProfile bool) *gorm.DB { +func (s *ActionsStore) listByUser(ctx context.Context, userID, actorID, afterID int64, isProfile bool) *gorm.DB { /* Equivalent SQL for PostgreSQL: @@ -141,14 +98,14 @@ func (s *actionsStore) listByUser(ctx context.Context, userID, actorID, afterID ORDER BY id DESC LIMIT @limit */ - return s.WithContext(ctx). + return s.db.WithContext(ctx). Where("user_id = ?", userID). - Where(s. + Where(s.db. // Not apply when afterID is not given Where("?", afterID <= 0). Or("id < ?", afterID), ). - Where(s. + Where(s.db. // Not apply when in not profile page or the user is viewing own profile Where("?", !isProfile || actorID == userID). Or("is_private = ? AND act_user_id = ?", false, userID), @@ -157,14 +114,17 @@ func (s *actionsStore) listByUser(ctx context.Context, userID, actorID, afterID Order("id DESC") } -func (s *actionsStore) ListByUser(ctx context.Context, userID, actorID, afterID int64, isProfile bool) ([]*Action, error) { +// ListByUser returns actions of the user viewable by the actor. Results are +// paginated if `afterID` is given. The `isProfile` indicates whether repository +// permissions should be considered. +func (s *ActionsStore) ListByUser(ctx context.Context, userID, actorID, afterID int64, isProfile bool) ([]*Action, error) { actions := make([]*Action, 0, conf.UI.User.NewsFeedPagingNum) return actions, s.listByUser(ctx, userID, actorID, afterID, isProfile).Find(&actions).Error } // notifyWatchers creates rows in action table for watchers who are able to see the action. -func (s *actionsStore) notifyWatchers(ctx context.Context, act *Action) error { - watches, err := NewReposStore(s.DB).ListWatches(ctx, act.RepoID) +func (s *ActionsStore) notifyWatchers(ctx context.Context, act *Action) error { + watches, err := NewReposStore(s.db).ListWatches(ctx, act.RepoID) if err != nil { return errors.Wrap(err, "list watches") } @@ -187,10 +147,13 @@ func (s *actionsStore) notifyWatchers(ctx context.Context, act *Action) error { actions = append(actions, clone(watch.UserID)) } - return s.Create(actions).Error + return s.db.Create(actions).Error } -func (s *actionsStore) NewRepo(ctx context.Context, doer, owner *User, repo *Repository) error { +// NewRepo creates an action for creating a new repository. The action type +// could be ActionCreateRepo or ActionForkRepo based on whether the repository +// is a fork. +func (s *ActionsStore) NewRepo(ctx context.Context, doer, owner *User, repo *Repository) error { opType := ActionCreateRepo if repo.IsFork { opType = ActionForkRepo @@ -209,7 +172,8 @@ func (s *actionsStore) NewRepo(ctx context.Context, doer, owner *User, repo *Rep ) } -func (s *actionsStore) RenameRepo(ctx context.Context, doer, owner *User, oldRepoName string, repo *Repository) error { +// RenameRepo creates an action for renaming a repository. +func (s *ActionsStore) RenameRepo(ctx context.Context, doer, owner *User, oldRepoName string, repo *Repository) error { return s.notifyWatchers(ctx, &Action{ ActUserID: doer.ID, @@ -224,7 +188,7 @@ func (s *actionsStore) RenameRepo(ctx context.Context, doer, owner *User, oldRep ) } -func (s *actionsStore) mirrorSyncAction(ctx context.Context, opType ActionType, owner *User, repo *Repository, refName string, content []byte) error { +func (s *ActionsStore) mirrorSyncAction(ctx context.Context, opType ActionType, owner *User, repo *Repository, refName string, content []byte) error { return s.notifyWatchers(ctx, &Action{ ActUserID: owner.ID, @@ -249,13 +213,15 @@ type MirrorSyncPushOptions struct { Commits *PushCommits } -func (s *actionsStore) MirrorSyncPush(ctx context.Context, opts MirrorSyncPushOptions) error { +// MirrorSyncPush creates an action for mirror synchronization of pushed +// commits. +func (s *ActionsStore) MirrorSyncPush(ctx context.Context, opts MirrorSyncPushOptions) error { if conf.UI.FeedMaxCommitNum > 0 && len(opts.Commits.Commits) > conf.UI.FeedMaxCommitNum { opts.Commits.Commits = opts.Commits.Commits[:conf.UI.FeedMaxCommitNum] } apiCommits, err := opts.Commits.APIFormat(ctx, - NewUsersStore(s.DB), + NewUsersStore(s.db), repoutil.RepositoryPath(opts.Owner.Name, opts.Repo.Name), repoutil.HTMLURL(opts.Owner.Name, opts.Repo.Name), ) @@ -291,15 +257,20 @@ func (s *actionsStore) MirrorSyncPush(ctx context.Context, opts MirrorSyncPushOp return s.mirrorSyncAction(ctx, ActionMirrorSyncPush, opts.Owner, opts.Repo, opts.RefName, data) } -func (s *actionsStore) MirrorSyncCreate(ctx context.Context, owner *User, repo *Repository, refName string) error { +// MirrorSyncCreate creates an action for mirror synchronization of a new +// reference. +func (s *ActionsStore) MirrorSyncCreate(ctx context.Context, owner *User, repo *Repository, refName string) error { return s.mirrorSyncAction(ctx, ActionMirrorSyncCreate, owner, repo, refName, nil) } -func (s *actionsStore) MirrorSyncDelete(ctx context.Context, owner *User, repo *Repository, refName string) error { +// MirrorSyncDelete creates an action for mirror synchronization of a reference +// deletion. +func (s *ActionsStore) MirrorSyncDelete(ctx context.Context, owner *User, repo *Repository, refName string) error { return s.mirrorSyncAction(ctx, ActionMirrorSyncDelete, owner, repo, refName, nil) } -func (s *actionsStore) MergePullRequest(ctx context.Context, doer, owner *User, repo *Repository, pull *Issue) error { +// MergePullRequest creates an action for merging a pull request. +func (s *ActionsStore) MergePullRequest(ctx context.Context, doer, owner *User, repo *Repository, pull *Issue) error { return s.notifyWatchers(ctx, &Action{ ActUserID: doer.ID, @@ -314,7 +285,8 @@ func (s *actionsStore) MergePullRequest(ctx context.Context, doer, owner *User, ) } -func (s *actionsStore) TransferRepo(ctx context.Context, doer, oldOwner, newOwner *User, repo *Repository) error { +// TransferRepo creates an action for transferring a repository to a new owner. +func (s *ActionsStore) TransferRepo(ctx context.Context, doer, oldOwner, newOwner *User, repo *Repository) error { return s.notifyWatchers(ctx, &Action{ ActUserID: doer.ID, @@ -487,13 +459,18 @@ type CommitRepoOptions struct { Commits *PushCommits } -func (s *actionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) error { - err := NewReposStore(s.DB).Touch(ctx, opts.Repo.ID) +// CommitRepo creates actions for pushing commits to the repository. An action +// with the type ActionDeleteBranch is created if the push deletes a branch; an +// action with the type ActionCommitRepo is created for a regular push. If the +// regular push also creates a new branch, then another action with type +// ActionCreateBranch is created. +func (s *ActionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) error { + err := NewReposStore(s.db).Touch(ctx, opts.Repo.ID) if err != nil { return errors.Wrap(err, "touch repository") } - pusher, err := NewUsersStore(s.DB).GetByUsername(ctx, opts.PusherName) + pusher, err := NewUsersStore(s.db).GetByUsername(ctx, opts.PusherName) if err != nil { return errors.Wrapf(err, "get pusher [name: %s]", opts.PusherName) } @@ -589,7 +566,7 @@ func (s *actionsStore) CommitRepo(ctx context.Context, opts CommitRepoOptions) e } commits, err := opts.Commits.APIFormat(ctx, - NewUsersStore(s.DB), + NewUsersStore(s.db), repoutil.RepositoryPath(opts.Owner.Name, opts.Repo.Name), repoutil.HTMLURL(opts.Owner.Name, opts.Repo.Name), ) @@ -631,13 +608,16 @@ type PushTagOptions struct { NewCommitID string } -func (s *actionsStore) PushTag(ctx context.Context, opts PushTagOptions) error { - err := NewReposStore(s.DB).Touch(ctx, opts.Repo.ID) +// PushTag creates an action for pushing tags to the repository. An action with +// the type ActionDeleteTag is created if the push deletes a tag. Otherwise, an +// action with the type ActionPushTag is created for a regular push. +func (s *ActionsStore) PushTag(ctx context.Context, opts PushTagOptions) error { + err := NewReposStore(s.db).Touch(ctx, opts.Repo.ID) if err != nil { return errors.Wrap(err, "touch repository") } - pusher, err := NewUsersStore(s.DB).GetByUsername(ctx, opts.PusherName) + pusher, err := NewUsersStore(s.db).GetByUsername(ctx, opts.PusherName) if err != nil { return errors.Wrapf(err, "get pusher [name: %s]", opts.PusherName) } @@ -703,7 +683,7 @@ func (s *actionsStore) PushTag(ctx context.Context, opts PushTagOptions) error { return nil } -// ActionType is the type of an action. +// ActionType is the type of action. type ActionType int // ⚠️ WARNING: Only append to the end of list to maintain backward compatibility. diff --git a/internal/database/actions_test.go b/internal/database/actions_test.go index 5fd3f7580..aa1eaa2a5 100644 --- a/internal/database/actions_test.go +++ b/internal/database/actions_test.go @@ -99,13 +99,13 @@ func TestActions(t *testing.T) { ctx := context.Background() t.Parallel() - db := &actionsStore{ - DB: newTestDB(t, "actionsStore"), + s := &ActionsStore{ + db: newTestDB(t, "ActionsStore"), } for _, tc := range []struct { name string - test func(t *testing.T, ctx context.Context, db *actionsStore) + test func(t *testing.T, ctx context.Context, s *ActionsStore) }{ {"CommitRepo", actionsCommitRepo}, {"ListByOrganization", actionsListByOrganization}, @@ -121,10 +121,10 @@ func TestActions(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { t.Cleanup(func() { - err := clearTables(t, db.DB) + err := clearTables(t, s.db) require.NoError(t, err) }) - tc.test(t, ctx, db) + tc.test(t, ctx, s) }) if t.Failed() { break @@ -132,10 +132,10 @@ func TestActions(t *testing.T) { } } -func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { - alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) +func actionsCommitRepo(t *testing.T, ctx context.Context, s *ActionsStore) { + alice, err := NewUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) require.NoError(t, err) - repo, err := NewReposStore(db.DB).Create(ctx, + repo, err := NewReposStore(s.db).Create(ctx, alice.ID, CreateRepoOptions{ Name: "example", @@ -149,11 +149,11 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { t.Run("new commit", func(t *testing.T) { t.Cleanup(func() { - err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error + err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error require.NoError(t, err) }) - err = db.CommitRepo(ctx, + err = s.CommitRepo(ctx, CommitRepoOptions{ PusherName: alice.Name, Owner: alice, @@ -183,7 +183,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { ) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -200,7 +200,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { RefName: "main", IsPrivate: false, Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"alice@example.com","AuthorName":"alice","CommitterEmail":"alice@example.com","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":"alice/example/compare/ca82a6dff817ec66f44342007202690a93763949...085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7"}`, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) @@ -209,11 +209,11 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { t.Run("new ref", func(t *testing.T) { t.Cleanup(func() { - err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error + err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error require.NoError(t, err) }) - err = db.CommitRepo(ctx, + err = s.CommitRepo(ctx, CommitRepoOptions{ PusherName: alice.Name, Owner: alice, @@ -243,7 +243,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { ) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 2) got[0].ID = 0 @@ -261,7 +261,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { RefName: "main", IsPrivate: false, Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"alice@example.com","AuthorName":"alice","CommitterEmail":"alice@example.com","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":""}`, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, { UserID: alice.ID, @@ -274,7 +274,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { RefName: "main", IsPrivate: false, Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"alice@example.com","AuthorName":"alice","CommitterEmail":"alice@example.com","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":""}`, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) @@ -284,11 +284,11 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { t.Run("delete ref", func(t *testing.T) { t.Cleanup(func() { - err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error + err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error require.NoError(t, err) }) - err = db.CommitRepo(ctx, + err = s.CommitRepo(ctx, CommitRepoOptions{ PusherName: alice.Name, Owner: alice, @@ -300,7 +300,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { ) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -316,7 +316,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { RepoName: repo.Name, RefName: "main", IsPrivate: false, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) @@ -324,7 +324,7 @@ func actionsCommitRepo(t *testing.T, ctx context.Context, db *actionsStore) { }) } -func actionsListByOrganization(t *testing.T, ctx context.Context, db *actionsStore) { +func actionsListByOrganization(t *testing.T, ctx context.Context, s *ActionsStore) { if os.Getenv("GOGS_DATABASE_TYPE") != "postgres" { t.Skip("Skipping testing with not using PostgreSQL") return @@ -362,15 +362,15 @@ func actionsListByOrganization(t *testing.T, ctx context.Context, db *actionsSto } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got := db.DB.ToSQL(func(tx *gorm.DB) *gorm.DB { - return NewActionsStore(tx).(*actionsStore).listByOrganization(ctx, test.orgID, test.actorID, test.afterID).Find(new(Action)) + got := s.db.ToSQL(func(tx *gorm.DB) *gorm.DB { + return newActionsStore(tx).listByOrganization(ctx, test.orgID, test.actorID, test.afterID).Find(new(Action)) }) assert.Equal(t, test.want, got) }) } } -func actionsListByUser(t *testing.T, ctx context.Context, db *actionsStore) { +func actionsListByUser(t *testing.T, ctx context.Context, s *ActionsStore) { if os.Getenv("GOGS_DATABASE_TYPE") != "postgres" { t.Skip("Skipping testing with not using PostgreSQL") return @@ -427,18 +427,18 @@ func actionsListByUser(t *testing.T, ctx context.Context, db *actionsStore) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got := db.DB.ToSQL(func(tx *gorm.DB) *gorm.DB { - return NewActionsStore(tx).(*actionsStore).listByUser(ctx, test.userID, test.actorID, test.afterID, test.isProfile).Find(new(Action)) + got := s.db.ToSQL(func(tx *gorm.DB) *gorm.DB { + return newActionsStore(tx).listByUser(ctx, test.userID, test.actorID, test.afterID, test.isProfile).Find(new(Action)) }) assert.Equal(t, test.want, got) }) } } -func actionsMergePullRequest(t *testing.T, ctx context.Context, db *actionsStore) { - alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) +func actionsMergePullRequest(t *testing.T, ctx context.Context, s *ActionsStore) { + alice, err := NewUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) require.NoError(t, err) - repo, err := NewReposStore(db.DB).Create(ctx, + repo, err := NewReposStore(s.db).Create(ctx, alice.ID, CreateRepoOptions{ Name: "example", @@ -446,7 +446,7 @@ func actionsMergePullRequest(t *testing.T, ctx context.Context, db *actionsStore ) require.NoError(t, err) - err = db.MergePullRequest(ctx, + err = s.MergePullRequest(ctx, alice, alice, repo, @@ -457,7 +457,7 @@ func actionsMergePullRequest(t *testing.T, ctx context.Context, db *actionsStore ) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -473,17 +473,17 @@ func actionsMergePullRequest(t *testing.T, ctx context.Context, db *actionsStore RepoName: repo.Name, IsPrivate: false, Content: `1|Fix issue 1`, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) assert.Equal(t, want, got) } -func actionsMirrorSyncCreate(t *testing.T, ctx context.Context, db *actionsStore) { - alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) +func actionsMirrorSyncCreate(t *testing.T, ctx context.Context, s *ActionsStore) { + alice, err := NewUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) require.NoError(t, err) - repo, err := NewReposStore(db.DB).Create(ctx, + repo, err := NewReposStore(s.db).Create(ctx, alice.ID, CreateRepoOptions{ Name: "example", @@ -491,14 +491,14 @@ func actionsMirrorSyncCreate(t *testing.T, ctx context.Context, db *actionsStore ) require.NoError(t, err) - err = db.MirrorSyncCreate(ctx, + err = s.MirrorSyncCreate(ctx, alice, repo, "main", ) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -514,17 +514,17 @@ func actionsMirrorSyncCreate(t *testing.T, ctx context.Context, db *actionsStore RepoName: repo.Name, RefName: "main", IsPrivate: false, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) assert.Equal(t, want, got) } -func actionsMirrorSyncDelete(t *testing.T, ctx context.Context, db *actionsStore) { - alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) +func actionsMirrorSyncDelete(t *testing.T, ctx context.Context, s *ActionsStore) { + alice, err := NewUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) require.NoError(t, err) - repo, err := NewReposStore(db.DB).Create(ctx, + repo, err := NewReposStore(s.db).Create(ctx, alice.ID, CreateRepoOptions{ Name: "example", @@ -532,14 +532,14 @@ func actionsMirrorSyncDelete(t *testing.T, ctx context.Context, db *actionsStore ) require.NoError(t, err) - err = db.MirrorSyncDelete(ctx, + err = s.MirrorSyncDelete(ctx, alice, repo, "main", ) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -555,17 +555,17 @@ func actionsMirrorSyncDelete(t *testing.T, ctx context.Context, db *actionsStore RepoName: repo.Name, RefName: "main", IsPrivate: false, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) assert.Equal(t, want, got) } -func actionsMirrorSyncPush(t *testing.T, ctx context.Context, db *actionsStore) { - alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) +func actionsMirrorSyncPush(t *testing.T, ctx context.Context, s *ActionsStore) { + alice, err := NewUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) require.NoError(t, err) - repo, err := NewReposStore(db.DB).Create(ctx, + repo, err := NewReposStore(s.db).Create(ctx, alice.ID, CreateRepoOptions{ Name: "example", @@ -574,7 +574,7 @@ func actionsMirrorSyncPush(t *testing.T, ctx context.Context, db *actionsStore) require.NoError(t, err) now := time.Unix(1588568886, 0).UTC() - err = db.MirrorSyncPush(ctx, + err = s.MirrorSyncPush(ctx, MirrorSyncPushOptions{ Owner: alice, Repo: repo, @@ -603,7 +603,7 @@ func actionsMirrorSyncPush(t *testing.T, ctx context.Context, db *actionsStore) ) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -620,17 +620,17 @@ func actionsMirrorSyncPush(t *testing.T, ctx context.Context, db *actionsStore) RefName: "main", IsPrivate: false, Content: `{"Len":1,"Commits":[{"Sha1":"085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7","Message":"A random commit","AuthorEmail":"alice@example.com","AuthorName":"alice","CommitterEmail":"alice@example.com","CommitterName":"alice","Timestamp":"2020-05-04T05:08:06Z"}],"CompareURL":"alice/example/compare/ca82a6dff817ec66f44342007202690a93763949...085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7"}`, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) assert.Equal(t, want, got) } -func actionsNewRepo(t *testing.T, ctx context.Context, db *actionsStore) { - alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) +func actionsNewRepo(t *testing.T, ctx context.Context, s *ActionsStore) { + alice, err := NewUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) require.NoError(t, err) - repo, err := NewReposStore(db.DB).Create(ctx, + repo, err := NewReposStore(s.db).Create(ctx, alice.ID, CreateRepoOptions{ Name: "example", @@ -640,14 +640,14 @@ func actionsNewRepo(t *testing.T, ctx context.Context, db *actionsStore) { t.Run("new repo", func(t *testing.T) { t.Cleanup(func() { - err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error + err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error require.NoError(t, err) }) - err = db.NewRepo(ctx, alice, alice, repo) + err = s.NewRepo(ctx, alice, alice, repo) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -662,7 +662,7 @@ func actionsNewRepo(t *testing.T, ctx context.Context, db *actionsStore) { RepoUserName: alice.Name, RepoName: repo.Name, IsPrivate: false, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) @@ -671,15 +671,15 @@ func actionsNewRepo(t *testing.T, ctx context.Context, db *actionsStore) { t.Run("fork repo", func(t *testing.T) { t.Cleanup(func() { - err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error + err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error require.NoError(t, err) }) repo.IsFork = true - err = db.NewRepo(ctx, alice, alice, repo) + err = s.NewRepo(ctx, alice, alice, repo) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -694,7 +694,7 @@ func actionsNewRepo(t *testing.T, ctx context.Context, db *actionsStore) { RepoUserName: alice.Name, RepoName: repo.Name, IsPrivate: false, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) @@ -702,14 +702,14 @@ func actionsNewRepo(t *testing.T, ctx context.Context, db *actionsStore) { }) } -func actionsPushTag(t *testing.T, ctx context.Context, db *actionsStore) { +func actionsPushTag(t *testing.T, ctx context.Context, s *ActionsStore) { // NOTE: We set a noop mock here to avoid data race with other tests that writes // to the mock server because this function holds a lock. conf.SetMockServer(t, conf.ServerOpts{}) - alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) + alice, err := NewUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) require.NoError(t, err) - repo, err := NewReposStore(db.DB).Create(ctx, + repo, err := NewReposStore(s.db).Create(ctx, alice.ID, CreateRepoOptions{ Name: "example", @@ -719,11 +719,11 @@ func actionsPushTag(t *testing.T, ctx context.Context, db *actionsStore) { t.Run("new tag", func(t *testing.T) { t.Cleanup(func() { - err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error + err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error require.NoError(t, err) }) - err = db.PushTag(ctx, + err = s.PushTag(ctx, PushTagOptions{ Owner: alice, Repo: repo, @@ -734,7 +734,7 @@ func actionsPushTag(t *testing.T, ctx context.Context, db *actionsStore) { ) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -750,7 +750,7 @@ func actionsPushTag(t *testing.T, ctx context.Context, db *actionsStore) { RepoName: repo.Name, RefName: "v1.0.0", IsPrivate: false, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) @@ -759,11 +759,11 @@ func actionsPushTag(t *testing.T, ctx context.Context, db *actionsStore) { t.Run("delete tag", func(t *testing.T) { t.Cleanup(func() { - err := db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error + err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).WithContext(ctx).Delete(new(Action)).Error require.NoError(t, err) }) - err = db.PushTag(ctx, + err = s.PushTag(ctx, PushTagOptions{ Owner: alice, Repo: repo, @@ -774,7 +774,7 @@ func actionsPushTag(t *testing.T, ctx context.Context, db *actionsStore) { ) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -790,7 +790,7 @@ func actionsPushTag(t *testing.T, ctx context.Context, db *actionsStore) { RepoName: repo.Name, RefName: "v1.0.0", IsPrivate: false, - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) @@ -798,10 +798,10 @@ func actionsPushTag(t *testing.T, ctx context.Context, db *actionsStore) { }) } -func actionsRenameRepo(t *testing.T, ctx context.Context, db *actionsStore) { - alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) +func actionsRenameRepo(t *testing.T, ctx context.Context, s *ActionsStore) { + alice, err := NewUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) require.NoError(t, err) - repo, err := NewReposStore(db.DB).Create(ctx, + repo, err := NewReposStore(s.db).Create(ctx, alice.ID, CreateRepoOptions{ Name: "example", @@ -809,10 +809,10 @@ func actionsRenameRepo(t *testing.T, ctx context.Context, db *actionsStore) { ) require.NoError(t, err) - err = db.RenameRepo(ctx, alice, alice, "oldExample", repo) + err = s.RenameRepo(ctx, alice, alice, "oldExample", repo) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -828,19 +828,19 @@ func actionsRenameRepo(t *testing.T, ctx context.Context, db *actionsStore) { RepoName: repo.Name, IsPrivate: false, Content: "oldExample", - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) assert.Equal(t, want, got) } -func actionsTransferRepo(t *testing.T, ctx context.Context, db *actionsStore) { - alice, err := NewUsersStore(db.DB).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) +func actionsTransferRepo(t *testing.T, ctx context.Context, s *ActionsStore) { + alice, err := NewUsersStore(s.db).Create(ctx, "alice", "alice@example.com", CreateUserOptions{}) require.NoError(t, err) - bob, err := NewUsersStore(db.DB).Create(ctx, "bob", "bob@example.com", CreateUserOptions{}) + bob, err := NewUsersStore(s.db).Create(ctx, "bob", "bob@example.com", CreateUserOptions{}) require.NoError(t, err) - repo, err := NewReposStore(db.DB).Create(ctx, + repo, err := NewReposStore(s.db).Create(ctx, alice.ID, CreateRepoOptions{ Name: "example", @@ -848,10 +848,10 @@ func actionsTransferRepo(t *testing.T, ctx context.Context, db *actionsStore) { ) require.NoError(t, err) - err = db.TransferRepo(ctx, alice, alice, bob, repo) + err = s.TransferRepo(ctx, alice, alice, bob, repo) require.NoError(t, err) - got, err := db.ListByUser(ctx, alice.ID, alice.ID, 0, false) + got, err := s.ListByUser(ctx, alice.ID, alice.ID, 0, false) require.NoError(t, err) require.Len(t, got, 1) got[0].ID = 0 @@ -867,7 +867,7 @@ func actionsTransferRepo(t *testing.T, ctx context.Context, db *actionsStore) { RepoName: repo.Name, IsPrivate: false, Content: "alice/example", - CreatedUnix: db.NowFunc().Unix(), + CreatedUnix: s.db.NowFunc().Unix(), }, } want[0].Created = time.Unix(want[0].CreatedUnix, 0) diff --git a/internal/database/database.go b/internal/database/database.go index 14d9facff..f1f74e67e 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -123,7 +123,6 @@ func NewConnection(w logger.Writer) (*gorm.DB, error) { } // Initialize stores, sorted in alphabetical order. - Actions = NewActionsStore(db) LoginSources = &loginSourcesStore{DB: db, files: sourceFiles} LFS = &lfsStore{DB: db} Notices = NewNoticesStore(db) @@ -160,3 +159,7 @@ func SetHandle(db *gorm.DB) { func (db *DB) AccessTokens() *AccessTokensStore { return newAccessTokensStore(db.db) } + +func (db *DB) Actions() *ActionsStore { + return newActionsStore(db.db) +} diff --git a/internal/database/mirror.go b/internal/database/mirror.go index 8a4209576..3d2043d7f 100644 --- a/internal/database/mirror.go +++ b/internal/database/mirror.go @@ -361,7 +361,7 @@ func SyncMirrors() { // Delete reference if result.newCommitID == gitShortEmptyID { - if err = Actions.MirrorSyncDelete(ctx, m.Repo.MustOwner(), m.Repo, result.refName); err != nil { + if err = Handle.Actions().MirrorSyncDelete(ctx, m.Repo.MustOwner(), m.Repo, result.refName); err != nil { log.Error("Failed to create action for mirror sync delete [repo_id: %d]: %v", m.RepoID, err) } continue @@ -370,7 +370,7 @@ func SyncMirrors() { // New reference isNewRef := false if result.oldCommitID == gitShortEmptyID { - if err = Actions.MirrorSyncCreate(ctx, m.Repo.MustOwner(), m.Repo, result.refName); err != nil { + if err = Handle.Actions().MirrorSyncCreate(ctx, m.Repo.MustOwner(), m.Repo, result.refName); err != nil { log.Error("Failed to create action for mirror sync create [repo_id: %d]: %v", m.RepoID, err) continue } @@ -419,7 +419,7 @@ func SyncMirrors() { newCommitID = refNewCommit.ID.String() } - err = Actions.MirrorSyncPush(ctx, + err = Handle.Actions().MirrorSyncPush(ctx, MirrorSyncPushOptions{ Owner: m.Repo.MustOwner(), Repo: m.Repo, diff --git a/internal/database/pull.go b/internal/database/pull.go index f067211ef..5f7109d97 100644 --- a/internal/database/pull.go +++ b/internal/database/pull.go @@ -335,7 +335,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle return fmt.Errorf("Commit: %v", err) } - if err = Actions.MergePullRequest(ctx, doer, pr.Issue.Repo.Owner, pr.Issue.Repo, pr.Issue); err != nil { + if err = Handle.Actions().MergePullRequest(ctx, doer, pr.Issue.Repo.Owner, pr.Issue.Repo, pr.Issue); err != nil { log.Error("Failed to create action for merge pull request, pull_request_id: %d, error: %v", pr.ID, err) } diff --git a/internal/database/update.go b/internal/database/update.go index 7976d125c..aef43d9b4 100644 --- a/internal/database/update.go +++ b/internal/database/update.go @@ -49,8 +49,8 @@ type PushUpdateOptions struct { RepoName string } -// PushUpdate must be called for any push actions in order to -// generates necessary push action history feeds. +// PushUpdate must be called for any push actions in order to generate necessary +// push action history feeds. func PushUpdate(opts PushUpdateOptions) (err error) { ctx := context.TODO() @@ -89,7 +89,7 @@ func PushUpdate(opts PushUpdateOptions) (err error) { // Push tags if strings.HasPrefix(opts.FullRefspec, git.RefsTags) { - err := Actions.PushTag(ctx, + err := Handle.Actions().PushTag(ctx, PushTagOptions{ Owner: owner, Repo: repo, @@ -127,7 +127,7 @@ func PushUpdate(opts PushUpdateOptions) (err error) { } } - err = Actions.CommitRepo(ctx, + err = Handle.Actions().CommitRepo(ctx, CommitRepoOptions{ Owner: owner, Repo: repo, diff --git a/internal/route/repo/setting.go b/internal/route/repo/setting.go index 2f9e9239f..037fd9646 100644 --- a/internal/route/repo/setting.go +++ b/internal/route/repo/setting.go @@ -101,7 +101,7 @@ func SettingsPost(c *context.Context, f form.RepoSetting) { log.Trace("Repository basic settings updated: %s/%s", c.Repo.Owner.Name, repo.Name) if isNameChanged { - if err := database.Actions.RenameRepo(c.Req.Context(), c.User, repo.MustOwner(), oldRepoName, repo); err != nil { + if err := database.Handle.Actions().RenameRepo(c.Req.Context(), c.User, repo.MustOwner(), oldRepoName, repo); err != nil { log.Error("create rename repository action: %v", err) } } diff --git a/internal/route/user/home.go b/internal/route/user/home.go index e0fb94049..1f3d64da9 100644 --- a/internal/route/user/home.go +++ b/internal/route/user/home.go @@ -65,9 +65,9 @@ func retrieveFeeds(c *context.Context, ctxUser *database.User, userID int64, isP var err error var actions []*database.Action if ctxUser.IsOrganization() { - actions, err = database.Actions.ListByOrganization(c.Req.Context(), ctxUser.ID, userID, afterID) + actions, err = database.Handle.Actions().ListByOrganization(c.Req.Context(), ctxUser.ID, userID, afterID) } else { - actions, err = database.Actions.ListByUser(c.Req.Context(), ctxUser.ID, userID, afterID, isProfile) + actions, err = database.Handle.Actions().ListByUser(c.Req.Context(), ctxUser.ID, userID, afterID, isProfile) } if err != nil { c.Error(err, "list actions")