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

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