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