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 15 kB

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
Template Repositories (#8768) * Start work on templates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Continue work Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix IsTemplate vs IsGenerated Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tabs vs spaces * Tabs vs Spaces * Add templates to API & start adding tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix integration tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove unused User Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move template tests to existing repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Minor re-check updates and cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix optionalbool Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test fixes and icon change Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add new user and repo for tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests (finally) Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update meta repo with env variables Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move generation to create page Combine with repo create template Modify API search to prioritize owner for repo Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests and coverage Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix swagger and JS lint Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix API searching for own private repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Change wording Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix repo search test. User had a private repo that didn't show up Signed-off-by: jolheiser <john.olheiser@gmail.com> * Another search test fix Signed-off-by: jolheiser <john.olheiser@gmail.com> * Clarify git content Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Feedback updates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add topics WIP Signed-off-by: jolheiser <john.olheiser@gmail.com> * Finish adding topics Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update locale Signed-off-by: jolheiser <john.olheiser@gmail.com>
5 years ago
11 years ago
11 years ago
10 years ago
Template Repositories (#8768) * Start work on templates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Continue work Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix IsTemplate vs IsGenerated Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tabs vs spaces * Tabs vs Spaces * Add templates to API & start adding tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix integration tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove unused User Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move template tests to existing repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Minor re-check updates and cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix optionalbool Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test fixes and icon change Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add new user and repo for tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests (finally) Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update meta repo with env variables Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move generation to create page Combine with repo create template Modify API search to prioritize owner for repo Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests and coverage Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix swagger and JS lint Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix API searching for own private repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Change wording Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix repo search test. User had a private repo that didn't show up Signed-off-by: jolheiser <john.olheiser@gmail.com> * Another search test fix Signed-off-by: jolheiser <john.olheiser@gmail.com> * Clarify git content Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Feedback updates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add topics WIP Signed-off-by: jolheiser <john.olheiser@gmail.com> * Finish adding topics Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update locale Signed-off-by: jolheiser <john.olheiser@gmail.com>
5 years ago
Template Repositories (#8768) * Start work on templates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Continue work Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix IsTemplate vs IsGenerated Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tabs vs spaces * Tabs vs Spaces * Add templates to API & start adding tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix integration tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove unused User Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move template tests to existing repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Minor re-check updates and cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix optionalbool Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test fixes and icon change Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add new user and repo for tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests (finally) Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update meta repo with env variables Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move generation to create page Combine with repo create template Modify API search to prioritize owner for repo Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests and coverage Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix swagger and JS lint Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix API searching for own private repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Change wording Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix repo search test. User had a private repo that didn't show up Signed-off-by: jolheiser <john.olheiser@gmail.com> * Another search test fix Signed-off-by: jolheiser <john.olheiser@gmail.com> * Clarify git content Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Feedback updates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add topics WIP Signed-off-by: jolheiser <john.olheiser@gmail.com> * Finish adding topics Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update locale Signed-off-by: jolheiser <john.olheiser@gmail.com>
5 years ago
Template Repositories (#8768) * Start work on templates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Continue work Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix IsTemplate vs IsGenerated Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tabs vs spaces * Tabs vs Spaces * Add templates to API & start adding tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix integration tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove unused User Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move template tests to existing repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Minor re-check updates and cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix optionalbool Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test fixes and icon change Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add new user and repo for tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests (finally) Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update meta repo with env variables Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move generation to create page Combine with repo create template Modify API search to prioritize owner for repo Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests and coverage Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix swagger and JS lint Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix API searching for own private repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Change wording Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix repo search test. User had a private repo that didn't show up Signed-off-by: jolheiser <john.olheiser@gmail.com> * Another search test fix Signed-off-by: jolheiser <john.olheiser@gmail.com> * Clarify git content Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Feedback updates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add topics WIP Signed-off-by: jolheiser <john.olheiser@gmail.com> * Finish adding topics Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update locale Signed-off-by: jolheiser <john.olheiser@gmail.com>
5 years ago
Template Repositories (#8768) * Start work on templates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Continue work Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix IsTemplate vs IsGenerated Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tabs vs spaces * Tabs vs Spaces * Add templates to API & start adding tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix integration tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove unused User Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move template tests to existing repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Minor re-check updates and cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test cleanup Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix optionalbool Signed-off-by: jolheiser <john.olheiser@gmail.com> * make fmt Signed-off-by: jolheiser <john.olheiser@gmail.com> * Test fixes and icon change Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add new user and repo for tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests (finally) Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update meta repo with env variables Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move generation to create page Combine with repo create template Modify API search to prioritize owner for repo Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix tests and coverage Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix swagger and JS lint Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix API searching for own private repos Signed-off-by: jolheiser <john.olheiser@gmail.com> * Change wording Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix repo search test. User had a private repo that didn't show up Signed-off-by: jolheiser <john.olheiser@gmail.com> * Another search test fix Signed-off-by: jolheiser <john.olheiser@gmail.com> * Clarify git content Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> * Feedback updates Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add topics WIP Signed-off-by: jolheiser <john.olheiser@gmail.com> * Finish adding topics Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update locale Signed-off-by: jolheiser <john.olheiser@gmail.com>
5 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  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. "fmt"
  7. "os"
  8. "path"
  9. "strings"
  10. "code.gitea.io/gitea/models"
  11. "code.gitea.io/gitea/modules/auth"
  12. "code.gitea.io/gitea/modules/base"
  13. "code.gitea.io/gitea/modules/context"
  14. "code.gitea.io/gitea/modules/git"
  15. "code.gitea.io/gitea/modules/log"
  16. "code.gitea.io/gitea/modules/migrations"
  17. "code.gitea.io/gitea/modules/setting"
  18. "code.gitea.io/gitea/modules/task"
  19. "code.gitea.io/gitea/modules/util"
  20. repo_service "code.gitea.io/gitea/services/repository"
  21. "github.com/unknwon/com"
  22. )
  23. const (
  24. tplCreate base.TplName = "repo/create"
  25. tplMigrate base.TplName = "repo/migrate"
  26. )
  27. // MustBeNotEmpty render when a repo is a empty git dir
  28. func MustBeNotEmpty(ctx *context.Context) {
  29. if ctx.Repo.Repository.IsEmpty {
  30. ctx.NotFound("MustBeNotEmpty", nil)
  31. }
  32. }
  33. // MustBeEditable check that repo can be edited
  34. func MustBeEditable(ctx *context.Context) {
  35. if !ctx.Repo.Repository.CanEnableEditor() || ctx.Repo.IsViewCommit {
  36. ctx.NotFound("", nil)
  37. return
  38. }
  39. }
  40. // MustBeAbleToUpload check that repo can be uploaded to
  41. func MustBeAbleToUpload(ctx *context.Context) {
  42. if !setting.Repository.Upload.Enabled {
  43. ctx.NotFound("", nil)
  44. }
  45. }
  46. func checkContextUser(ctx *context.Context, uid int64) *models.User {
  47. orgs, err := models.GetOrgsCanCreateRepoByUserID(ctx.User.ID)
  48. if err != nil {
  49. ctx.ServerError("GetOrgsCanCreateRepoByUserID", err)
  50. return nil
  51. }
  52. ctx.Data["Orgs"] = orgs
  53. // Not equal means current user is an organization.
  54. if uid == ctx.User.ID || uid == 0 {
  55. return ctx.User
  56. }
  57. org, err := models.GetUserByID(uid)
  58. if models.IsErrUserNotExist(err) {
  59. return ctx.User
  60. }
  61. if err != nil {
  62. ctx.ServerError("GetUserByID", fmt.Errorf("[%d]: %v", uid, err))
  63. return nil
  64. }
  65. // Check ownership of organization.
  66. if !org.IsOrganization() {
  67. ctx.Error(403)
  68. return nil
  69. }
  70. if !ctx.User.IsAdmin {
  71. canCreate, err := org.CanCreateOrgRepo(ctx.User.ID)
  72. if err != nil {
  73. ctx.ServerError("CanCreateOrgRepo", err)
  74. return nil
  75. } else if !canCreate {
  76. ctx.Error(403)
  77. return nil
  78. }
  79. }
  80. return org
  81. }
  82. func getRepoPrivate(ctx *context.Context) bool {
  83. switch strings.ToLower(setting.Repository.DefaultPrivate) {
  84. case setting.RepoCreatingLastUserVisibility:
  85. return ctx.User.LastRepoVisibility
  86. case setting.RepoCreatingPrivate:
  87. return true
  88. case setting.RepoCreatingPublic:
  89. return false
  90. default:
  91. return ctx.User.LastRepoVisibility
  92. }
  93. }
  94. // Create render creating repository page
  95. func Create(ctx *context.Context) {
  96. if !ctx.User.CanCreateRepo() {
  97. ctx.RenderWithErr(ctx.Tr("repo.form.reach_limit_of_creation", ctx.User.MaxCreationLimit()), tplCreate, nil)
  98. }
  99. ctx.Data["Title"] = ctx.Tr("new_repo")
  100. // Give default value for template to render.
  101. ctx.Data["Gitignores"] = models.Gitignores
  102. ctx.Data["LabelTemplates"] = models.LabelTemplates
  103. ctx.Data["Licenses"] = models.Licenses
  104. ctx.Data["Readmes"] = models.Readmes
  105. ctx.Data["readme"] = "Default"
  106. ctx.Data["private"] = getRepoPrivate(ctx)
  107. ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
  108. ctxUser := checkContextUser(ctx, ctx.QueryInt64("org"))
  109. if ctx.Written() {
  110. return
  111. }
  112. ctx.Data["ContextUser"] = ctxUser
  113. ctx.Data["repo_template_name"] = ctx.Tr("repo.template_select")
  114. templateID := ctx.QueryInt64("template_id")
  115. if templateID > 0 {
  116. templateRepo, err := models.GetRepositoryByID(templateID)
  117. if err == nil && templateRepo.CheckUnitUser(ctxUser.ID, ctxUser.IsAdmin, models.UnitTypeCode) {
  118. ctx.Data["repo_template"] = templateID
  119. ctx.Data["repo_template_name"] = templateRepo.Name
  120. }
  121. }
  122. ctx.HTML(200, tplCreate)
  123. }
  124. func handleCreateError(ctx *context.Context, owner *models.User, err error, name string, tpl base.TplName, form interface{}) {
  125. switch {
  126. case models.IsErrReachLimitOfRepo(err):
  127. ctx.RenderWithErr(ctx.Tr("repo.form.reach_limit_of_creation", owner.MaxCreationLimit()), tpl, form)
  128. case models.IsErrRepoAlreadyExist(err):
  129. ctx.Data["Err_RepoName"] = true
  130. ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), tpl, form)
  131. case models.IsErrNameReserved(err):
  132. ctx.Data["Err_RepoName"] = true
  133. ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), tpl, form)
  134. case models.IsErrNamePatternNotAllowed(err):
  135. ctx.Data["Err_RepoName"] = true
  136. ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tpl, form)
  137. default:
  138. ctx.ServerError(name, err)
  139. }
  140. }
  141. // CreatePost response for creating repository
  142. func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
  143. ctx.Data["Title"] = ctx.Tr("new_repo")
  144. ctx.Data["Gitignores"] = models.Gitignores
  145. ctx.Data["LabelTemplates"] = models.LabelTemplates
  146. ctx.Data["Licenses"] = models.Licenses
  147. ctx.Data["Readmes"] = models.Readmes
  148. ctxUser := checkContextUser(ctx, form.UID)
  149. if ctx.Written() {
  150. return
  151. }
  152. ctx.Data["ContextUser"] = ctxUser
  153. if ctx.HasError() {
  154. ctx.HTML(200, tplCreate)
  155. return
  156. }
  157. var repo *models.Repository
  158. var err error
  159. if form.RepoTemplate > 0 {
  160. opts := models.GenerateRepoOptions{
  161. Name: form.RepoName,
  162. Description: form.Description,
  163. Private: form.Private,
  164. GitContent: form.GitContent,
  165. Topics: form.Topics,
  166. GitHooks: form.GitHooks,
  167. Webhooks: form.Webhooks,
  168. Avatar: form.Avatar,
  169. IssueLabels: form.Labels,
  170. }
  171. if !opts.IsValid() {
  172. ctx.RenderWithErr(ctx.Tr("repo.template.one_item"), tplCreate, form)
  173. return
  174. }
  175. templateRepo := getRepository(ctx, form.RepoTemplate)
  176. if ctx.Written() {
  177. return
  178. }
  179. if !templateRepo.IsTemplate {
  180. ctx.RenderWithErr(ctx.Tr("repo.template.invalid"), tplCreate, form)
  181. return
  182. }
  183. repo, err = repo_service.GenerateRepository(ctx.User, ctxUser, templateRepo, opts)
  184. if err == nil {
  185. log.Trace("Repository generated [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
  186. ctx.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + repo.Name)
  187. return
  188. }
  189. } else {
  190. repo, err = repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{
  191. Name: form.RepoName,
  192. Description: form.Description,
  193. Gitignores: form.Gitignores,
  194. IssueLabels: form.IssueLabels,
  195. License: form.License,
  196. Readme: form.Readme,
  197. IsPrivate: form.Private || setting.Repository.ForcePrivate,
  198. AutoInit: form.AutoInit,
  199. })
  200. if err == nil {
  201. log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
  202. ctx.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + repo.Name)
  203. return
  204. }
  205. }
  206. handleCreateError(ctx, ctxUser, err, "CreatePost", tplCreate, &form)
  207. }
  208. // Migrate render migration of repository page
  209. func Migrate(ctx *context.Context) {
  210. ctx.Data["Title"] = ctx.Tr("new_migrate")
  211. ctx.Data["private"] = getRepoPrivate(ctx)
  212. ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
  213. ctx.Data["mirror"] = ctx.Query("mirror") == "1"
  214. ctx.Data["wiki"] = ctx.Query("wiki") == "1"
  215. ctx.Data["milestones"] = ctx.Query("milestones") == "1"
  216. ctx.Data["labels"] = ctx.Query("labels") == "1"
  217. ctx.Data["issues"] = ctx.Query("issues") == "1"
  218. ctx.Data["pull_requests"] = ctx.Query("pull_requests") == "1"
  219. ctx.Data["releases"] = ctx.Query("releases") == "1"
  220. ctx.Data["LFSActive"] = setting.LFS.StartServer
  221. ctxUser := checkContextUser(ctx, ctx.QueryInt64("org"))
  222. if ctx.Written() {
  223. return
  224. }
  225. ctx.Data["ContextUser"] = ctxUser
  226. ctx.HTML(200, tplMigrate)
  227. }
  228. func handleMigrateError(ctx *context.Context, owner *models.User, err error, name string, tpl base.TplName, form *auth.MigrateRepoForm) {
  229. switch {
  230. case migrations.IsRateLimitError(err):
  231. ctx.RenderWithErr(ctx.Tr("form.visit_rate_limit"), tpl, form)
  232. case migrations.IsTwoFactorAuthError(err):
  233. ctx.RenderWithErr(ctx.Tr("form.2fa_auth_required"), tpl, form)
  234. case models.IsErrReachLimitOfRepo(err):
  235. ctx.RenderWithErr(ctx.Tr("repo.form.reach_limit_of_creation", owner.MaxCreationLimit()), tpl, form)
  236. case models.IsErrRepoAlreadyExist(err):
  237. ctx.Data["Err_RepoName"] = true
  238. ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), tpl, form)
  239. case models.IsErrNameReserved(err):
  240. ctx.Data["Err_RepoName"] = true
  241. ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), tpl, form)
  242. case models.IsErrNamePatternNotAllowed(err):
  243. ctx.Data["Err_RepoName"] = true
  244. ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tpl, form)
  245. default:
  246. remoteAddr, _ := form.ParseRemoteAddr(owner)
  247. err = util.URLSanitizedError(err, remoteAddr)
  248. if strings.Contains(err.Error(), "Authentication failed") ||
  249. strings.Contains(err.Error(), "Bad credentials") ||
  250. strings.Contains(err.Error(), "could not read Username") {
  251. ctx.Data["Err_Auth"] = true
  252. ctx.RenderWithErr(ctx.Tr("form.auth_failed", err.Error()), tpl, form)
  253. } else if strings.Contains(err.Error(), "fatal:") {
  254. ctx.Data["Err_CloneAddr"] = true
  255. ctx.RenderWithErr(ctx.Tr("repo.migrate.failed", err.Error()), tpl, form)
  256. } else {
  257. ctx.ServerError(name, err)
  258. }
  259. }
  260. }
  261. // MigratePost response for migrating from external git repository
  262. func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
  263. ctx.Data["Title"] = ctx.Tr("new_migrate")
  264. ctxUser := checkContextUser(ctx, form.UID)
  265. if ctx.Written() {
  266. return
  267. }
  268. ctx.Data["ContextUser"] = ctxUser
  269. if ctx.HasError() {
  270. ctx.HTML(200, tplMigrate)
  271. return
  272. }
  273. remoteAddr, err := form.ParseRemoteAddr(ctx.User)
  274. if err != nil {
  275. if models.IsErrInvalidCloneAddr(err) {
  276. ctx.Data["Err_CloneAddr"] = true
  277. addrErr := err.(models.ErrInvalidCloneAddr)
  278. switch {
  279. case addrErr.IsURLError:
  280. ctx.RenderWithErr(ctx.Tr("form.url_error"), tplMigrate, &form)
  281. case addrErr.IsPermissionDenied:
  282. ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied"), tplMigrate, &form)
  283. case addrErr.IsInvalidPath:
  284. ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), tplMigrate, &form)
  285. default:
  286. ctx.ServerError("Unknown error", err)
  287. }
  288. } else {
  289. ctx.ServerError("ParseRemoteAddr", err)
  290. }
  291. return
  292. }
  293. var opts = migrations.MigrateOptions{
  294. OriginalURL: form.CloneAddr,
  295. CloneAddr: remoteAddr,
  296. RepoName: form.RepoName,
  297. Description: form.Description,
  298. Private: form.Private || setting.Repository.ForcePrivate,
  299. Mirror: form.Mirror,
  300. AuthUsername: form.AuthUsername,
  301. AuthPassword: form.AuthPassword,
  302. Wiki: form.Wiki,
  303. Issues: form.Issues,
  304. Milestones: form.Milestones,
  305. Labels: form.Labels,
  306. Comments: true,
  307. PullRequests: form.PullRequests,
  308. Releases: form.Releases,
  309. }
  310. if opts.Mirror {
  311. opts.Issues = false
  312. opts.Milestones = false
  313. opts.Labels = false
  314. opts.Comments = false
  315. opts.PullRequests = false
  316. opts.Releases = false
  317. }
  318. err = models.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName)
  319. if err != nil {
  320. handleMigrateError(ctx, ctxUser, err, "MigratePost", tplMigrate, &form)
  321. return
  322. }
  323. err = task.MigrateRepository(ctx.User, ctxUser, opts)
  324. if err == nil {
  325. ctx.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + opts.RepoName)
  326. return
  327. }
  328. handleMigrateError(ctx, ctxUser, err, "MigratePost", tplMigrate, &form)
  329. }
  330. // Action response for actions to a repository
  331. func Action(ctx *context.Context) {
  332. var err error
  333. switch ctx.Params(":action") {
  334. case "watch":
  335. err = models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, true)
  336. case "unwatch":
  337. err = models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, false)
  338. case "star":
  339. err = models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, true)
  340. case "unstar":
  341. err = models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, false)
  342. case "desc": // FIXME: this is not used
  343. if !ctx.Repo.IsOwner() {
  344. ctx.Error(404)
  345. return
  346. }
  347. ctx.Repo.Repository.Description = ctx.Query("desc")
  348. ctx.Repo.Repository.Website = ctx.Query("site")
  349. err = models.UpdateRepository(ctx.Repo.Repository, false)
  350. }
  351. if err != nil {
  352. ctx.ServerError(fmt.Sprintf("Action (%s)", ctx.Params(":action")), err)
  353. return
  354. }
  355. ctx.RedirectToFirst(ctx.Query("redirect_to"), ctx.Repo.RepoLink)
  356. }
  357. // RedirectDownload return a file based on the following infos:
  358. func RedirectDownload(ctx *context.Context) {
  359. var (
  360. vTag = ctx.Params("vTag")
  361. fileName = ctx.Params("fileName")
  362. )
  363. tagNames := []string{vTag}
  364. curRepo := ctx.Repo.Repository
  365. releases, err := models.GetReleasesByRepoIDAndNames(curRepo.ID, tagNames)
  366. if err != nil {
  367. if models.IsErrAttachmentNotExist(err) {
  368. ctx.Error(404)
  369. return
  370. }
  371. ctx.ServerError("RedirectDownload", err)
  372. return
  373. }
  374. if len(releases) == 1 {
  375. release := releases[0]
  376. att, err := models.GetAttachmentByReleaseIDFileName(release.ID, fileName)
  377. if err != nil {
  378. ctx.Error(404)
  379. return
  380. }
  381. if att != nil {
  382. ctx.Redirect(att.DownloadURL())
  383. return
  384. }
  385. }
  386. ctx.Error(404)
  387. }
  388. // Download download an archive of a repository
  389. func Download(ctx *context.Context) {
  390. var (
  391. uri = ctx.Params("*")
  392. refName string
  393. ext string
  394. archivePath string
  395. archiveType git.ArchiveType
  396. )
  397. switch {
  398. case strings.HasSuffix(uri, ".zip"):
  399. ext = ".zip"
  400. archivePath = path.Join(ctx.Repo.GitRepo.Path, "archives/zip")
  401. archiveType = git.ZIP
  402. case strings.HasSuffix(uri, ".tar.gz"):
  403. ext = ".tar.gz"
  404. archivePath = path.Join(ctx.Repo.GitRepo.Path, "archives/targz")
  405. archiveType = git.TARGZ
  406. default:
  407. log.Trace("Unknown format: %s", uri)
  408. ctx.Error(404)
  409. return
  410. }
  411. refName = strings.TrimSuffix(uri, ext)
  412. if !com.IsDir(archivePath) {
  413. if err := os.MkdirAll(archivePath, os.ModePerm); err != nil {
  414. ctx.ServerError("Download -> os.MkdirAll(archivePath)", err)
  415. return
  416. }
  417. }
  418. // Get corresponding commit.
  419. var (
  420. commit *git.Commit
  421. err error
  422. )
  423. gitRepo := ctx.Repo.GitRepo
  424. if gitRepo.IsBranchExist(refName) {
  425. commit, err = gitRepo.GetBranchCommit(refName)
  426. if err != nil {
  427. ctx.ServerError("GetBranchCommit", err)
  428. return
  429. }
  430. } else if gitRepo.IsTagExist(refName) {
  431. commit, err = gitRepo.GetTagCommit(refName)
  432. if err != nil {
  433. ctx.ServerError("GetTagCommit", err)
  434. return
  435. }
  436. } else if len(refName) >= 4 && len(refName) <= 40 {
  437. commit, err = gitRepo.GetCommit(refName)
  438. if err != nil {
  439. ctx.NotFound("GetCommit", nil)
  440. return
  441. }
  442. } else {
  443. ctx.NotFound("Download", nil)
  444. return
  445. }
  446. archivePath = path.Join(archivePath, base.ShortSha(commit.ID.String())+ext)
  447. if !com.IsFile(archivePath) {
  448. if err := commit.CreateArchive(archivePath, archiveType); err != nil {
  449. ctx.ServerError("Download -> CreateArchive "+archivePath, err)
  450. return
  451. }
  452. }
  453. ctx.ServeFile(archivePath, ctx.Repo.Repository.Name+"-"+refName+ext)
  454. }
  455. // Status returns repository's status
  456. func Status(ctx *context.Context) {
  457. task, err := models.GetMigratingTask(ctx.Repo.Repository.ID)
  458. if err != nil {
  459. ctx.JSON(500, map[string]interface{}{
  460. "err": err,
  461. })
  462. return
  463. }
  464. ctx.JSON(200, map[string]interface{}{
  465. "status": ctx.Repo.Repository.Status,
  466. "err": task.Errors,
  467. })
  468. }