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

repository.go 8.0 kB

3 years ago
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. // Copyright 2019 The Gitea 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 repository
  5. import (
  6. "fmt"
  7. "io/ioutil"
  8. "net/http"
  9. "os"
  10. "strings"
  11. "code.gitea.io/gitea/models"
  12. "code.gitea.io/gitea/modules/log"
  13. "code.gitea.io/gitea/modules/notification"
  14. repo_module "code.gitea.io/gitea/modules/repository"
  15. "code.gitea.io/gitea/modules/setting"
  16. pull_service "code.gitea.io/gitea/services/pull"
  17. )
  18. // CreateRepository creates a repository for the user/organization.
  19. func CreateRepository(doer, owner *models.User, opts models.CreateRepoOptions) (*models.Repository, error) {
  20. repo, err := repo_module.CreateRepository(doer, owner, opts)
  21. if err != nil {
  22. if repo != nil {
  23. if errDelete := models.DeleteRepository(doer, owner.ID, repo.ID); errDelete != nil {
  24. log.Error("Rollback deleteRepository: %v", errDelete)
  25. }
  26. }
  27. return nil, err
  28. }
  29. notification.NotifyCreateRepository(doer, owner, repo)
  30. return repo, nil
  31. }
  32. // ForkRepository forks a repository
  33. func ForkRepository(doer, u *models.User, oldRepo *models.Repository, name, desc, alias string) (*models.Repository, error) {
  34. repo, err := repo_module.ForkRepository(doer, u, oldRepo, name, desc, alias)
  35. if err != nil {
  36. if repo != nil {
  37. if errDelete := models.DeleteRepository(doer, u.ID, repo.ID); errDelete != nil {
  38. log.Error("Rollback deleteRepository: %v", errDelete)
  39. }
  40. }
  41. return nil, err
  42. }
  43. notification.NotifyForkRepository(doer, oldRepo, repo)
  44. return repo, nil
  45. }
  46. // DeleteRepository deletes a repository for a user or organization.
  47. func DeleteRepository(doer *models.User, repo *models.Repository) error {
  48. if err := pull_service.CloseRepoBranchesPulls(doer, repo); err != nil {
  49. log.Error("CloseRepoBranchesPulls failed: %v", err)
  50. }
  51. if err := models.DeleteRepository(doer, repo.OwnerID, repo.ID); err != nil {
  52. return err
  53. }
  54. notification.NotifyDeleteRepository(doer, repo)
  55. return nil
  56. }
  57. // PushCreateRepo creates a repository when a new repository is pushed to an appropriate namespace
  58. func PushCreateRepo(authUser, owner *models.User, repoName string) (*models.Repository, error) {
  59. if !authUser.IsAdmin {
  60. if owner.IsOrganization() {
  61. if ok, err := owner.CanCreateOrgRepo(authUser.ID); err != nil {
  62. return nil, err
  63. } else if !ok {
  64. return nil, fmt.Errorf("cannot push-create repository for org")
  65. }
  66. } else if authUser.ID != owner.ID {
  67. return nil, fmt.Errorf("cannot push-create repository for another user")
  68. }
  69. }
  70. repo, err := CreateRepository(authUser, owner, models.CreateRepoOptions{
  71. Name: repoName,
  72. IsPrivate: true,
  73. })
  74. if err != nil {
  75. return nil, err
  76. }
  77. return repo, nil
  78. }
  79. func GetRecommendCourseKeyWords() ([]string, error) {
  80. url := setting.RecommentRepoAddr + "course_keywords"
  81. result, err := RecommendFromPromote(url)
  82. if err != nil {
  83. return []string{}, err
  84. }
  85. return result, err
  86. }
  87. func GetRecommendRepoFromPromote(filename string) ([]map[string]interface{}, error) {
  88. resultRepo := make([]map[string]interface{}, 0)
  89. url := setting.RecommentRepoAddr + filename
  90. result, err := RecommendFromPromote(url)
  91. if err != nil {
  92. return resultRepo, err
  93. }
  94. //resultRepo := make([]*models.Repository, 0)
  95. for _, repoName := range result {
  96. tmpIndex := strings.Index(repoName, "/")
  97. if tmpIndex == -1 {
  98. log.Info("error repo name format.")
  99. } else {
  100. ownerName := strings.Trim(repoName[0:tmpIndex], " ")
  101. repoName := strings.Trim(repoName[tmpIndex+1:], " ")
  102. repo, err := models.GetRepositoryByOwnerAndAlias(ownerName, repoName)
  103. if err == nil {
  104. repoMap := make(map[string]interface{})
  105. repoMap["ID"] = fmt.Sprint(repo.ID)
  106. repoMap["Name"] = repo.Name
  107. repoMap["Alias"] = repo.Alias
  108. if repo.RepoType == models.RepoCourse {
  109. //Load creator
  110. repo.GetCreator()
  111. repoMap["Creator"] = repo.Creator
  112. }
  113. repoMap["OwnerName"] = repo.OwnerName
  114. repoMap["NumStars"] = repo.NumStars
  115. repoMap["NumForks"] = repo.NumForks
  116. repoMap["Description"] = repo.Description
  117. repoMap["NumWatchs"] = repo.NumWatches
  118. repoMap["Topics"] = repo.Topics
  119. repoMap["Avatar"] = repo.RelAvatarLink()
  120. resultRepo = append(resultRepo, repoMap)
  121. } else {
  122. log.Info("query repo error," + err.Error())
  123. }
  124. }
  125. }
  126. return resultRepo, nil
  127. }
  128. func RecommendFromPromote(url string) ([]string, error) {
  129. resp, err := http.Get(url)
  130. if err != nil || resp.StatusCode != 200 {
  131. log.Info("Get organizations url error=" + err.Error())
  132. return nil, err
  133. }
  134. bytes, err := ioutil.ReadAll(resp.Body)
  135. resp.Body.Close()
  136. if err != nil {
  137. log.Info("Get organizations url error=" + err.Error())
  138. return nil, err
  139. }
  140. allLineStr := string(bytes)
  141. lines := strings.Split(allLineStr, "\n")
  142. result := make([]string, len(lines))
  143. for i, line := range lines {
  144. log.Info("i=" + fmt.Sprint(i) + " line=" + line)
  145. result[i] = strings.Trim(line, " ")
  146. }
  147. return result, nil
  148. }
  149. func CheckPushSizeLimit4Web(repo *models.Repository, fileIds []string) error {
  150. if err := CheckRepoNumOnceLimit(len(fileIds)); err != nil {
  151. return err
  152. }
  153. totalSize, err := CountUploadFileSizeByIds(fileIds)
  154. if err != nil {
  155. return UploadFileInvalidErr{}
  156. }
  157. if err := CheckRepoTotalSizeLimit(repo, totalSize); err != nil {
  158. return err
  159. }
  160. return nil
  161. }
  162. func CheckPushSizeLimit4Http(repo *models.Repository, uploadFileSize int64) error {
  163. if err := CheckRepoOnceTotalSizeLimit(uploadFileSize); err != nil {
  164. return err
  165. }
  166. if err := CheckRepoTotalSizeLimit(repo, uploadFileSize); err != nil {
  167. return err
  168. }
  169. return nil
  170. }
  171. func CheckRepoTotalSizeLimit(repo *models.Repository, uploadFileSize int64) error {
  172. if repo.Size+uploadFileSize > setting.Repository.RepoMaxSize*1024*1024 {
  173. return RepoTooLargeErr{}
  174. }
  175. return nil
  176. }
  177. func CheckRepoOnceTotalSizeLimit(uploadFileSize int64) error {
  178. if uploadFileSize > setting.Repository.Upload.TotalMaxSize*1024*1024 {
  179. return UploadFileTooLargeErr{}
  180. }
  181. return nil
  182. }
  183. func CheckRepoNumOnceLimit(uploadFileNum int) error {
  184. if uploadFileNum > setting.Repository.Upload.MaxFiles {
  185. return UploadFileTooMuchErr{}
  186. }
  187. return nil
  188. }
  189. func CountUploadFileSizeByIds(fileIds []string) (int64, error) {
  190. if len(fileIds) == 0 {
  191. return 0, nil
  192. }
  193. uploads, err := models.GetUploadsByUUIDs(fileIds)
  194. if err != nil {
  195. return 0, fmt.Errorf("CountUploadFileSizeByIds error [uuids: %v]: %v", fileIds, err)
  196. }
  197. var totalSize int64
  198. for _, upload := range uploads {
  199. size, err := GetUploadFileSize(upload)
  200. if err != nil {
  201. return 0, err
  202. }
  203. totalSize += size
  204. }
  205. return totalSize, nil
  206. }
  207. func GetUploadFileSize(upload *models.Upload) (int64, error) {
  208. info, err := os.Lstat(upload.LocalPath())
  209. if err != nil {
  210. return 0, err
  211. }
  212. return info.Size(), nil
  213. }
  214. type RepoTooLargeErr struct {
  215. }
  216. func (RepoTooLargeErr) Error() string {
  217. return fmt.Sprintf("Repository can not exceed %d MB. Please remove some unnecessary files and try again", setting.Repository.RepoMaxSize)
  218. }
  219. func IsRepoTooLargeErr(err error) bool {
  220. _, ok := err.(RepoTooLargeErr)
  221. return ok
  222. }
  223. type UploadFileTooLargeErr struct {
  224. }
  225. func (UploadFileTooLargeErr) Error() string {
  226. return fmt.Sprintf("Upload files can not exceed %d MB at a time", setting.Repository.Upload.TotalMaxSize)
  227. }
  228. func IsUploadFileTooLargeErr(err error) bool {
  229. _, ok := err.(UploadFileTooLargeErr)
  230. return ok
  231. }
  232. type RepoFileTooLargeErr struct {
  233. }
  234. func (RepoFileTooLargeErr) Error() string {
  235. return "repository file is too large"
  236. }
  237. func IsRepoFileTooLargeErr(err error) bool {
  238. _, ok := err.(RepoFileTooLargeErr)
  239. return ok
  240. }
  241. type UploadFileTooMuchErr struct {
  242. }
  243. func (UploadFileTooMuchErr) Error() string {
  244. return "upload files are too lmuch"
  245. }
  246. func IsUploadFileTooMuchErr(err error) bool {
  247. _, ok := err.(UploadFileTooMuchErr)
  248. return ok
  249. }
  250. type UploadFileInvalidErr struct {
  251. }
  252. func (UploadFileInvalidErr) Error() string {
  253. return "upload files are invalid"
  254. }
  255. func IsUploadFileInvalidErr(err error) bool {
  256. _, ok := err.(UploadFileInvalidErr)
  257. return ok
  258. }