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 8.0 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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(models.AccessModeOwner)
  87. }
  88. i := numOwnRepos
  89. for repo, access := range accessibleRepos {
  90. repos[i] = repo.APIFormat(access)
  91. i++
  92. }
  93. ctx.JSON(200, &repos)
  94. }
  95. // CreateUserRepo create a repository for a user
  96. func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateRepoOption) {
  97. repo, err := models.CreateRepository(owner, models.CreateRepoOptions{
  98. Name: opt.Name,
  99. Description: opt.Description,
  100. Gitignores: opt.Gitignores,
  101. License: opt.License,
  102. Readme: opt.Readme,
  103. IsPrivate: opt.Private,
  104. AutoInit: opt.AutoInit,
  105. })
  106. if err != nil {
  107. if models.IsErrRepoAlreadyExist(err) ||
  108. models.IsErrNameReserved(err) ||
  109. models.IsErrNamePatternNotAllowed(err) {
  110. ctx.Error(422, "", err)
  111. } else {
  112. if repo != nil {
  113. if err = models.DeleteRepository(ctx.User.ID, repo.ID); err != nil {
  114. log.Error(4, "DeleteRepository: %v", err)
  115. }
  116. }
  117. ctx.Error(500, "CreateRepository", err)
  118. }
  119. return
  120. }
  121. ctx.JSON(201, repo.APIFormat(models.AccessModeOwner))
  122. }
  123. // Create one repository of mine
  124. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#create
  125. func Create(ctx *context.APIContext, opt api.CreateRepoOption) {
  126. // Shouldn't reach this condition, but just in case.
  127. if ctx.User.IsOrganization() {
  128. ctx.Error(422, "", "not allowed creating repository for organization")
  129. return
  130. }
  131. CreateUserRepo(ctx, ctx.User, opt)
  132. }
  133. // CreateOrgRepo create one repository of the organization
  134. func CreateOrgRepo(ctx *context.APIContext, opt api.CreateRepoOption) {
  135. org, err := models.GetOrgByName(ctx.Params(":org"))
  136. if err != nil {
  137. if models.IsErrUserNotExist(err) {
  138. ctx.Error(422, "", err)
  139. } else {
  140. ctx.Error(500, "GetOrgByName", err)
  141. }
  142. return
  143. }
  144. if !org.IsOwnedBy(ctx.User.ID) {
  145. ctx.Error(403, "", "Given user is not owner of organization.")
  146. return
  147. }
  148. CreateUserRepo(ctx, org, opt)
  149. }
  150. // Migrate migrate remote git repository to gitea
  151. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#migrate
  152. func Migrate(ctx *context.APIContext, form auth.MigrateRepoForm) {
  153. ctxUser := ctx.User
  154. // Not equal means context user is an organization,
  155. // or is another user/organization if current user is admin.
  156. if form.UID != ctxUser.ID {
  157. org, err := models.GetUserByID(form.UID)
  158. if err != nil {
  159. if models.IsErrUserNotExist(err) {
  160. ctx.Error(422, "", err)
  161. } else {
  162. ctx.Error(500, "GetUserByID", err)
  163. }
  164. return
  165. }
  166. ctxUser = org
  167. }
  168. if ctx.HasError() {
  169. ctx.Error(422, "", ctx.GetErrMsg())
  170. return
  171. }
  172. if ctxUser.IsOrganization() && !ctx.User.IsAdmin {
  173. // Check ownership of organization.
  174. if !ctxUser.IsOwnedBy(ctx.User.ID) {
  175. ctx.Error(403, "", "Given user is not owner of organization.")
  176. return
  177. }
  178. }
  179. remoteAddr, err := form.ParseRemoteAddr(ctx.User)
  180. if err != nil {
  181. if models.IsErrInvalidCloneAddr(err) {
  182. addrErr := err.(models.ErrInvalidCloneAddr)
  183. switch {
  184. case addrErr.IsURLError:
  185. ctx.Error(422, "", err)
  186. case addrErr.IsPermissionDenied:
  187. ctx.Error(422, "", "You are not allowed to import local repositories.")
  188. case addrErr.IsInvalidPath:
  189. ctx.Error(422, "", "Invalid local path, it does not exist or not a directory.")
  190. default:
  191. ctx.Error(500, "ParseRemoteAddr", "Unknown error type (ErrInvalidCloneAddr): "+err.Error())
  192. }
  193. } else {
  194. ctx.Error(500, "ParseRemoteAddr", err)
  195. }
  196. return
  197. }
  198. repo, err := models.MigrateRepository(ctxUser, models.MigrateRepoOptions{
  199. Name: form.RepoName,
  200. Description: form.Description,
  201. IsPrivate: form.Private || setting.Repository.ForcePrivate,
  202. IsMirror: form.Mirror,
  203. RemoteAddr: remoteAddr,
  204. })
  205. if err != nil {
  206. if repo != nil {
  207. if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil {
  208. log.Error(4, "DeleteRepository: %v", errDelete)
  209. }
  210. }
  211. ctx.Error(500, "MigrateRepository", models.HandleCloneUserCredentials(err.Error(), true))
  212. return
  213. }
  214. log.Trace("Repository migrated: %s/%s", ctxUser.Name, form.RepoName)
  215. ctx.JSON(201, repo.APIFormat(models.AccessModeAdmin))
  216. }
  217. // Get one repository
  218. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#get
  219. func Get(ctx *context.APIContext) {
  220. repo := ctx.Repo.Repository
  221. access, err := models.AccessLevel(ctx.User, repo)
  222. if err != nil {
  223. ctx.Error(500, "GetRepository", err)
  224. return
  225. }
  226. ctx.JSON(200, repo.APIFormat(access))
  227. }
  228. // GetByID returns a single Repository
  229. func GetByID(ctx *context.APIContext) {
  230. repo, err := models.GetRepositoryByID(ctx.ParamsInt64(":id"))
  231. if err != nil {
  232. if models.IsErrRepoNotExist(err) {
  233. ctx.Status(404)
  234. } else {
  235. ctx.Error(500, "GetRepositoryByID", err)
  236. }
  237. return
  238. }
  239. access, err := models.AccessLevel(ctx.User, repo)
  240. if err != nil {
  241. ctx.Error(500, "GetRepositoryByID", err)
  242. return
  243. }
  244. ctx.JSON(200, repo.APIFormat(access))
  245. }
  246. // Delete one repository
  247. // see https://github.com/gogits/go-gogs-client/wiki/Repositories#delete
  248. func Delete(ctx *context.APIContext) {
  249. if !ctx.Repo.IsAdmin() {
  250. ctx.Error(403, "", "Must have admin rights")
  251. return
  252. }
  253. owner := ctx.Repo.Owner
  254. repo := ctx.Repo.Repository
  255. if owner.IsOrganization() && !owner.IsOwnedBy(ctx.User.ID) {
  256. ctx.Error(403, "", "Given user is not owner of organization.")
  257. return
  258. }
  259. if err := models.DeleteRepository(owner.ID, repo.ID); err != nil {
  260. ctx.Error(500, "DeleteRepository", err)
  261. return
  262. }
  263. log.Trace("Repository deleted: %s/%s", owner.Name, repo.Name)
  264. ctx.Status(204)
  265. }