all: unwrap `database.RepositoriesStore` interface (#7706)

pull/7707/head
Joe Chen 2024-03-26 23:34:31 -04:00 committed by GitHub
parent e1e75ed36b
commit 4d05804729
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 289 additions and 1463 deletions

View File

@ -29,7 +29,7 @@ func ServeGoGet() macaron.Handler {
owner, err := database.Users.GetByUsername(c.Req.Context(), ownerName)
if err == nil {
repo, err := database.Repos.GetByName(c.Req.Context(), owner.ID, repoName)
repo, err := database.Handle.Repositories().GetByName(c.Req.Context(), owner.ID, repoName)
if err == nil && repo.DefaultBranch != "" {
branchName = repo.DefaultBranch
}

View File

@ -403,7 +403,7 @@ func RepoRef() macaron.Handler {
c.Data["IsViewCommit"] = c.Repo.IsViewCommit
// People who have push access or have forked repository can propose a new pull request.
if c.Repo.IsWriter() || (c.IsLogged && database.Repos.HasForkedBy(c.Req.Context(), c.Repo.Repository.ID, c.User.ID)) {
if c.Repo.IsWriter() || (c.IsLogged && database.Handle.Repositories().HasForkedBy(c.Req.Context(), c.Repo.Repository.ID, c.User.ID)) {
// Pull request is allowed if this is a fork repository
// and base repository accepts pull requests.
if c.Repo.Repository.BaseRepo != nil {

View File

@ -124,7 +124,7 @@ func (s *ActionsStore) ListByUser(ctx context.Context, userID, actorID, afterID
// 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)
watches, err := newReposStore(s.db).ListWatches(ctx, act.RepoID)
if err != nil {
return errors.Wrap(err, "list watches")
}
@ -465,7 +465,7 @@ type CommitRepoOptions struct {
// 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)
err := newReposStore(s.db).Touch(ctx, opts.Repo.ID)
if err != nil {
return errors.Wrap(err, "touch repository")
}
@ -612,7 +612,7 @@ type PushTagOptions struct {
// 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)
err := newReposStore(s.db).Touch(ctx, opts.Repo.ID)
if err != nil {
return errors.Wrap(err, "touch repository")
}

View File

@ -135,7 +135,7 @@ func TestActions(t *testing.T) {
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(s.db).Create(ctx,
repo, err := newReposStore(s.db).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -438,7 +438,7 @@ func actionsListByUser(t *testing.T, ctx context.Context, s *ActionsStore) {
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(s.db).Create(ctx,
repo, err := newReposStore(s.db).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -483,7 +483,7 @@ func actionsMergePullRequest(t *testing.T, ctx context.Context, s *ActionsStore)
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(s.db).Create(ctx,
repo, err := newReposStore(s.db).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -524,7 +524,7 @@ func actionsMirrorSyncCreate(t *testing.T, ctx context.Context, s *ActionsStore)
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(s.db).Create(ctx,
repo, err := newReposStore(s.db).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -565,7 +565,7 @@ func actionsMirrorSyncDelete(t *testing.T, ctx context.Context, s *ActionsStore)
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(s.db).Create(ctx,
repo, err := newReposStore(s.db).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -630,7 +630,7 @@ func actionsMirrorSyncPush(t *testing.T, ctx context.Context, s *ActionsStore) {
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(s.db).Create(ctx,
repo, err := newReposStore(s.db).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -709,7 +709,7 @@ func actionsPushTag(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(s.db).Create(ctx,
repo, err := newReposStore(s.db).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -801,7 +801,7 @@ func actionsPushTag(t *testing.T, ctx context.Context, s *ActionsStore) {
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(s.db).Create(ctx,
repo, err := newReposStore(s.db).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",
@ -840,7 +840,7 @@ func actionsTransferRepo(t *testing.T, ctx context.Context, s *ActionsStore) {
require.NoError(t, err)
bob, err := NewUsersStore(s.db).Create(ctx, "bob", "bob@example.com", CreateUserOptions{})
require.NoError(t, err)
repo, err := NewReposStore(s.db).Create(ctx,
repo, err := newReposStore(s.db).Create(ctx,
alice.ID,
CreateRepoOptions{
Name: "example",

View File

@ -123,7 +123,6 @@ func NewConnection(w logger.Writer) (*gorm.DB, error) {
}
// Initialize stores, sorted in alphabetical order.
Repos = NewReposStore(db)
TwoFactors = &twoFactorsStore{DB: db}
Users = NewUsersStore(db)
@ -183,3 +182,7 @@ func (db *DB) Permissions() *PermissionsStore {
func (db *DB) PublicKey() *PublicKeysStore {
return newPublicKeysStore(db.db)
}
func (db *DB) Repositories() *RepositoriesStore {
return newReposStore(db.db)
}

View File

@ -8,14 +8,6 @@ import (
"testing"
)
func SetMockReposStore(t *testing.T, mock ReposStore) {
before := Repos
Repos = mock
t.Cleanup(func() {
Repos = before
})
}
func SetMockTwoFactorsStore(t *testing.T, mock TwoFactorsStore) {
before := TwoFactors
TwoFactors = mock

View File

@ -18,46 +18,6 @@ import (
"gogs.io/gogs/internal/repoutil"
)
// ReposStore is the persistent interface for repositories.
type ReposStore interface {
// Create creates a new repository record in the database. It returns
// ErrNameNotAllowed when the repository name is not allowed, or
// ErrRepoAlreadyExist when a repository with same name already exists for the
// owner.
Create(ctx context.Context, ownerID int64, opts CreateRepoOptions) (*Repository, error)
// GetByCollaboratorID returns a list of repositories that the given
// collaborator has access to. Results are limited to the given limit and sorted
// by the given order (e.g. "updated_unix DESC"). Repositories that are owned
// directly by the given collaborator are not included.
GetByCollaboratorID(ctx context.Context, collaboratorID int64, limit int, orderBy string) ([]*Repository, error)
// GetByCollaboratorIDWithAccessMode returns a list of repositories and
// corresponding access mode that the given collaborator has access to.
// Repositories that are owned directly by the given collaborator are not
// included.
GetByCollaboratorIDWithAccessMode(ctx context.Context, collaboratorID int64) (map[*Repository]AccessMode, error)
// GetByID returns the repository with given ID. It returns ErrRepoNotExist when
// not found.
GetByID(ctx context.Context, id int64) (*Repository, error)
// GetByName returns the repository with given owner and name. It returns
// ErrRepoNotExist when not found.
GetByName(ctx context.Context, ownerID int64, name string) (*Repository, error)
// Star marks the user to star the repository.
Star(ctx context.Context, userID, repoID int64) error
// Touch updates the updated time to the current time and removes the bare state
// of the given repository.
Touch(ctx context.Context, id int64) error
// ListWatches returns all watches of the given repository.
ListWatches(ctx context.Context, repoID int64) ([]*Watch, error)
// Watch marks the user to watch the repository.
Watch(ctx context.Context, userID, repoID int64) error
// HasForkedBy returns true if the given repository has forked by the given user.
HasForkedBy(ctx context.Context, repoID, userID int64) bool
}
var Repos ReposStore
// BeforeCreate implements the GORM create hook.
func (r *Repository) BeforeCreate(tx *gorm.DB) error {
if r.CreatedUnix == 0 {
@ -119,16 +79,13 @@ func (r *Repository) APIFormat(owner *User, opts ...RepositoryAPIFormatOptions)
}
}
var _ ReposStore = (*reposStore)(nil)
type reposStore struct {
*gorm.DB
// RepositoriesStore is the storage layer for repositories.
type RepositoriesStore struct {
db *gorm.DB
}
// NewReposStore returns a persistent interface for repositories with given
// database connection.
func NewReposStore(db *gorm.DB) ReposStore {
return &reposStore{DB: db}
func newReposStore(db *gorm.DB) *RepositoriesStore {
return &RepositoriesStore{db: db}
}
type ErrRepoAlreadyExist struct {
@ -157,7 +114,11 @@ type CreateRepoOptions struct {
ForkID int64
}
func (s *reposStore) Create(ctx context.Context, ownerID int64, opts CreateRepoOptions) (*Repository, error) {
// Create creates a new repository record in the database. It returns
// ErrNameNotAllowed when the repository name is not allowed, or
// ErrRepoAlreadyExist when a repository with same name already exists for the
// owner.
func (s *RepositoriesStore) Create(ctx context.Context, ownerID int64, opts CreateRepoOptions) (*Repository, error) {
err := isRepoNameAllowed(opts.Name)
if err != nil {
return nil, err
@ -189,13 +150,13 @@ func (s *reposStore) Create(ctx context.Context, ownerID int64, opts CreateRepoO
IsFork: opts.Fork,
ForkID: opts.ForkID,
}
return repo, s.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
return repo, s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
err = tx.Create(repo).Error
if err != nil {
return errors.Wrap(err, "create")
}
err = NewReposStore(tx).Watch(ctx, ownerID, repo.ID)
err = newReposStore(tx).Watch(ctx, ownerID, repo.ID)
if err != nil {
return errors.Wrap(err, "watch")
}
@ -203,7 +164,11 @@ func (s *reposStore) Create(ctx context.Context, ownerID int64, opts CreateRepoO
})
}
func (s *reposStore) GetByCollaboratorID(ctx context.Context, collaboratorID int64, limit int, orderBy string) ([]*Repository, error) {
// GetByCollaboratorID returns a list of repositories that the given
// collaborator has access to. Results are limited to the given limit and sorted
// by the given order (e.g. "updated_unix DESC"). Repositories that are owned
// directly by the given collaborator are not included.
func (s *RepositoriesStore) GetByCollaboratorID(ctx context.Context, collaboratorID int64, limit int, orderBy string) ([]*Repository, error) {
/*
Equivalent SQL for PostgreSQL:
@ -214,7 +179,7 @@ func (s *reposStore) GetByCollaboratorID(ctx context.Context, collaboratorID int
LIMIT @limit
*/
var repos []*Repository
return repos, s.WithContext(ctx).
return repos, s.db.WithContext(ctx).
Joins("JOIN access ON access.repo_id = repository.id AND access.user_id = ?", collaboratorID).
Where("access.mode >= ?", AccessModeRead).
Order(orderBy).
@ -223,7 +188,11 @@ func (s *reposStore) GetByCollaboratorID(ctx context.Context, collaboratorID int
Error
}
func (s *reposStore) GetByCollaboratorIDWithAccessMode(ctx context.Context, collaboratorID int64) (map[*Repository]AccessMode, error) {
// GetByCollaboratorIDWithAccessMode returns a list of repositories and
// corresponding access mode that the given collaborator has access to.
// Repositories that are owned directly by the given collaborator are not
// included.
func (s *RepositoriesStore) GetByCollaboratorIDWithAccessMode(ctx context.Context, collaboratorID int64) (map[*Repository]AccessMode, error) {
/*
Equivalent SQL for PostgreSQL:
@ -238,7 +207,7 @@ func (s *reposStore) GetByCollaboratorIDWithAccessMode(ctx context.Context, coll
*Repository
Mode AccessMode
}
err := s.WithContext(ctx).
err := s.db.WithContext(ctx).
Select("repository.*", "access.mode").
Table("repository").
Joins("JOIN access ON access.repo_id = repository.id AND access.user_id = ?", collaboratorID).
@ -275,11 +244,13 @@ func (ErrRepoNotExist) NotFound() bool {
return true
}
func (s *reposStore) GetByID(ctx context.Context, id int64) (*Repository, error) {
// GetByID returns the repository with given ID. It returns ErrRepoNotExist when
// not found.
func (s *RepositoriesStore) GetByID(ctx context.Context, id int64) (*Repository, error) {
repo := new(Repository)
err := s.WithContext(ctx).Where("id = ?", id).First(repo).Error
err := s.db.WithContext(ctx).Where("id = ?", id).First(repo).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrRepoNotExist{errutil.Args{"repoID": id}}
}
return nil, err
@ -287,9 +258,11 @@ func (s *reposStore) GetByID(ctx context.Context, id int64) (*Repository, error)
return repo, nil
}
func (s *reposStore) GetByName(ctx context.Context, ownerID int64, name string) (*Repository, error) {
// GetByName returns the repository with given owner and name. It returns
// ErrRepoNotExist when not found.
func (s *RepositoriesStore) GetByName(ctx context.Context, ownerID int64, name string) (*Repository, error) {
repo := new(Repository)
err := s.WithContext(ctx).
err := s.db.WithContext(ctx).
Where("owner_id = ? AND lower_name = ?", ownerID, strings.ToLower(name)).
First(repo).
Error
@ -307,7 +280,7 @@ func (s *reposStore) GetByName(ctx context.Context, ownerID int64, name string)
return repo, nil
}
func (s *reposStore) recountStars(tx *gorm.DB, userID, repoID int64) error {
func (s *RepositoriesStore) recountStars(tx *gorm.DB, userID, repoID int64) error {
/*
Equivalent SQL for PostgreSQL:
@ -350,8 +323,9 @@ func (s *reposStore) recountStars(tx *gorm.DB, userID, repoID int64) error {
return nil
}
func (s *reposStore) Star(ctx context.Context, userID, repoID int64) error {
return s.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
// Star marks the user to star the repository.
func (s *RepositoriesStore) Star(ctx context.Context, userID, repoID int64) error {
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
star := &Star{
UserID: userID,
RepoID: repoID,
@ -367,23 +341,26 @@ func (s *reposStore) Star(ctx context.Context, userID, repoID int64) error {
})
}
func (s *reposStore) Touch(ctx context.Context, id int64) error {
return s.WithContext(ctx).
// Touch updates the updated time to the current time and removes the bare state
// of the given repository.
func (s *RepositoriesStore) Touch(ctx context.Context, id int64) error {
return s.db.WithContext(ctx).
Model(new(Repository)).
Where("id = ?", id).
Updates(map[string]any{
"is_bare": false,
"updated_unix": s.NowFunc().Unix(),
"updated_unix": s.db.NowFunc().Unix(),
}).
Error
}
func (s *reposStore) ListWatches(ctx context.Context, repoID int64) ([]*Watch, error) {
// ListWatches returns all watches of the given repository.
func (s *RepositoriesStore) ListWatches(ctx context.Context, repoID int64) ([]*Watch, error) {
var watches []*Watch
return watches, s.WithContext(ctx).Where("repo_id = ?", repoID).Find(&watches).Error
return watches, s.db.WithContext(ctx).Where("repo_id = ?", repoID).Find(&watches).Error
}
func (s *reposStore) recountWatches(tx *gorm.DB, repoID int64) error {
func (s *RepositoriesStore) recountWatches(tx *gorm.DB, repoID int64) error {
/*
Equivalent SQL for PostgreSQL:
@ -402,8 +379,9 @@ func (s *reposStore) recountWatches(tx *gorm.DB, repoID int64) error {
Error
}
func (s *reposStore) Watch(ctx context.Context, userID, repoID int64) error {
return s.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
// Watch marks the user to watch the repository.
func (s *RepositoriesStore) Watch(ctx context.Context, userID, repoID int64) error {
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
w := &Watch{
UserID: userID,
RepoID: repoID,
@ -419,8 +397,9 @@ func (s *reposStore) Watch(ctx context.Context, userID, repoID int64) error {
})
}
func (s *reposStore) HasForkedBy(ctx context.Context, repoID, userID int64) bool {
// HasForkedBy returns true if the given repository has forked by the given user.
func (s *RepositoriesStore) HasForkedBy(ctx context.Context, repoID, userID int64) bool {
var count int64
s.WithContext(ctx).Model(new(Repository)).Where("owner_id = ? AND fork_id = ?", userID, repoID).Count(&count)
s.db.WithContext(ctx).Model(new(Repository)).Where("owner_id = ? AND fork_id = ?", userID, repoID).Count(&count)
return count > 0
}

View File

@ -85,13 +85,13 @@ func TestRepos(t *testing.T) {
t.Parallel()
ctx := context.Background()
db := &reposStore{
DB: newTestDB(t, "repos"),
s := &RepositoriesStore{
db: newTestDB(t, "repos"),
}
for _, tc := range []struct {
name string
test func(t *testing.T, ctx context.Context, db *reposStore)
test func(t *testing.T, ctx context.Context, s *RepositoriesStore)
}{
{"Create", reposCreate},
{"GetByCollaboratorID", reposGetByCollaboratorID},
@ -106,10 +106,10 @@ func TestRepos(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
@ -117,9 +117,9 @@ func TestRepos(t *testing.T) {
}
}
func reposCreate(t *testing.T, ctx context.Context, db *reposStore) {
func reposCreate(t *testing.T, ctx context.Context, s *RepositoriesStore) {
t.Run("name not allowed", func(t *testing.T) {
_, err := db.Create(ctx,
_, err := s.Create(ctx,
1,
CreateRepoOptions{
Name: "my.git",
@ -130,14 +130,14 @@ func reposCreate(t *testing.T, ctx context.Context, db *reposStore) {
})
t.Run("already exists", func(t *testing.T) {
_, err := db.Create(ctx, 2,
_, err := s.Create(ctx, 2,
CreateRepoOptions{
Name: "repo1",
},
)
require.NoError(t, err)
_, err = db.Create(ctx, 2,
_, err = s.Create(ctx, 2,
CreateRepoOptions{
Name: "repo1",
},
@ -146,54 +146,54 @@ func reposCreate(t *testing.T, ctx context.Context, db *reposStore) {
assert.Equal(t, wantErr, err)
})
repo, err := db.Create(ctx, 3,
repo, err := s.Create(ctx, 3,
CreateRepoOptions{
Name: "repo2",
},
)
require.NoError(t, err)
repo, err = db.GetByName(ctx, repo.OwnerID, repo.Name)
repo, err = s.GetByName(ctx, repo.OwnerID, repo.Name)
require.NoError(t, err)
assert.Equal(t, db.NowFunc().Format(time.RFC3339), repo.Created.UTC().Format(time.RFC3339))
assert.Equal(t, s.db.NowFunc().Format(time.RFC3339), repo.Created.UTC().Format(time.RFC3339))
assert.Equal(t, 1, repo.NumWatches) // The owner is watching the repo by default.
}
func reposGetByCollaboratorID(t *testing.T, ctx context.Context, db *reposStore) {
repo1, err := db.Create(ctx, 1, CreateRepoOptions{Name: "repo1"})
func reposGetByCollaboratorID(t *testing.T, ctx context.Context, s *RepositoriesStore) {
repo1, err := s.Create(ctx, 1, CreateRepoOptions{Name: "repo1"})
require.NoError(t, err)
repo2, err := db.Create(ctx, 2, CreateRepoOptions{Name: "repo2"})
repo2, err := s.Create(ctx, 2, CreateRepoOptions{Name: "repo2"})
require.NoError(t, err)
permissionsStore := newPermissionsStore(db.DB)
permissionsStore := newPermissionsStore(s.db)
err = permissionsStore.SetRepoPerms(ctx, repo1.ID, map[int64]AccessMode{3: AccessModeRead})
require.NoError(t, err)
err = permissionsStore.SetRepoPerms(ctx, repo2.ID, map[int64]AccessMode{4: AccessModeAdmin})
require.NoError(t, err)
t.Run("user 3 is a collaborator of repo1", func(t *testing.T) {
got, err := db.GetByCollaboratorID(ctx, 3, 10, "")
got, err := s.GetByCollaboratorID(ctx, 3, 10, "")
require.NoError(t, err)
require.Len(t, got, 1)
assert.Equal(t, repo1.ID, got[0].ID)
})
t.Run("do not return directly owned repository", func(t *testing.T) {
got, err := db.GetByCollaboratorID(ctx, 1, 10, "")
got, err := s.GetByCollaboratorID(ctx, 1, 10, "")
require.NoError(t, err)
require.Len(t, got, 0)
})
}
func reposGetByCollaboratorIDWithAccessMode(t *testing.T, ctx context.Context, db *reposStore) {
repo1, err := db.Create(ctx, 1, CreateRepoOptions{Name: "repo1"})
func reposGetByCollaboratorIDWithAccessMode(t *testing.T, ctx context.Context, s *RepositoriesStore) {
repo1, err := s.Create(ctx, 1, CreateRepoOptions{Name: "repo1"})
require.NoError(t, err)
repo2, err := db.Create(ctx, 2, CreateRepoOptions{Name: "repo2"})
repo2, err := s.Create(ctx, 2, CreateRepoOptions{Name: "repo2"})
require.NoError(t, err)
repo3, err := db.Create(ctx, 2, CreateRepoOptions{Name: "repo3"})
repo3, err := s.Create(ctx, 2, CreateRepoOptions{Name: "repo3"})
require.NoError(t, err)
permissionsStore := newPermissionsStore(db.DB)
permissionsStore := newPermissionsStore(s.db)
err = permissionsStore.SetRepoPerms(ctx, repo1.ID, map[int64]AccessMode{3: AccessModeRead})
require.NoError(t, err)
err = permissionsStore.SetRepoPerms(ctx, repo2.ID, map[int64]AccessMode{3: AccessModeAdmin, 4: AccessModeWrite})
@ -201,7 +201,7 @@ func reposGetByCollaboratorIDWithAccessMode(t *testing.T, ctx context.Context, d
err = permissionsStore.SetRepoPerms(ctx, repo3.ID, map[int64]AccessMode{4: AccessModeWrite})
require.NoError(t, err)
got, err := db.GetByCollaboratorIDWithAccessMode(ctx, 3)
got, err := s.GetByCollaboratorIDWithAccessMode(ctx, 3)
require.NoError(t, err)
require.Len(t, got, 2)
@ -213,46 +213,46 @@ func reposGetByCollaboratorIDWithAccessMode(t *testing.T, ctx context.Context, d
assert.Equal(t, AccessModeAdmin, accessModes[repo2.ID])
}
func reposGetByID(t *testing.T, ctx context.Context, db *reposStore) {
repo1, err := db.Create(ctx, 1, CreateRepoOptions{Name: "repo1"})
func reposGetByID(t *testing.T, ctx context.Context, s *RepositoriesStore) {
repo1, err := s.Create(ctx, 1, CreateRepoOptions{Name: "repo1"})
require.NoError(t, err)
got, err := db.GetByID(ctx, repo1.ID)
got, err := s.GetByID(ctx, repo1.ID)
require.NoError(t, err)
assert.Equal(t, repo1.Name, got.Name)
_, err = db.GetByID(ctx, 404)
_, err = s.GetByID(ctx, 404)
wantErr := ErrRepoNotExist{args: errutil.Args{"repoID": int64(404)}}
assert.Equal(t, wantErr, err)
}
func reposGetByName(t *testing.T, ctx context.Context, db *reposStore) {
repo, err := db.Create(ctx, 1,
func reposGetByName(t *testing.T, ctx context.Context, s *RepositoriesStore) {
repo, err := s.Create(ctx, 1,
CreateRepoOptions{
Name: "repo1",
},
)
require.NoError(t, err)
_, err = db.GetByName(ctx, repo.OwnerID, repo.Name)
_, err = s.GetByName(ctx, repo.OwnerID, repo.Name)
require.NoError(t, err)
_, err = db.GetByName(ctx, 1, "bad_name")
_, err = s.GetByName(ctx, 1, "bad_name")
wantErr := ErrRepoNotExist{args: errutil.Args{"ownerID": int64(1), "name": "bad_name"}}
assert.Equal(t, wantErr, err)
}
func reposStar(t *testing.T, ctx context.Context, db *reposStore) {
repo1, err := db.Create(ctx, 1, CreateRepoOptions{Name: "repo1"})
func reposStar(t *testing.T, ctx context.Context, s *RepositoriesStore) {
repo1, err := s.Create(ctx, 1, CreateRepoOptions{Name: "repo1"})
require.NoError(t, err)
usersStore := NewUsersStore(db.DB)
usersStore := NewUsersStore(s.db)
alice, err := usersStore.Create(ctx, "alice", "alice@example.com", CreateUserOptions{})
require.NoError(t, err)
err = db.Star(ctx, alice.ID, repo1.ID)
err = s.Star(ctx, alice.ID, repo1.ID)
require.NoError(t, err)
repo1, err = db.GetByID(ctx, repo1.ID)
repo1, err = s.GetByID(ctx, repo1.ID)
require.NoError(t, err)
assert.Equal(t, 1, repo1.NumStars)
@ -261,41 +261,41 @@ func reposStar(t *testing.T, ctx context.Context, db *reposStore) {
assert.Equal(t, 1, alice.NumStars)
}
func reposTouch(t *testing.T, ctx context.Context, db *reposStore) {
repo, err := db.Create(ctx, 1,
func reposTouch(t *testing.T, ctx context.Context, s *RepositoriesStore) {
repo, err := s.Create(ctx, 1,
CreateRepoOptions{
Name: "repo1",
},
)
require.NoError(t, err)
err = db.WithContext(ctx).Model(new(Repository)).Where("id = ?", repo.ID).Update("is_bare", true).Error
err = s.db.WithContext(ctx).Model(new(Repository)).Where("id = ?", repo.ID).Update("is_bare", true).Error
require.NoError(t, err)
// Make sure it is bare
got, err := db.GetByName(ctx, repo.OwnerID, repo.Name)
got, err := s.GetByName(ctx, repo.OwnerID, repo.Name)
require.NoError(t, err)
assert.True(t, got.IsBare)
// Touch it
err = db.Touch(ctx, repo.ID)
err = s.Touch(ctx, repo.ID)
require.NoError(t, err)
// It should not be bare anymore
got, err = db.GetByName(ctx, repo.OwnerID, repo.Name)
got, err = s.GetByName(ctx, repo.OwnerID, repo.Name)
require.NoError(t, err)
assert.False(t, got.IsBare)
}
func reposListWatches(t *testing.T, ctx context.Context, db *reposStore) {
err := db.Watch(ctx, 1, 1)
func reposListWatches(t *testing.T, ctx context.Context, s *RepositoriesStore) {
err := s.Watch(ctx, 1, 1)
require.NoError(t, err)
err = db.Watch(ctx, 2, 1)
err = s.Watch(ctx, 2, 1)
require.NoError(t, err)
err = db.Watch(ctx, 2, 2)
err = s.Watch(ctx, 2, 2)
require.NoError(t, err)
got, err := db.ListWatches(ctx, 1)
got, err := s.ListWatches(ctx, 1)
require.NoError(t, err)
for _, w := range got {
w.ID = 0
@ -308,16 +308,16 @@ func reposListWatches(t *testing.T, ctx context.Context, db *reposStore) {
assert.Equal(t, want, got)
}
func reposWatch(t *testing.T, ctx context.Context, db *reposStore) {
reposStore := NewReposStore(db.DB)
func reposWatch(t *testing.T, ctx context.Context, s *RepositoriesStore) {
reposStore := newReposStore(s.db)
repo1, err := reposStore.Create(ctx, 1, CreateRepoOptions{Name: "repo1"})
require.NoError(t, err)
err = db.Watch(ctx, 2, repo1.ID)
err = s.Watch(ctx, 2, repo1.ID)
require.NoError(t, err)
// It is OK to watch multiple times and just be noop.
err = db.Watch(ctx, 2, repo1.ID)
err = s.Watch(ctx, 2, repo1.ID)
require.NoError(t, err)
repo1, err = reposStore.GetByID(ctx, repo1.ID)
@ -325,11 +325,11 @@ func reposWatch(t *testing.T, ctx context.Context, db *reposStore) {
assert.Equal(t, 2, repo1.NumWatches) // The owner is watching the repo by default.
}
func reposHasForkedBy(t *testing.T, ctx context.Context, db *reposStore) {
has := db.HasForkedBy(ctx, 1, 2)
func reposHasForkedBy(t *testing.T, ctx context.Context, s *RepositoriesStore) {
has := s.HasForkedBy(ctx, 1, 2)
assert.False(t, has)
_, err := NewReposStore(db.DB).Create(
_, err := newReposStore(s.db).Create(
ctx,
2,
CreateRepoOptions{
@ -339,6 +339,6 @@ func reposHasForkedBy(t *testing.T, ctx context.Context, db *reposStore) {
)
require.NoError(t, err)
has = db.HasForkedBy(ctx, 1, 2)
has = s.HasForkedBy(ctx, 1, 2)
assert.True(t, has)
}

View File

@ -294,7 +294,7 @@ func usersChangeUsername(t *testing.T, ctx context.Context, db *usersStore) {
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tempServerAppDataPath) }()
repo, err := NewReposStore(db.DB).Create(
repo, err := newReposStore(db.DB).Create(
ctx,
alice.ID,
CreateRepoOptions{
@ -466,7 +466,7 @@ func usersDeleteCustomAvatar(t *testing.T, ctx context.Context, db *usersStore)
}
func usersDeleteByID(t *testing.T, ctx context.Context, db *usersStore) {
reposStore := NewReposStore(db.DB)
reposStore := newReposStore(db.DB)
t.Run("user still has repository ownership", func(t *testing.T) {
alice, err := db.Create(ctx, "alice", "alice@exmaple.com", CreateUserOptions{})
@ -679,7 +679,7 @@ func usersDeleteInactivated(t *testing.T, ctx context.Context, db *usersStore) {
// User with repository ownership should be skipped
alice, err := db.Create(ctx, "alice", "alice@exmaple.com", CreateUserOptions{})
require.NoError(t, err)
reposStore := NewReposStore(db.DB)
reposStore := newReposStore(db.DB)
_, err = reposStore.Create(ctx, alice.ID, CreateRepoOptions{Name: "repo1"})
require.NoError(t, err)

View File

@ -45,7 +45,7 @@ func repoAssignment() macaron.Handler {
}
c.Repo.Owner = owner
repo, err := database.Repos.GetByName(c.Req.Context(), owner.ID, reponame)
repo, err := database.Handle.Repositories().GetByName(c.Req.Context(), owner.ID, reponame)
if err != nil {
c.NotFoundOrError(err, "get repository by name")
return

View File

@ -116,7 +116,7 @@ func listUserRepositories(c *context.APIContext, username string) {
return
}
accessibleRepos, err := database.Repos.GetByCollaboratorIDWithAccessMode(c.Req.Context(), user.ID)
accessibleRepos, err := database.Handle.Repositories().GetByCollaboratorIDWithAccessMode(c.Req.Context(), user.ID)
if err != nil {
c.Error(err, "get repositories accesses by collaborator")
return

File diff suppressed because it is too large Load Diff

View File

@ -120,7 +120,7 @@ func authorize(store Store, mode database.AccessMode) macaron.Handler {
return
}
repo, err := database.Repos.GetByName(c.Req.Context(), owner.ID, reponame)
repo, err := store.GetRepositoryByName(c.Req.Context(), owner.ID, reponame)
if err != nil {
if database.IsErrRepoNotExist(err) {
c.Status(http.StatusNotFound)

View File

@ -192,7 +192,6 @@ func TestAuthorize(t *testing.T) {
name string
accessMode database.AccessMode
mockUsersStore func() database.UsersStore
mockReposStore func() database.ReposStore
mockStore func() *MockStore
expStatusCode int
expBody string
@ -217,10 +216,10 @@ func TestAuthorize(t *testing.T) {
})
return mock
},
mockReposStore: func() database.ReposStore {
mock := NewMockReposStore()
mock.GetByNameFunc.SetDefaultReturn(nil, database.ErrRepoNotExist{})
return mock
mockStore: func() *MockStore {
mockStore := NewMockStore()
mockStore.GetRepositoryByNameFunc.SetDefaultReturn(nil, database.ErrRepoNotExist{})
return mockStore
},
expStatusCode: http.StatusNotFound,
},
@ -234,18 +233,14 @@ func TestAuthorize(t *testing.T) {
})
return mock
},
mockReposStore: func() database.ReposStore {
mock := NewMockReposStore()
mock.GetByNameFunc.SetDefaultHook(func(ctx context.Context, ownerID int64, name string) (*database.Repository, error) {
return &database.Repository{Name: name}, nil
})
return mock
},
mockStore: func() *MockStore {
mockStore := NewMockStore()
mockStore.AuthorizeRepositoryAccessFunc.SetDefaultHook(func(_ context.Context, _ int64, _ int64, desired database.AccessMode, _ database.AccessModeOptions) bool {
return desired <= database.AccessModeRead
})
mockStore.GetRepositoryByNameFunc.SetDefaultHook(func(ctx context.Context, ownerID int64, name string) (*database.Repository, error) {
return &database.Repository{Name: name}, nil
})
return mockStore
},
expStatusCode: http.StatusNotFound,
@ -261,18 +256,14 @@ func TestAuthorize(t *testing.T) {
})
return mock
},
mockReposStore: func() database.ReposStore {
mock := NewMockReposStore()
mock.GetByNameFunc.SetDefaultHook(func(ctx context.Context, ownerID int64, name string) (*database.Repository, error) {
return &database.Repository{Name: name}, nil
})
return mock
},
mockStore: func() *MockStore {
mockStore := NewMockStore()
mockStore.AuthorizeRepositoryAccessFunc.SetDefaultHook(func(_ context.Context, _ int64, _ int64, desired database.AccessMode, _ database.AccessModeOptions) bool {
return desired <= database.AccessModeRead
})
mockStore.GetRepositoryByNameFunc.SetDefaultHook(func(ctx context.Context, ownerID int64, name string) (*database.Repository, error) {
return &database.Repository{Name: name}, nil
})
return mockStore
},
expStatusCode: http.StatusOK,
@ -284,9 +275,6 @@ func TestAuthorize(t *testing.T) {
if test.mockUsersStore != nil {
database.SetMockUsersStore(t, test.mockUsersStore())
}
if test.mockReposStore != nil {
database.SetMockReposStore(t, test.mockReposStore())
}
mockStore := NewMockStore()
if test.mockStore != nil {
mockStore = test.mockStore()

View File

@ -30,6 +30,10 @@ type Store interface {
// AuthorizeRepositoryAccess returns true if the user has as good as desired
// access mode to the repository.
AuthorizeRepositoryAccess(ctx context.Context, userID, repoID int64, desired database.AccessMode, opts database.AccessModeOptions) bool
// GetRepositoryByName returns the repository with given owner and name. It
// returns database.ErrRepoNotExist when not found.
GetRepositoryByName(ctx context.Context, ownerID int64, name string) (*database.Repository, error)
}
type store struct{}
@ -62,3 +66,7 @@ func (*store) GetLFSObjectsByOIDs(ctx context.Context, repoID int64, oids ...lfs
func (*store) AuthorizeRepositoryAccess(ctx context.Context, userID, repoID int64, desired database.AccessMode, opts database.AccessModeOptions) bool {
return database.Handle.Permissions().Authorize(ctx, userID, repoID, desired, opts)
}
func (*store) GetRepositoryByName(ctx context.Context, ownerID int64, name string) (*database.Repository, error) {
return database.Handle.Repositories().GetByName(ctx, ownerID, name)
}

View File

@ -77,7 +77,7 @@ func HTTPContexter(store Store) macaron.Handler {
return
}
repo, err := database.Repos.GetByName(c.Req.Context(), owner.ID, repoName)
repo, err := store.GetRepositoryByName(c.Req.Context(), owner.ID, repoName)
if err != nil {
if database.IsErrRepoNotExist(err) {
c.Status(http.StatusNotFound)

View File

@ -68,7 +68,7 @@ func MustAllowPulls(c *context.Context) {
}
// User can send pull request if owns a forked repository.
if c.IsLogged && database.Repos.HasForkedBy(c.Req.Context(), c.Repo.Repository.ID, c.User.ID) {
if c.IsLogged && database.Handle.Repositories().HasForkedBy(c.Req.Context(), c.Repo.Repository.ID, c.User.ID) {
c.Repo.PullRequest.Allowed = true
c.Repo.PullRequest.HeadInfo = c.User.Name + ":" + c.Repo.BranchName
}

View File

@ -16,6 +16,10 @@ type Store interface {
// TouchAccessTokenByID updates the updated time of the given access token to
// the current time.
TouchAccessTokenByID(ctx context.Context, id int64) error
// GetRepositoryByName returns the repository with given owner and name. It
// returns database.ErrRepoNotExist when not found.
GetRepositoryByName(ctx context.Context, ownerID int64, name string) (*database.Repository, error)
}
type store struct{}
@ -32,3 +36,7 @@ func (*store) GetAccessTokenBySHA1(ctx context.Context, sha1 string) (*database.
func (*store) TouchAccessTokenByID(ctx context.Context, id int64) error {
return database.Handle.AccessTokens().Touch(ctx, id)
}
func (*store) GetRepositoryByName(ctx context.Context, ownerID int64, name string) (*database.Repository, error) {
return database.Handle.Repositories().GetByName(ctx, ownerID, name)
}

View File

@ -44,7 +44,7 @@ func TriggerTask(c *macaron.Context) {
return
}
repo, err := database.Repos.GetByName(c.Req.Context(), owner.ID, reponame)
repo, err := database.Handle.Repositories().GetByName(c.Req.Context(), owner.ID, reponame)
if err != nil {
if database.IsErrRepoNotExist(err) {
c.Error(http.StatusBadRequest, "Repository does not exist")

View File

@ -125,7 +125,7 @@ func Dashboard(c *context.Context) {
// Only user can have collaborative repositories.
if !ctxUser.IsOrganization() {
collaborateRepos, err := database.Repos.GetByCollaboratorID(c.Req.Context(), c.User.ID, conf.UI.User.RepoPagingNum, "updated_unix DESC")
collaborateRepos, err := database.Handle.Repositories().GetByCollaboratorID(c.Req.Context(), c.User.ID, conf.UI.User.RepoPagingNum, "updated_unix DESC")
if err != nil {
c.Error(err, "get accessible repositories by collaborator")
return

View File

@ -38,7 +38,6 @@ mocks:
interfaces:
- UsersStore
- TwoFactorsStore
- ReposStore
- path: gogs.io/gogs/internal/route/lfs
interfaces:
- Store