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