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