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

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