You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 7 години
преди 10 години
преди 7 години
преди 8 години
преди 8 години
преди 8 години
преди 8 години
преди 8 години
преди 8 години
преди 9 години
преди 8 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 8 години
преди 8 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 7 години
преди 8 години
преди 7 години
преди 10 години
преди 10 години
преди 8 години
преди 10 години
преди 9 години
преди 9 години
преди 10 години
преди 7 години
преди 10 години
преди 8 години
преди 8 години
преди 8 години
преди 8 години
преди 7 години
преди 8 години
преди 10 години
преди 10 години
преди 10 години
преди 7 години
преди 9 години
преди 10 години
преди 10 години
преди 7 години
преди 10 години
преди 8 години
преди 8 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 8 години
преди 10 години
преди 10 години
преди 7 години
преди 10 години
преди 10 години
преди 7 години
преди 8 години
преди 10 години
преди 8 години
преди 10 години
преди 9 години
преди 9 години
преди 10 години
преди 10 години
преди 7 години
преди 10 години
преди 7 години
преди 8 години
преди 10 години
преди 7 години
преди 9 години
преди 10 години
преди 10 години
преди 7 години
преди 10 години
преди 7 години
преди 7 години
преди 7 години
преди 8 години
преди 10 години
преди 8 години
преди 10 години
преди 8 години
преди 8 години
преди 10 години
преди 7 години
преди 8 години
преди 7 години
преди 8 години
преди 7 години
преди 10 години
преди 7 години
преди 8 години
преди 10 години
преди 8 години
преди 10 години
преди 8 години
преди 10 години
преди 8 години
преди 10 години
преди 8 години
преди 10 години
преди 10 години
преди 10 години
преди 9 години
преди 10 години
преди 10 години
преди 7 години
преди 8 години
преди 9 години
преди 9 години
преди 9 години
преди 10 години
преди 9 години
преди 9 години
преди 10 години
преди 9 години
преди 10 години
преди 10 години
преди 10 години
преди 9 години
преди 10 години
преди 10 години
преди 10 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 9 години
преди 8 години
преди 10 години
преди 9 години
преди 10 години
преди 10 години
преди 10 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package repo
  5. import (
  6. "fmt"
  7. "os"
  8. "path"
  9. "strings"
  10. "github.com/Unknwon/com"
  11. "code.gitea.io/git"
  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/log"
  17. "code.gitea.io/gitea/modules/setting"
  18. )
  19. const (
  20. tplCreate base.TplName = "repo/create"
  21. tplMigrate base.TplName = "repo/migrate"
  22. )
  23. // MustBeNotBare render when a repo is a bare git dir
  24. func MustBeNotBare(ctx *context.Context) {
  25. if ctx.Repo.Repository.IsBare {
  26. ctx.Handle(404, "MustBeNotBare", nil)
  27. }
  28. }
  29. func checkContextUser(ctx *context.Context, uid int64) *models.User {
  30. orgs, err := models.GetOwnedOrgsByUserIDDesc(ctx.User.ID, "updated_unix")
  31. if err != nil {
  32. ctx.Handle(500, "GetOwnedOrgsByUserIDDesc", err)
  33. return nil
  34. }
  35. ctx.Data["Orgs"] = orgs
  36. // Not equal means current user is an organization.
  37. if uid == ctx.User.ID || uid == 0 {
  38. return ctx.User
  39. }
  40. org, err := models.GetUserByID(uid)
  41. if models.IsErrUserNotExist(err) {
  42. return ctx.User
  43. }
  44. if err != nil {
  45. ctx.Handle(500, "GetUserByID", fmt.Errorf("[%d]: %v", uid, err))
  46. return nil
  47. }
  48. // Check ownership of organization.
  49. if !org.IsOrganization() || !(ctx.User.IsAdmin || org.IsOwnedBy(ctx.User.ID)) {
  50. ctx.Error(403)
  51. return nil
  52. }
  53. return org
  54. }
  55. // Create render creating repository page
  56. func Create(ctx *context.Context) {
  57. if !ctx.User.CanCreateRepo() {
  58. ctx.RenderWithErr(ctx.Tr("repo.form.reach_limit_of_creation", ctx.User.MaxCreationLimit()), tplCreate, nil)
  59. }
  60. ctx.Data["Title"] = ctx.Tr("new_repo")
  61. // Give default value for template to render.
  62. ctx.Data["Gitignores"] = models.Gitignores
  63. ctx.Data["Licenses"] = models.Licenses
  64. ctx.Data["Readmes"] = models.Readmes
  65. ctx.Data["readme"] = "Default"
  66. ctx.Data["private"] = ctx.User.LastRepoVisibility
  67. ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
  68. ctxUser := checkContextUser(ctx, ctx.QueryInt64("org"))
  69. if ctx.Written() {
  70. return
  71. }
  72. ctx.Data["ContextUser"] = ctxUser
  73. ctx.HTML(200, tplCreate)
  74. }
  75. func handleCreateError(ctx *context.Context, owner *models.User, err error, name string, tpl base.TplName, form interface{}) {
  76. switch {
  77. case models.IsErrReachLimitOfRepo(err):
  78. ctx.RenderWithErr(ctx.Tr("repo.form.reach_limit_of_creation", owner.MaxCreationLimit()), tpl, form)
  79. case models.IsErrRepoAlreadyExist(err):
  80. ctx.Data["Err_RepoName"] = true
  81. ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), tpl, form)
  82. case models.IsErrNameReserved(err):
  83. ctx.Data["Err_RepoName"] = true
  84. ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), tpl, form)
  85. case models.IsErrNamePatternNotAllowed(err):
  86. ctx.Data["Err_RepoName"] = true
  87. ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tpl, form)
  88. default:
  89. ctx.Handle(500, name, err)
  90. }
  91. }
  92. // CreatePost response for creating repository
  93. func CreatePost(ctx *context.Context, form auth.CreateRepoForm) {
  94. ctx.Data["Title"] = ctx.Tr("new_repo")
  95. ctx.Data["Gitignores"] = models.Gitignores
  96. ctx.Data["Licenses"] = models.Licenses
  97. ctx.Data["Readmes"] = models.Readmes
  98. ctxUser := checkContextUser(ctx, form.UID)
  99. if ctx.Written() {
  100. return
  101. }
  102. ctx.Data["ContextUser"] = ctxUser
  103. if ctx.HasError() {
  104. ctx.HTML(200, tplCreate)
  105. return
  106. }
  107. repo, err := models.CreateRepository(ctxUser, models.CreateRepoOptions{
  108. Name: form.RepoName,
  109. Description: form.Description,
  110. Gitignores: form.Gitignores,
  111. License: form.License,
  112. Readme: form.Readme,
  113. IsPrivate: form.Private || setting.Repository.ForcePrivate,
  114. AutoInit: form.AutoInit,
  115. })
  116. if err == nil {
  117. log.Trace("Repository created [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
  118. ctx.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + repo.Name)
  119. return
  120. }
  121. if repo != nil {
  122. if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil {
  123. log.Error(4, "DeleteRepository: %v", errDelete)
  124. }
  125. }
  126. handleCreateError(ctx, ctxUser, err, "CreatePost", tplCreate, &form)
  127. }
  128. // Migrate render migration of repository page
  129. func Migrate(ctx *context.Context) {
  130. ctx.Data["Title"] = ctx.Tr("new_migrate")
  131. ctx.Data["private"] = ctx.User.LastRepoVisibility
  132. ctx.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
  133. ctx.Data["mirror"] = ctx.Query("mirror") == "1"
  134. ctx.Data["LFSActive"] = setting.LFS.StartServer
  135. ctxUser := checkContextUser(ctx, ctx.QueryInt64("org"))
  136. if ctx.Written() {
  137. return
  138. }
  139. ctx.Data["ContextUser"] = ctxUser
  140. ctx.HTML(200, tplMigrate)
  141. }
  142. // MigratePost response for migrating from external git repository
  143. func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) {
  144. ctx.Data["Title"] = ctx.Tr("new_migrate")
  145. ctxUser := checkContextUser(ctx, form.UID)
  146. if ctx.Written() {
  147. return
  148. }
  149. ctx.Data["ContextUser"] = ctxUser
  150. if ctx.HasError() {
  151. ctx.HTML(200, tplMigrate)
  152. return
  153. }
  154. remoteAddr, err := form.ParseRemoteAddr(ctx.User)
  155. if err != nil {
  156. if models.IsErrInvalidCloneAddr(err) {
  157. ctx.Data["Err_CloneAddr"] = true
  158. addrErr := err.(models.ErrInvalidCloneAddr)
  159. switch {
  160. case addrErr.IsURLError:
  161. ctx.RenderWithErr(ctx.Tr("form.url_error"), tplMigrate, &form)
  162. case addrErr.IsPermissionDenied:
  163. ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied"), tplMigrate, &form)
  164. case addrErr.IsInvalidPath:
  165. ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), tplMigrate, &form)
  166. default:
  167. ctx.Handle(500, "Unknown error", err)
  168. }
  169. } else {
  170. ctx.Handle(500, "ParseRemoteAddr", err)
  171. }
  172. return
  173. }
  174. repo, err := models.MigrateRepository(ctxUser, models.MigrateRepoOptions{
  175. Name: form.RepoName,
  176. Description: form.Description,
  177. IsPrivate: form.Private || setting.Repository.ForcePrivate,
  178. IsMirror: form.Mirror,
  179. RemoteAddr: remoteAddr,
  180. })
  181. if err == nil {
  182. log.Trace("Repository migrated [%d]: %s/%s", repo.ID, ctxUser.Name, form.RepoName)
  183. ctx.Redirect(setting.AppSubURL + "/" + ctxUser.Name + "/" + form.RepoName)
  184. return
  185. }
  186. if repo != nil {
  187. if errDelete := models.DeleteRepository(ctxUser.ID, repo.ID); errDelete != nil {
  188. log.Error(4, "DeleteRepository: %v", errDelete)
  189. }
  190. }
  191. if strings.Contains(err.Error(), "Authentication failed") ||
  192. strings.Contains(err.Error(), "could not read Username") {
  193. ctx.Data["Err_Auth"] = true
  194. ctx.RenderWithErr(ctx.Tr("form.auth_failed", models.HandleCloneUserCredentials(err.Error(), true)), tplMigrate, &form)
  195. return
  196. } else if strings.Contains(err.Error(), "fatal:") {
  197. ctx.Data["Err_CloneAddr"] = true
  198. ctx.RenderWithErr(ctx.Tr("repo.migrate.failed", models.HandleCloneUserCredentials(err.Error(), true)), tplMigrate, &form)
  199. return
  200. }
  201. handleCreateError(ctx, ctxUser, err, "MigratePost", tplMigrate, &form)
  202. }
  203. // Action response for actions to a repository
  204. func Action(ctx *context.Context) {
  205. var err error
  206. switch ctx.Params(":action") {
  207. case "watch":
  208. err = models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, true)
  209. case "unwatch":
  210. err = models.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, false)
  211. case "star":
  212. err = models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, true)
  213. case "unstar":
  214. err = models.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, false)
  215. case "desc": // FIXME: this is not used
  216. if !ctx.Repo.IsOwner() {
  217. ctx.Error(404)
  218. return
  219. }
  220. ctx.Repo.Repository.Description = ctx.Query("desc")
  221. ctx.Repo.Repository.Website = ctx.Query("site")
  222. err = models.UpdateRepository(ctx.Repo.Repository, false)
  223. }
  224. if err != nil {
  225. ctx.Handle(500, fmt.Sprintf("Action (%s)", ctx.Params(":action")), err)
  226. return
  227. }
  228. redirectTo := ctx.Query("redirect_to")
  229. if len(redirectTo) == 0 {
  230. redirectTo = ctx.Repo.RepoLink
  231. }
  232. ctx.Redirect(redirectTo)
  233. }
  234. // Download download an archive of a repository
  235. func Download(ctx *context.Context) {
  236. var (
  237. uri = ctx.Params("*")
  238. refName string
  239. ext string
  240. archivePath string
  241. archiveType git.ArchiveType
  242. )
  243. switch {
  244. case strings.HasSuffix(uri, ".zip"):
  245. ext = ".zip"
  246. archivePath = path.Join(ctx.Repo.GitRepo.Path, "archives/zip")
  247. archiveType = git.ZIP
  248. case strings.HasSuffix(uri, ".tar.gz"):
  249. ext = ".tar.gz"
  250. archivePath = path.Join(ctx.Repo.GitRepo.Path, "archives/targz")
  251. archiveType = git.TARGZ
  252. default:
  253. log.Trace("Unknown format: %s", uri)
  254. ctx.Error(404)
  255. return
  256. }
  257. refName = strings.TrimSuffix(uri, ext)
  258. if !com.IsDir(archivePath) {
  259. if err := os.MkdirAll(archivePath, os.ModePerm); err != nil {
  260. ctx.Handle(500, "Download -> os.MkdirAll(archivePath)", err)
  261. return
  262. }
  263. }
  264. // Get corresponding commit.
  265. var (
  266. commit *git.Commit
  267. err error
  268. )
  269. gitRepo := ctx.Repo.GitRepo
  270. if gitRepo.IsBranchExist(refName) {
  271. commit, err = gitRepo.GetBranchCommit(refName)
  272. if err != nil {
  273. ctx.Handle(500, "GetBranchCommit", err)
  274. return
  275. }
  276. } else if gitRepo.IsTagExist(refName) {
  277. commit, err = gitRepo.GetTagCommit(refName)
  278. if err != nil {
  279. ctx.Handle(500, "GetTagCommit", err)
  280. return
  281. }
  282. } else if len(refName) >= 4 && len(refName) <= 40 {
  283. commit, err = gitRepo.GetCommit(refName)
  284. if err != nil {
  285. ctx.Handle(404, "GetCommit", nil)
  286. return
  287. }
  288. } else {
  289. ctx.Handle(404, "Download", nil)
  290. return
  291. }
  292. archivePath = path.Join(archivePath, base.ShortSha(commit.ID.String())+ext)
  293. if !com.IsFile(archivePath) {
  294. if err := commit.CreateArchive(archivePath, archiveType); err != nil {
  295. ctx.Handle(500, "Download -> CreateArchive "+archivePath, err)
  296. return
  297. }
  298. }
  299. ctx.ServeFile(archivePath, ctx.Repo.Repository.Name+"-"+refName+ext)
  300. }