repos.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright 2020 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package db
  5. import (
  6. "fmt"
  7. "strings"
  8. "time"
  9. "gorm.io/gorm"
  10. "gogs.io/gogs/internal/errutil"
  11. )
  12. // ReposStore is the persistent interface for repositories.
  13. //
  14. // NOTE: All methods are sorted in alphabetical order.
  15. type ReposStore interface {
  16. // GetByName returns the repository with given owner and name.
  17. // It returns ErrRepoNotExist when not found.
  18. GetByName(ownerID int64, name string) (*Repository, error)
  19. }
  20. var Repos ReposStore
  21. // NOTE: This is a GORM create hook.
  22. func (r *Repository) BeforeCreate(tx *gorm.DB) error {
  23. if r.CreatedUnix == 0 {
  24. r.CreatedUnix = tx.NowFunc().Unix()
  25. }
  26. return nil
  27. }
  28. // NOTE: This is a GORM update hook.
  29. func (r *Repository) BeforeUpdate(tx *gorm.DB) error {
  30. r.UpdatedUnix = tx.NowFunc().Unix()
  31. return nil
  32. }
  33. // NOTE: This is a GORM query hook.
  34. func (r *Repository) AfterFind(tx *gorm.DB) error {
  35. r.Created = time.Unix(r.CreatedUnix, 0).Local()
  36. r.Updated = time.Unix(r.UpdatedUnix, 0).Local()
  37. return nil
  38. }
  39. var _ ReposStore = (*repos)(nil)
  40. type repos struct {
  41. *gorm.DB
  42. }
  43. type ErrRepoAlreadyExist struct {
  44. args errutil.Args
  45. }
  46. func IsErrRepoAlreadyExist(err error) bool {
  47. _, ok := err.(ErrRepoAlreadyExist)
  48. return ok
  49. }
  50. func (err ErrRepoAlreadyExist) Error() string {
  51. return fmt.Sprintf("repository already exists: %v", err.args)
  52. }
  53. type createRepoOpts struct {
  54. Name string
  55. Description string
  56. DefaultBranch string
  57. Private bool
  58. Mirror bool
  59. EnableWiki bool
  60. EnableIssues bool
  61. EnablePulls bool
  62. Fork bool
  63. ForkID int64
  64. }
  65. // create creates a new repository record in the database. Fields of "repo" will be updated
  66. // in place upon insertion. It returns ErrNameNotAllowed when the repository name is not allowed,
  67. // or ErrRepoAlreadyExist when a repository with same name already exists for the owner.
  68. func (db *repos) create(ownerID int64, opts createRepoOpts) (*Repository, error) {
  69. err := isRepoNameAllowed(opts.Name)
  70. if err != nil {
  71. return nil, err
  72. }
  73. _, err = db.GetByName(ownerID, opts.Name)
  74. if err == nil {
  75. return nil, ErrRepoAlreadyExist{args: errutil.Args{"ownerID": ownerID, "name": opts.Name}}
  76. } else if !IsErrRepoNotExist(err) {
  77. return nil, err
  78. }
  79. repo := &Repository{
  80. OwnerID: ownerID,
  81. LowerName: strings.ToLower(opts.Name),
  82. Name: opts.Name,
  83. Description: opts.Description,
  84. DefaultBranch: opts.DefaultBranch,
  85. IsPrivate: opts.Private,
  86. IsMirror: opts.Mirror,
  87. EnableWiki: opts.EnableWiki,
  88. EnableIssues: opts.EnableIssues,
  89. EnablePulls: opts.EnablePulls,
  90. IsFork: opts.Fork,
  91. ForkID: opts.ForkID,
  92. }
  93. return repo, db.DB.Create(repo).Error
  94. }
  95. var _ errutil.NotFound = (*ErrRepoNotExist)(nil)
  96. type ErrRepoNotExist struct {
  97. args map[string]interface{}
  98. }
  99. func IsErrRepoNotExist(err error) bool {
  100. _, ok := err.(ErrRepoNotExist)
  101. return ok
  102. }
  103. func (err ErrRepoNotExist) Error() string {
  104. return fmt.Sprintf("repository does not exist: %v", err.args)
  105. }
  106. func (ErrRepoNotExist) NotFound() bool {
  107. return true
  108. }
  109. func (db *repos) GetByName(ownerID int64, name string) (*Repository, error) {
  110. repo := new(Repository)
  111. err := db.Where("owner_id = ? AND lower_name = ?", ownerID, strings.ToLower(name)).First(repo).Error
  112. if err != nil {
  113. if err == gorm.ErrRecordNotFound {
  114. return nil, ErrRepoNotExist{args: map[string]interface{}{"ownerID": ownerID, "name": name}}
  115. }
  116. return nil, err
  117. }
  118. return repo, nil
  119. }