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.5 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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. "path"
  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: path.Base(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. results := make([]*api.Repository, len(repos))
  51. for i := range repos {
  52. if err = repos[i].GetOwner(); err != nil {
  53. ctx.JSON(500, map[string]interface{}{
  54. "ok": false,
  55. "error": err.Error(),
  56. })
  57. return
  58. }
  59. results[i] = &api.Repository{
  60. ID: repos[i].ID,
  61. FullName: path.Join(repos[i].Owner.Name, repos[i].Name),
  62. }
  63. }
  64. ctx.SetLinkHeader(int(count), setting.API.MaxResponseItems)
  65. ctx.JSON(200, map[string]interface{}{
  66. "ok": true,
  67. "data": results,
  68. })
  69. }
  70. // ListMyRepos list all my repositories
  71. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#list-your-repositories
  72. func ListMyRepos(ctx *context.APIContext) {
  73. ownRepos, err := models.GetUserRepositories(ctx.User.ID, true, 1, ctx.User.NumRepos)
  74. if err != nil {
  75. ctx.Error(500, "GetRepositories", err)
  76. return
  77. }
  78. numOwnRepos := len(ownRepos)
  79. accessibleRepos, err := ctx.User.GetRepositoryAccesses()
  80. if err != nil {
  81. ctx.Error(500, "GetRepositoryAccesses", err)
  82. return
  83. }
  84. repos := make([]*api.Repository, numOwnRepos+len(accessibleRepos))
  85. for i := range ownRepos {
  86. repos[i] = ownRepos[i].APIFormat(&api.Permission{true, true, true})
  87. }
  88. i := numOwnRepos
  89. for repo, access := range accessibleRepos {
  90. repos[i] = repo.APIFormat(&api.Permission{
  91. Admin: access >= models.AccessModeAdmin,
  92. Push: access >= models.AccessModeWrite,
  93. Pull: true,
  94. })
  95. i++
  96. }
  97. ctx.JSON(200, &repos)
  98. }
  99. // CreateUserRepo create a repository for a user
  100. func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateRepoOption) {
  101. repo, err := models.CreateRepository(owner, models.CreateRepoOptions{
  102. Name: opt.Name,
  103. Description: opt.Description,
  104. Gitignores: opt.Gitignores,
  105. License: opt.License,
  106. Readme: opt.Readme,
  107. IsPrivate: opt.Private,
  108. AutoInit: opt.AutoInit,
  109. })
  110. if err != nil {
  111. if models.IsErrRepoAlreadyExist(err) ||
  112. models.IsErrNameReserved(err) ||
  113. models.IsErrNamePatternNotAllowed(err) {
  114. ctx.Error(422, "", err)
  115. } else {
  116. if repo != nil {
  117. if err = models.DeleteRepository(ctx.User.ID, repo.ID); err != nil {
  118. log.Error(4, "DeleteRepository: %v", err)
  119. }
  120. }
  121. ctx.Error(500, "CreateRepository", err)
  122. }
  123. return
  124. }
  125. ctx.JSON(201, repo.APIFormat(&api.Permission{true, true, true}))
  126. }
  127. // Create create one repository of mine
  128. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#create
  129. func Create(ctx *context.APIContext, opt api.CreateRepoOption) {
  130. // Shouldn't reach this condition, but just in case.
  131. if ctx.User.IsOrganization() {
  132. ctx.Error(422, "", "not allowed creating repository for organization")
  133. return
  134. }
  135. CreateUserRepo(ctx, ctx.User, opt)
  136. }
  137. // CreateOrgRepo create one repository of the organization
  138. func CreateOrgRepo(ctx *context.APIContext, opt api.CreateRepoOption) {
  139. org, err := models.GetOrgByName(ctx.Params(":org"))
  140. if err != nil {
  141. if models.IsErrUserNotExist(err) {
  142. ctx.Error(422, "", err)
  143. } else {
  144. ctx.Error(500, "GetOrgByName", err)
  145. }
  146. return
  147. }
  148. if !org.IsOwnedBy(ctx.User.ID) {
  149. ctx.Error(403, "", "Given user is not owner of organization.")
  150. return
  151. }
  152. CreateUserRepo(ctx, org, opt)
  153. }
  154. // Migrate migrate remote git repository to gitea
  155. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#migrate
  156. func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
  157. ctxUser := ctx.User
  158. // Not equal means context user is an organization,
  159. // or is another user/organization if current user is admin.
  160. if form.UID != ctxUser.ID {
  161. org, err := models.GetUserByID(form.UID)
  162. if err != nil {
  163. if models.IsErrUserNotExist(err) {
  164. ctx.Error(422, "", err)
  165. } else {
  166. ctx.Error(500, "GetUserByID", err)
  167. }
  168. return
  169. }
  170. ctxUser = org
  171. }
  172. if ctx.HasError() {
  173. ctx.Error(422, "", ctx.GetErrMsg())
  174. return
  175. }
  176. if ctxUser.IsOrganization() && !ctx.User.IsAdmin {
  177. // Check ownership of organization.
  178. if !ctxUser.IsOwnedBy(ctx.User.ID) {
  179. ctx.Error(403, "", "Given user is not owner of organization.")
  180. return
  181. }
  182. }
  183. remoteAddr, err := form.ParseRemoteAddr(ctx.User)
  184. if err != nil {
  185. if models.IsErrInvalidCloneAddr(err) {
  186. addrErr := err.(models.ErrInvalidCloneAddr)
  187. switch {
  188. case addrErr.IsURLError:
  189. ctx.Error(422, "", err)
  190. case addrErr.IsPermissionDenied:
  191. ctx.Error(422, "", "You are not allowed to import local repositories.")
  192. case addrErr.IsInvalidPath:
  193. ctx.Error(422, "", "Invalid local path, it does not exist or not a directory.")
  194. default:
  195. ctx.Error(500, "ParseRemoteAddr", "Unknown error type (ErrInvalidCloneAddr): "+err.Error())
  196. }
  197. } else {
  198. ctx.Error(500, "ParseRemoteAddr", err)
  199. }
  200. return
  201. }
  202. repo, err := models.MigrateRepository(ctxUser, models.MigrateRepoOptions{
  203. Name: form.RepoName,
  204. Description: form.Description,
  205. IsPrivate: form.Private || setting.Repository.ForcePrivate,
  206. IsMirror: form.Mirror,
  207. RemoteAddr: remoteAddr,
  208. })
  209. if err != nil {
  210. if repo != nil {
  211. if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil {
  212. log.Error(4, "DeleteRepository: %v", errDelete)
  213. }
  214. }
  215. ctx.Error(500, "MigrateRepository", models.HandleCloneUserCredentials(err.Error(), true))
  216. return
  217. }
  218. log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
  219. ctx.JSON(201, repo.APIFormat(&api.Permission{true, true, true}))
  220. }
  221. // Get get one repository
  222. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#get
  223. func Get(ctx *context.APIContext) {
  224. repo := ctx.Repo.Repository
  225. ctx.JSON(200, repo.APIFormat(&api.Permission{true, true, true}))
  226. }
  227. // Delete delete one repository
  228. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#delete
  229. func Delete(ctx *context.APIContext) {
  230. owner := ctx.Repo.Owner
  231. repo := ctx.Repo.Repository
  232. if owner.IsOrganization() && !owner.IsOwnedBy(ctx.User.ID) {
  233. ctx.Error(403, "", "Given user is not owner of organization.")
  234. return
  235. }
  236. if err := models.DeleteRepository(owner.ID, repo.ID); err != nil {
  237. ctx.Error(500, "DeleteRepository", err)
  238. return
  239. }
  240. log.Trace("Repository deleted: %s/%s", owner.Name, repo.Name)
  241. ctx.Status(204)
  242. }