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