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