You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

update.go 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package repo
  4. import (
  5. "context"
  6. "fmt"
  7. "strings"
  8. "time"
  9. "code.gitea.io/gitea/models/db"
  10. user_model "code.gitea.io/gitea/models/user"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/util"
  13. )
  14. // UpdateRepositoryOwnerNames updates repository owner_names (this should only be used when the ownerName has changed case)
  15. func UpdateRepositoryOwnerNames(ctx context.Context, ownerID int64, ownerName string) error {
  16. if ownerID == 0 {
  17. return nil
  18. }
  19. ctx, committer, err := db.TxContext(ctx)
  20. if err != nil {
  21. return err
  22. }
  23. defer committer.Close()
  24. if _, err := db.GetEngine(ctx).Where("owner_id = ?", ownerID).Cols("owner_name").Update(&Repository{
  25. OwnerName: ownerName,
  26. }); err != nil {
  27. return err
  28. }
  29. return committer.Commit()
  30. }
  31. // UpdateRepositoryUpdatedTime updates a repository's updated time
  32. func UpdateRepositoryUpdatedTime(ctx context.Context, repoID int64, updateTime time.Time) error {
  33. _, err := db.GetEngine(ctx).Exec("UPDATE repository SET updated_unix = ? WHERE id = ?", updateTime.Unix(), repoID)
  34. return err
  35. }
  36. // UpdateRepositoryCols updates repository's columns
  37. func UpdateRepositoryCols(ctx context.Context, repo *Repository, cols ...string) error {
  38. _, err := db.GetEngine(ctx).ID(repo.ID).Cols(cols...).Update(repo)
  39. return err
  40. }
  41. // ErrReachLimitOfRepo represents a "ReachLimitOfRepo" kind of error.
  42. type ErrReachLimitOfRepo struct {
  43. Limit int
  44. }
  45. // IsErrReachLimitOfRepo checks if an error is a ErrReachLimitOfRepo.
  46. func IsErrReachLimitOfRepo(err error) bool {
  47. _, ok := err.(ErrReachLimitOfRepo)
  48. return ok
  49. }
  50. func (err ErrReachLimitOfRepo) Error() string {
  51. return fmt.Sprintf("user has reached maximum limit of repositories [limit: %d]", err.Limit)
  52. }
  53. func (err ErrReachLimitOfRepo) Unwrap() error {
  54. return util.ErrPermissionDenied
  55. }
  56. // ErrRepoAlreadyExist represents a "RepoAlreadyExist" kind of error.
  57. type ErrRepoAlreadyExist struct {
  58. Uname string
  59. Name string
  60. }
  61. // IsErrRepoAlreadyExist checks if an error is a ErrRepoAlreadyExist.
  62. func IsErrRepoAlreadyExist(err error) bool {
  63. _, ok := err.(ErrRepoAlreadyExist)
  64. return ok
  65. }
  66. func (err ErrRepoAlreadyExist) Error() string {
  67. return fmt.Sprintf("repository already exists [uname: %s, name: %s]", err.Uname, err.Name)
  68. }
  69. func (err ErrRepoAlreadyExist) Unwrap() error {
  70. return util.ErrAlreadyExist
  71. }
  72. // ErrRepoFilesAlreadyExist represents a "RepoFilesAlreadyExist" kind of error.
  73. type ErrRepoFilesAlreadyExist struct {
  74. Uname string
  75. Name string
  76. }
  77. // IsErrRepoFilesAlreadyExist checks if an error is a ErrRepoAlreadyExist.
  78. func IsErrRepoFilesAlreadyExist(err error) bool {
  79. _, ok := err.(ErrRepoFilesAlreadyExist)
  80. return ok
  81. }
  82. func (err ErrRepoFilesAlreadyExist) Error() string {
  83. return fmt.Sprintf("repository files already exist [uname: %s, name: %s]", err.Uname, err.Name)
  84. }
  85. func (err ErrRepoFilesAlreadyExist) Unwrap() error {
  86. return util.ErrAlreadyExist
  87. }
  88. // CheckCreateRepository check if could created a repository
  89. func CheckCreateRepository(ctx context.Context, doer, u *user_model.User, name string, overwriteOrAdopt bool) error {
  90. if !doer.CanCreateRepo() {
  91. return ErrReachLimitOfRepo{u.MaxRepoCreation}
  92. }
  93. if err := IsUsableRepoName(name); err != nil {
  94. return err
  95. }
  96. has, err := IsRepositoryModelOrDirExist(ctx, u, name)
  97. if err != nil {
  98. return fmt.Errorf("IsRepositoryExist: %w", err)
  99. } else if has {
  100. return ErrRepoAlreadyExist{u.Name, name}
  101. }
  102. repoPath := RepoPath(u.Name, name)
  103. isExist, err := util.IsExist(repoPath)
  104. if err != nil {
  105. log.Error("Unable to check if %s exists. Error: %v", repoPath, err)
  106. return err
  107. }
  108. if !overwriteOrAdopt && isExist {
  109. return ErrRepoFilesAlreadyExist{u.Name, name}
  110. }
  111. return nil
  112. }
  113. // ChangeRepositoryName changes all corresponding setting from old repository name to new one.
  114. func ChangeRepositoryName(ctx context.Context, doer *user_model.User, repo *Repository, newRepoName string) (err error) {
  115. oldRepoName := repo.Name
  116. newRepoName = strings.ToLower(newRepoName)
  117. if err = IsUsableRepoName(newRepoName); err != nil {
  118. return err
  119. }
  120. if err := repo.LoadOwner(ctx); err != nil {
  121. return err
  122. }
  123. has, err := IsRepositoryModelOrDirExist(ctx, repo.Owner, newRepoName)
  124. if err != nil {
  125. return fmt.Errorf("IsRepositoryExist: %w", err)
  126. } else if has {
  127. return ErrRepoAlreadyExist{repo.Owner.Name, newRepoName}
  128. }
  129. newRepoPath := RepoPath(repo.Owner.Name, newRepoName)
  130. if err = util.Rename(repo.RepoPath(), newRepoPath); err != nil {
  131. return fmt.Errorf("rename repository directory: %w", err)
  132. }
  133. wikiPath := repo.WikiPath()
  134. isExist, err := util.IsExist(wikiPath)
  135. if err != nil {
  136. log.Error("Unable to check if %s exists. Error: %v", wikiPath, err)
  137. return err
  138. }
  139. if isExist {
  140. if err = util.Rename(wikiPath, WikiPath(repo.Owner.Name, newRepoName)); err != nil {
  141. return fmt.Errorf("rename repository wiki: %w", err)
  142. }
  143. }
  144. ctx, committer, err := db.TxContext(ctx)
  145. if err != nil {
  146. return err
  147. }
  148. defer committer.Close()
  149. if err := NewRedirect(ctx, repo.Owner.ID, repo.ID, oldRepoName, newRepoName); err != nil {
  150. return err
  151. }
  152. return committer.Commit()
  153. }
  154. // UpdateRepoSize updates the repository size, calculating it using getDirectorySize
  155. func UpdateRepoSize(ctx context.Context, repoID, gitSize, lfsSize int64) error {
  156. _, err := db.GetEngine(ctx).ID(repoID).Cols("size", "git_size", "lfs_size").NoAutoTime().Update(&Repository{
  157. Size: gitSize + lfsSize,
  158. GitSize: gitSize,
  159. LFSSize: lfsSize,
  160. })
  161. return err
  162. }