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.

repo.go 7.6 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // Copyright 2014 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 repo
  5. import (
  6. "strings"
  7. api "code.gitea.io/sdk/gitea"
  8. "code.gitea.io/gitea/models"
  9. "code.gitea.io/gitea/modules/auth"
  10. "code.gitea.io/gitea/modules/context"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/setting"
  13. "code.gitea.io/gitea/routers/api/v1/convert"
  14. )
  15. // Search repositories via options
  16. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#search-repositories
  17. func Search(ctx *context.APIContext) {
  18. opts := &models.SearchRepoOptions{
  19. Keyword: strings.Trim(ctx.Query("q"), " "),
  20. OwnerID: ctx.QueryInt64("uid"),
  21. PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")),
  22. }
  23. // Check visibility.
  24. if ctx.IsSigned && opts.OwnerID > 0 {
  25. if ctx.User.ID == opts.OwnerID {
  26. opts.Private = true
  27. } else {
  28. u, err := models.GetUserByID(opts.OwnerID)
  29. if err != nil {
  30. ctx.JSON(500, map[string]interface{}{
  31. "ok": false,
  32. "error": err.Error(),
  33. })
  34. return
  35. }
  36. if u.IsOrganization() && u.IsOwnedBy(ctx.User.ID) {
  37. opts.Private = true
  38. }
  39. // FIXME: how about collaborators?
  40. }
  41. }
  42. repos, count, err := models.SearchRepositoryByName(opts)
  43. if err != nil {
  44. ctx.JSON(500, map[string]interface{}{
  45. "ok": false,
  46. "error": err.Error(),
  47. })
  48. return
  49. }
  50. var userID int64
  51. if ctx.IsSigned {
  52. userID = ctx.User.ID
  53. }
  54. results := make([]*api.Repository, len(repos))
  55. for i, repo := range repos {
  56. if err = repo.GetOwner(); err != nil {
  57. ctx.JSON(500, map[string]interface{}{
  58. "ok": false,
  59. "error": err.Error(),
  60. })
  61. return
  62. }
  63. accessMode, err := models.AccessLevel(userID, repo)
  64. if err != nil {
  65. ctx.JSON(500, map[string]interface{}{
  66. "ok": false,
  67. "error": err.Error(),
  68. })
  69. }
  70. results[i] = repo.APIFormat(accessMode)
  71. }
  72. ctx.SetLinkHeader(int(count), setting.API.MaxResponseItems)
  73. ctx.JSON(200, map[string]interface{}{
  74. "ok": true,
  75. "data": results,
  76. })
  77. }
  78. // CreateUserRepo create a repository for a user
  79. func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateRepoOption) {
  80. repo, err := models.CreateRepository(owner, models.CreateRepoOptions{
  81. Name: opt.Name,
  82. Description: opt.Description,
  83. Gitignores: opt.Gitignores,
  84. License: opt.License,
  85. Readme: opt.Readme,
  86. IsPrivate: opt.Private,
  87. AutoInit: opt.AutoInit,
  88. })
  89. if err != nil {
  90. if models.IsErrRepoAlreadyExist(err) ||
  91. models.IsErrNameReserved(err) ||
  92. models.IsErrNamePatternNotAllowed(err) {
  93. ctx.Error(422, "", err)
  94. } else {
  95. if repo != nil {
  96. if err = models.DeleteRepository(ctx.User.ID, repo.ID); err != nil {
  97. log.Error(4, "DeleteRepository: %v", err)
  98. }
  99. }
  100. ctx.Error(500, "CreateRepository", err)
  101. }
  102. return
  103. }
  104. ctx.JSON(201, repo.APIFormat(models.AccessModeOwner))
  105. }
  106. // Create one repository of mine
  107. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#create
  108. func Create(ctx *context.APIContext, opt api.CreateRepoOption) {
  109. // Shouldn't reach this condition, but just in case.
  110. if ctx.User.IsOrganization() {
  111. ctx.Error(422, "", "not allowed creating repository for organization")
  112. return
  113. }
  114. CreateUserRepo(ctx, ctx.User, opt)
  115. }
  116. // CreateOrgRepo create one repository of the organization
  117. func CreateOrgRepo(ctx *context.APIContext, opt api.CreateRepoOption) {
  118. org, err := models.GetOrgByName(ctx.Params(":org"))
  119. if err != nil {
  120. if models.IsErrUserNotExist(err) {
  121. ctx.Error(422, "", err)
  122. } else {
  123. ctx.Error(500, "GetOrgByName", err)
  124. }
  125. return
  126. }
  127. if !org.IsOwnedBy(ctx.User.ID) {
  128. ctx.Error(403, "", "Given user is not owner of organization.")
  129. return
  130. }
  131. CreateUserRepo(ctx, org, opt)
  132. }
  133. // Migrate migrate remote git repository to gitea
  134. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#migrate
  135. func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
  136. ctxUser := ctx.User
  137. // Not equal means context user is an organization,
  138. // or is another user/organization if current user is admin.
  139. if form.UID != ctxUser.ID {
  140. org, err := models.GetUserByID(form.UID)
  141. if err != nil {
  142. if models.IsErrUserNotExist(err) {
  143. ctx.Error(422, "", err)
  144. } else {
  145. ctx.Error(500, "GetUserByID", err)
  146. }
  147. return
  148. }
  149. ctxUser = org
  150. }
  151. if ctx.HasError() {
  152. ctx.Error(422, "", ctx.GetErrMsg())
  153. return
  154. }
  155. if ctxUser.IsOrganization() && !ctx.User.IsAdmin {
  156. // Check ownership of organization.
  157. if !ctxUser.IsOwnedBy(ctx.User.ID) {
  158. ctx.Error(403, "", "Given user is not owner of organization.")
  159. return
  160. }
  161. }
  162. remoteAddr, err := form.ParseRemoteAddr(ctx.User)
  163. if err != nil {
  164. if models.IsErrInvalidCloneAddr(err) {
  165. addrErr := err.(models.ErrInvalidCloneAddr)
  166. switch {
  167. case addrErr.IsURLError:
  168. ctx.Error(422, "", err)
  169. case addrErr.IsPermissionDenied:
  170. ctx.Error(422, "", "You are not allowed to import local repositories.")
  171. case addrErr.IsInvalidPath:
  172. ctx.Error(422, "", "Invalid local path, it does not exist or not a directory.")
  173. default:
  174. ctx.Error(500, "ParseRemoteAddr", "Unknown error type (ErrInvalidCloneAddr): "+err.Error())
  175. }
  176. } else {
  177. ctx.Error(500, "ParseRemoteAddr", err)
  178. }
  179. return
  180. }
  181. repo, err := models.MigrateRepository(ctxUser, models.MigrateRepoOptions{
  182. Name: form.RepoName,
  183. Description: form.Description,
  184. IsPrivate: form.Private || setting.Repository.ForcePrivate,
  185. IsMirror: form.Mirror,
  186. RemoteAddr: remoteAddr,
  187. })
  188. if err != nil {
  189. if repo != nil {
  190. if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil {
  191. log.Error(4, "DeleteRepository: %v", errDelete)
  192. }
  193. }
  194. ctx.Error(500, "MigrateRepository", models.HandleCloneUserCredentials(err.Error(), true))
  195. return
  196. }
  197. log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
  198. ctx.JSON(201, repo.APIFormat(models.AccessModeAdmin))
  199. }
  200. // Get one repository
  201. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#get
  202. func Get(ctx *context.APIContext) {
  203. repo := ctx.Repo.Repository
  204. access, err := models.AccessLevel(ctx.User.ID, repo)
  205. if err != nil {
  206. ctx.Error(500, "GetRepository", err)
  207. return
  208. }
  209. ctx.JSON(200, repo.APIFormat(access))
  210. }
  211. // GetByID returns a single Repository
  212. func GetByID(ctx *context.APIContext) {
  213. repo, err := models.GetRepositoryByID(ctx.ParamsInt64(":id"))
  214. if err != nil {
  215. if models.IsErrRepoNotExist(err) {
  216. ctx.Status(404)
  217. } else {
  218. ctx.Error(500, "GetRepositoryByID", err)
  219. }
  220. return
  221. }
  222. access, err := models.AccessLevel(ctx.User.ID, repo)
  223. if err != nil {
  224. ctx.Error(500, "GetRepositoryByID", err)
  225. return
  226. }
  227. ctx.JSON(200, repo.APIFormat(access))
  228. }
  229. // Delete one repository
  230. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#delete
  231. func Delete(ctx *context.APIContext) {
  232. if !ctx.Repo.IsAdmin() {
  233. ctx.Error(403, "", "Must have admin rights")
  234. return
  235. }
  236. owner := ctx.Repo.Owner
  237. repo := ctx.Repo.Repository
  238. if owner.IsOrganization() && !owner.IsOwnedBy(ctx.User.ID) {
  239. ctx.Error(403, "", "Given user is not owner of organization.")
  240. return
  241. }
  242. if err := models.DeleteRepository(owner.ID, repo.ID); err != nil {
  243. ctx.Error(500, "DeleteRepository", err)
  244. return
  245. }
  246. log.Trace("Repository deleted: %s/%s", owner.Name, repo.Name)
  247. ctx.Status(204)
  248. }
  249. // MirrorSync adds a mirrored repository to the sync queue
  250. func MirrorSync(ctx *context.APIContext) {
  251. repo := ctx.Repo.Repository
  252. if !ctx.Repo.IsWriter() {
  253. ctx.Error(403, "MirrorSync", "Must have write access")
  254. }
  255. go models.MirrorQueue.Add(repo.ID)
  256. ctx.Status(200)
  257. }