| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 | 
							- // Copyright 2020 The Gogs 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 db
 
- import (
 
- 	"context"
 
- 	"fmt"
 
- 	"strings"
 
- 	"time"
 
- 	api "github.com/gogs/go-gogs-client"
 
- 	"gorm.io/gorm"
 
- 	"gogs.io/gogs/internal/errutil"
 
- 	"gogs.io/gogs/internal/repoutil"
 
- )
 
- // ReposStore is the persistent interface for repositories.
 
- //
 
- // NOTE: All methods are sorted in alphabetical order.
 
- 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)
 
- 	// 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)
 
- 	// 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
 
- }
 
- var Repos ReposStore
 
- // BeforeCreate implements the GORM create hook.
 
- func (r *Repository) BeforeCreate(tx *gorm.DB) error {
 
- 	if r.CreatedUnix == 0 {
 
- 		r.CreatedUnix = tx.NowFunc().Unix()
 
- 	}
 
- 	return nil
 
- }
 
- // BeforeUpdate implements the GORM update hook.
 
- func (r *Repository) BeforeUpdate(tx *gorm.DB) error {
 
- 	r.UpdatedUnix = tx.NowFunc().Unix()
 
- 	return nil
 
- }
 
- // AfterFind implements the GORM query hook.
 
- func (r *Repository) AfterFind(_ *gorm.DB) error {
 
- 	r.Created = time.Unix(r.CreatedUnix, 0).Local()
 
- 	r.Updated = time.Unix(r.UpdatedUnix, 0).Local()
 
- 	return nil
 
- }
 
- type RepositoryAPIFormatOptions struct {
 
- 	Permission *api.Permission
 
- 	Parent     *api.Repository
 
- }
 
- // APIFormat returns the API format of a repository.
 
- func (r *Repository) APIFormat(owner *User, opts ...RepositoryAPIFormatOptions) *api.Repository {
 
- 	var opt RepositoryAPIFormatOptions
 
- 	if len(opts) > 0 {
 
- 		opt = opts[0]
 
- 	}
 
- 	cloneLink := repoutil.NewCloneLink(owner.Name, r.Name, false)
 
- 	return &api.Repository{
 
- 		ID:            r.ID,
 
- 		Owner:         owner.APIFormat(),
 
- 		Name:          r.Name,
 
- 		FullName:      owner.Name + "/" + r.Name,
 
- 		Description:   r.Description,
 
- 		Private:       r.IsPrivate,
 
- 		Fork:          r.IsFork,
 
- 		Parent:        opt.Parent,
 
- 		Empty:         r.IsBare,
 
- 		Mirror:        r.IsMirror,
 
- 		Size:          r.Size,
 
- 		HTMLURL:       repoutil.HTMLURL(owner.Name, r.Name),
 
- 		SSHURL:        cloneLink.SSH,
 
- 		CloneURL:      cloneLink.HTTPS,
 
- 		Website:       r.Website,
 
- 		Stars:         r.NumStars,
 
- 		Forks:         r.NumForks,
 
- 		Watchers:      r.NumWatches,
 
- 		OpenIssues:    r.NumOpenIssues,
 
- 		DefaultBranch: r.DefaultBranch,
 
- 		Created:       r.Created,
 
- 		Updated:       r.Updated,
 
- 		Permissions:   opt.Permission,
 
- 	}
 
- }
 
- var _ ReposStore = (*repos)(nil)
 
- type repos struct {
 
- 	*gorm.DB
 
- }
 
- // NewReposStore returns a persistent interface for repositories with given
 
- // database connection.
 
- func NewReposStore(db *gorm.DB) ReposStore {
 
- 	return &repos{DB: db}
 
- }
 
- type ErrRepoAlreadyExist struct {
 
- 	args errutil.Args
 
- }
 
- func IsErrRepoAlreadyExist(err error) bool {
 
- 	_, ok := err.(ErrRepoAlreadyExist)
 
- 	return ok
 
- }
 
- func (err ErrRepoAlreadyExist) Error() string {
 
- 	return fmt.Sprintf("repository already exists: %v", err.args)
 
- }
 
- type CreateRepoOptions struct {
 
- 	Name          string
 
- 	Description   string
 
- 	DefaultBranch string
 
- 	Private       bool
 
- 	Mirror        bool
 
- 	EnableWiki    bool
 
- 	EnableIssues  bool
 
- 	EnablePulls   bool
 
- 	Fork          bool
 
- 	ForkID        int64
 
- }
 
- func (db *repos) Create(ctx context.Context, ownerID int64, opts CreateRepoOptions) (*Repository, error) {
 
- 	err := isRepoNameAllowed(opts.Name)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	_, err = db.GetByName(ctx, ownerID, opts.Name)
 
- 	if err == nil {
 
- 		return nil, ErrRepoAlreadyExist{
 
- 			args: errutil.Args{
 
- 				"ownerID": ownerID,
 
- 				"name":    opts.Name,
 
- 			},
 
- 		}
 
- 	} else if !IsErrRepoNotExist(err) {
 
- 		return nil, err
 
- 	}
 
- 	repo := &Repository{
 
- 		OwnerID:       ownerID,
 
- 		LowerName:     strings.ToLower(opts.Name),
 
- 		Name:          opts.Name,
 
- 		Description:   opts.Description,
 
- 		DefaultBranch: opts.DefaultBranch,
 
- 		IsPrivate:     opts.Private,
 
- 		IsMirror:      opts.Mirror,
 
- 		EnableWiki:    opts.EnableWiki,
 
- 		EnableIssues:  opts.EnableIssues,
 
- 		EnablePulls:   opts.EnablePulls,
 
- 		IsFork:        opts.Fork,
 
- 		ForkID:        opts.ForkID,
 
- 	}
 
- 	return repo, db.WithContext(ctx).Create(repo).Error
 
- }
 
- var _ errutil.NotFound = (*ErrRepoNotExist)(nil)
 
- type ErrRepoNotExist struct {
 
- 	args errutil.Args
 
- }
 
- func IsErrRepoNotExist(err error) bool {
 
- 	_, ok := err.(ErrRepoNotExist)
 
- 	return ok
 
- }
 
- func (err ErrRepoNotExist) Error() string {
 
- 	return fmt.Sprintf("repository does not exist: %v", err.args)
 
- }
 
- func (ErrRepoNotExist) NotFound() bool {
 
- 	return true
 
- }
 
- func (db *repos) GetByName(ctx context.Context, ownerID int64, name string) (*Repository, error) {
 
- 	repo := new(Repository)
 
- 	err := db.WithContext(ctx).
 
- 		Where("owner_id = ? AND lower_name = ?", ownerID, strings.ToLower(name)).
 
- 		First(repo).
 
- 		Error
 
- 	if err != nil {
 
- 		if err == gorm.ErrRecordNotFound {
 
- 			return nil, ErrRepoNotExist{
 
- 				args: errutil.Args{
 
- 					"ownerID": ownerID,
 
- 					"name":    name,
 
- 				},
 
- 			}
 
- 		}
 
- 		return nil, err
 
- 	}
 
- 	return repo, nil
 
- }
 
- func (db *repos) Touch(ctx context.Context, id int64) error {
 
- 	return db.WithContext(ctx).
 
- 		Model(new(Repository)).
 
- 		Where("id = ?", id).
 
- 		Updates(map[string]interface{}{
 
- 			"is_bare":      false,
 
- 			"updated_unix": db.NowFunc().Unix(),
 
- 		}).
 
- 		Error
 
- }
 
 
  |