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