diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2021-01-26 23:36:53 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-26 16:36:53 +0100 |
commit | 6433ba0ec3dfde67f45267aa12bd713c4a44c740 (patch) | |
tree | 8813388f7e58ff23ad24af9ccbdb5f0350cb3a09 /modules/context/repo.go | |
parent | 3adbbb4255c42cde04d59b6ebf5ead7e3edda3e7 (diff) | |
download | gitea-6433ba0ec3dfde67f45267aa12bd713c4a44c740.tar.gz gitea-6433ba0ec3dfde67f45267aa12bd713c4a44c740.zip |
Move macaron to chi (#14293)
Use [chi](https://github.com/go-chi/chi) instead of the forked [macaron](https://gitea.com/macaron/macaron). Since macaron and chi have conflicts with session share, this big PR becomes a have-to thing. According my previous idea, we can replace macaron step by step but I'm wrong. :( Below is a list of big changes on this PR.
- [x] Define `context.ResponseWriter` interface with an implementation `context.Response`.
- [x] Use chi instead of macaron, and also a customize `Route` to wrap chi so that the router usage is similar as before.
- [x] Create different routers for `web`, `api`, `internal` and `install` so that the codes will be more clear and no magic .
- [x] Use https://github.com/unrolled/render instead of macaron's internal render
- [x] Use https://github.com/NYTimes/gziphandler instead of https://gitea.com/macaron/gzip
- [x] Use https://gitea.com/go-chi/session which is a modified version of https://gitea.com/macaron/session and removed `nodb` support since it will not be maintained. **BREAK**
- [x] Use https://gitea.com/go-chi/captcha which is a modified version of https://gitea.com/macaron/captcha
- [x] Use https://gitea.com/go-chi/cache which is a modified version of https://gitea.com/macaron/cache
- [x] Use https://gitea.com/go-chi/binding which is a modified version of https://gitea.com/macaron/binding
- [x] Use https://github.com/go-chi/cors instead of https://gitea.com/macaron/cors
- [x] Dropped https://gitea.com/macaron/i18n and make a new one in `code.gitea.io/gitea/modules/translation`
- [x] Move validation form structs from `code.gitea.io/gitea/modules/auth` to `code.gitea.io/gitea/modules/forms` to avoid dependency cycle.
- [x] Removed macaron log service because it's not need any more. **BREAK**
- [x] All form structs have to be get by `web.GetForm(ctx)` in the route function but not as a function parameter on routes definition.
- [x] Move Git HTTP protocol implementation to use routers directly.
- [x] Fix the problem that chi routes don't support trailing slash but macaron did.
- [x] `/api/v1/swagger` now will be redirect to `/api/swagger` but not render directly so that `APIContext` will not create a html render.
Notices:
- Chi router don't support request with trailing slash
- Integration test `TestUserHeatmap` maybe mysql version related. It's failed on my macOS(mysql 5.7.29 installed via brew) but succeed on CI.
Co-authored-by: 6543 <6543@obermui.de>
Diffstat (limited to 'modules/context/repo.go')
-rw-r--r-- | modules/context/repo.go | 570 |
1 files changed, 285 insertions, 285 deletions
diff --git a/modules/context/repo.go b/modules/context/repo.go index 63cb02dc06..79192267fb 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -8,6 +8,7 @@ package context import ( "fmt" "io/ioutil" + "net/http" "net/url" "path" "strings" @@ -21,7 +22,6 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" - "gitea.com/macaron/macaron" "github.com/editorconfig/editorconfig-core-go/v2" "github.com/unknwon/com" ) @@ -81,7 +81,7 @@ func (r *Repository) CanCreateBranch() bool { } // RepoMustNotBeArchived checks if a repo is archived -func RepoMustNotBeArchived() macaron.Handler { +func RepoMustNotBeArchived() func(ctx *Context) { return func(ctx *Context) { if ctx.Repo.Repository.IsArchived { ctx.NotFound("IsArchived", fmt.Errorf(ctx.Tr("repo.archive.title"))) @@ -374,7 +374,7 @@ func repoAssignment(ctx *Context, repo *models.Repository) { } // RepoIDAssignment returns a macaron handler which assigns the repo to the context. -func RepoIDAssignment() macaron.Handler { +func RepoIDAssignment() func(ctx *Context) { return func(ctx *Context) { repoID := ctx.ParamsInt64(":repoid") @@ -394,223 +394,220 @@ func RepoIDAssignment() macaron.Handler { } // RepoAssignment returns a macaron to handle repository assignment -func RepoAssignment() macaron.Handler { - return func(ctx *Context) { - var ( - owner *models.User - err error - ) - - userName := ctx.Params(":username") - repoName := ctx.Params(":reponame") +func RepoAssignment() func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + var ( + owner *models.User + err error + ctx = GetContext(req) + ) + + userName := ctx.Params(":username") + repoName := ctx.Params(":reponame") + repoName = strings.TrimSuffix(repoName, ".git") + + // Check if the user is the same as the repository owner + if ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName) { + owner = ctx.User + } else { + owner, err = models.GetUserByName(userName) + if err != nil { + if models.IsErrUserNotExist(err) { + if ctx.Query("go-get") == "1" { + EarlyResponseForGoGetMeta(ctx) + return + } + ctx.NotFound("GetUserByName", nil) + } else { + ctx.ServerError("GetUserByName", err) + } + return + } + } + ctx.Repo.Owner = owner + ctx.Data["Username"] = ctx.Repo.Owner.Name - // Check if the user is the same as the repository owner - if ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName) { - owner = ctx.User - } else { - owner, err = models.GetUserByName(userName) + // Get repository. + repo, err := models.GetRepositoryByName(owner.ID, repoName) if err != nil { - if models.IsErrUserNotExist(err) { - redirectUserID, err := models.LookupUserRedirect(userName) + if models.IsErrRepoNotExist(err) { + redirectRepoID, err := models.LookupRepoRedirect(owner.ID, repoName) if err == nil { - RedirectToUser(ctx, userName, redirectUserID) - } else if models.IsErrUserRedirectNotExist(err) { + RedirectToRepo(ctx, redirectRepoID) + } else if models.IsErrRepoRedirectNotExist(err) { if ctx.Query("go-get") == "1" { EarlyResponseForGoGetMeta(ctx) return } - ctx.NotFound("GetUserByName", nil) + ctx.NotFound("GetRepositoryByName", nil) } else { - ctx.ServerError("LookupUserRedirect", err) + ctx.ServerError("LookupRepoRedirect", err) } } else { - ctx.ServerError("GetUserByName", err) + ctx.ServerError("GetRepositoryByName", err) } return } - } - ctx.Repo.Owner = owner - ctx.Data["Username"] = ctx.Repo.Owner.Name + repo.Owner = owner - // Get repository. - repo, err := models.GetRepositoryByName(owner.ID, repoName) - if err != nil { - if models.IsErrRepoNotExist(err) { - redirectRepoID, err := models.LookupRepoRedirect(owner.ID, repoName) - if err == nil { - RedirectToRepo(ctx, redirectRepoID) - } else if models.IsErrRepoRedirectNotExist(err) { - if ctx.Query("go-get") == "1" { - EarlyResponseForGoGetMeta(ctx) - return - } - ctx.NotFound("GetRepositoryByName", nil) - } else { - ctx.ServerError("LookupRepoRedirect", err) - } - } else { - ctx.ServerError("GetRepositoryByName", err) + repoAssignment(ctx, repo) + if ctx.Written() { + return } - return - } - repo.Owner = owner - repoAssignment(ctx, repo) - if ctx.Written() { - return - } + ctx.Repo.RepoLink = repo.Link() + ctx.Data["RepoLink"] = ctx.Repo.RepoLink + ctx.Data["RepoRelPath"] = ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name - ctx.Repo.RepoLink = repo.Link() - ctx.Data["RepoLink"] = ctx.Repo.RepoLink - ctx.Data["RepoRelPath"] = ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name + unit, err := ctx.Repo.Repository.GetUnit(models.UnitTypeExternalTracker) + if err == nil { + ctx.Data["RepoExternalIssuesLink"] = unit.ExternalTrackerConfig().ExternalTrackerURL + } - unit, err := ctx.Repo.Repository.GetUnit(models.UnitTypeExternalTracker) - if err == nil { - ctx.Data["RepoExternalIssuesLink"] = unit.ExternalTrackerConfig().ExternalTrackerURL - } + ctx.Data["NumTags"], err = models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{ + IncludeTags: true, + }) + if err != nil { + ctx.ServerError("GetReleaseCountByRepoID", err) + return + } + ctx.Data["NumReleases"], err = models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{}) + if err != nil { + ctx.ServerError("GetReleaseCountByRepoID", err) + return + } - ctx.Data["NumTags"], err = models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{ - IncludeTags: true, - }) - if err != nil { - ctx.ServerError("GetReleaseCountByRepoID", err) - return - } - ctx.Data["NumReleases"], err = models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{}) - if err != nil { - ctx.ServerError("GetReleaseCountByRepoID", err) - return - } + ctx.Data["Title"] = owner.Name + "/" + repo.Name + ctx.Data["Repository"] = repo + ctx.Data["Owner"] = ctx.Repo.Repository.Owner + ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner() + ctx.Data["IsRepositoryAdmin"] = ctx.Repo.IsAdmin() + ctx.Data["RepoOwnerIsOrganization"] = repo.Owner.IsOrganization() + ctx.Data["CanWriteCode"] = ctx.Repo.CanWrite(models.UnitTypeCode) + ctx.Data["CanWriteIssues"] = ctx.Repo.CanWrite(models.UnitTypeIssues) + ctx.Data["CanWritePulls"] = ctx.Repo.CanWrite(models.UnitTypePullRequests) + + if ctx.Data["CanSignedUserFork"], err = ctx.Repo.Repository.CanUserFork(ctx.User); err != nil { + ctx.ServerError("CanUserFork", err) + return + } - ctx.Data["Title"] = owner.Name + "/" + repo.Name - ctx.Data["Repository"] = repo - ctx.Data["Owner"] = ctx.Repo.Repository.Owner - ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner() - ctx.Data["IsRepositoryAdmin"] = ctx.Repo.IsAdmin() - ctx.Data["RepoOwnerIsOrganization"] = repo.Owner.IsOrganization() - ctx.Data["CanWriteCode"] = ctx.Repo.CanWrite(models.UnitTypeCode) - ctx.Data["CanWriteIssues"] = ctx.Repo.CanWrite(models.UnitTypeIssues) - ctx.Data["CanWritePulls"] = ctx.Repo.CanWrite(models.UnitTypePullRequests) - - if ctx.Data["CanSignedUserFork"], err = ctx.Repo.Repository.CanUserFork(ctx.User); err != nil { - ctx.ServerError("CanUserFork", err) - return - } + ctx.Data["DisableSSH"] = setting.SSH.Disabled + ctx.Data["ExposeAnonSSH"] = setting.SSH.ExposeAnonymous + ctx.Data["DisableHTTP"] = setting.Repository.DisableHTTPGit + ctx.Data["RepoSearchEnabled"] = setting.Indexer.RepoIndexerEnabled + ctx.Data["CloneLink"] = repo.CloneLink() + ctx.Data["WikiCloneLink"] = repo.WikiCloneLink() - ctx.Data["DisableSSH"] = setting.SSH.Disabled - ctx.Data["ExposeAnonSSH"] = setting.SSH.ExposeAnonymous - ctx.Data["DisableHTTP"] = setting.Repository.DisableHTTPGit - ctx.Data["RepoSearchEnabled"] = setting.Indexer.RepoIndexerEnabled - ctx.Data["CloneLink"] = repo.CloneLink() - ctx.Data["WikiCloneLink"] = repo.WikiCloneLink() + if ctx.IsSigned { + ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.ID, repo.ID) + ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.ID, repo.ID) + } - if ctx.IsSigned { - ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.ID, repo.ID) - ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.ID, repo.ID) - } + if repo.IsFork { + RetrieveBaseRepo(ctx, repo) + if ctx.Written() { + return + } + } - if repo.IsFork { - RetrieveBaseRepo(ctx, repo) - if ctx.Written() { - return + if repo.IsGenerated() { + RetrieveTemplateRepo(ctx, repo) + if ctx.Written() { + return + } } - } - if repo.IsGenerated() { - RetrieveTemplateRepo(ctx, repo) - if ctx.Written() { + // Disable everything when the repo is being created + if ctx.Repo.Repository.IsBeingCreated() { + ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch return } - } - - // Disable everything when the repo is being created - if ctx.Repo.Repository.IsBeingCreated() { - ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch - return - } - gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName)) - if err != nil { - ctx.ServerError("RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err) - return - } - ctx.Repo.GitRepo = gitRepo - - // We opened it, we should close it - defer func() { - // If it's been set to nil then assume someone else has closed it. - if ctx.Repo.GitRepo != nil { - ctx.Repo.GitRepo.Close() + gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName)) + if err != nil { + ctx.ServerError("RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err) + return } - }() + ctx.Repo.GitRepo = gitRepo - // Stop at this point when the repo is empty. - if ctx.Repo.Repository.IsEmpty { - ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch - ctx.Next() - return - } + // We opened it, we should close it + defer func() { + // If it's been set to nil then assume someone else has closed it. + if ctx.Repo.GitRepo != nil { + ctx.Repo.GitRepo.Close() + } + }() - tags, err := ctx.Repo.GitRepo.GetTags() - if err != nil { - ctx.ServerError("GetTags", err) - return - } - ctx.Data["Tags"] = tags + // Stop at this point when the repo is empty. + if ctx.Repo.Repository.IsEmpty { + ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch + next.ServeHTTP(w, req) + return + } - brs, err := ctx.Repo.GitRepo.GetBranches() - if err != nil { - ctx.ServerError("GetBranches", err) - return - } - ctx.Data["Branches"] = brs - ctx.Data["BranchesCount"] = len(brs) - - ctx.Data["TagName"] = ctx.Repo.TagName - - // If not branch selected, try default one. - // If default branch doesn't exists, fall back to some other branch. - if len(ctx.Repo.BranchName) == 0 { - if len(ctx.Repo.Repository.DefaultBranch) > 0 && gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) { - ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch - } else if len(brs) > 0 { - ctx.Repo.BranchName = brs[0] + tags, err := ctx.Repo.GitRepo.GetTags() + if err != nil { + ctx.ServerError("GetTags", err) + return } - } - ctx.Data["BranchName"] = ctx.Repo.BranchName - ctx.Data["CommitID"] = ctx.Repo.CommitID - - // People who have push access or have forked repository can propose a new pull request. - canPush := ctx.Repo.CanWrite(models.UnitTypeCode) || (ctx.IsSigned && ctx.User.HasForkedRepo(ctx.Repo.Repository.ID)) - canCompare := false - - // Pull request is allowed if this is a fork repository - // and base repository accepts pull requests. - if repo.BaseRepo != nil && repo.BaseRepo.AllowsPulls() { - canCompare = true - ctx.Data["BaseRepo"] = repo.BaseRepo - ctx.Repo.PullRequest.BaseRepo = repo.BaseRepo - ctx.Repo.PullRequest.Allowed = canPush - ctx.Repo.PullRequest.HeadInfo = ctx.Repo.Owner.Name + ":" + ctx.Repo.BranchName - } else if repo.AllowsPulls() { - // Or, this is repository accepts pull requests between branches. - canCompare = true - ctx.Data["BaseRepo"] = repo - ctx.Repo.PullRequest.BaseRepo = repo - ctx.Repo.PullRequest.Allowed = canPush - ctx.Repo.PullRequest.SameRepo = true - ctx.Repo.PullRequest.HeadInfo = ctx.Repo.BranchName - } - ctx.Data["CanCompareOrPull"] = canCompare - ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest + ctx.Data["Tags"] = tags - if ctx.Query("go-get") == "1" { - ctx.Data["GoGetImport"] = ComposeGoGetImport(owner.Name, repo.Name) - prefix := setting.AppURL + path.Join(owner.Name, repo.Name, "src", "branch", ctx.Repo.BranchName) - ctx.Data["GoDocDirectory"] = prefix + "{/dir}" - ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}" - } - ctx.Next() + brs, err := ctx.Repo.GitRepo.GetBranches() + if err != nil { + ctx.ServerError("GetBranches", err) + return + } + ctx.Data["Branches"] = brs + ctx.Data["BranchesCount"] = len(brs) + + ctx.Data["TagName"] = ctx.Repo.TagName + + // If not branch selected, try default one. + // If default branch doesn't exists, fall back to some other branch. + if len(ctx.Repo.BranchName) == 0 { + if len(ctx.Repo.Repository.DefaultBranch) > 0 && gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) { + ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch + } else if len(brs) > 0 { + ctx.Repo.BranchName = brs[0] + } + } + ctx.Data["BranchName"] = ctx.Repo.BranchName + ctx.Data["CommitID"] = ctx.Repo.CommitID + + // People who have push access or have forked repository can propose a new pull request. + canPush := ctx.Repo.CanWrite(models.UnitTypeCode) || (ctx.IsSigned && ctx.User.HasForkedRepo(ctx.Repo.Repository.ID)) + canCompare := false + + // Pull request is allowed if this is a fork repository + // and base repository accepts pull requests. + if repo.BaseRepo != nil && repo.BaseRepo.AllowsPulls() { + canCompare = true + ctx.Data["BaseRepo"] = repo.BaseRepo + ctx.Repo.PullRequest.BaseRepo = repo.BaseRepo + ctx.Repo.PullRequest.Allowed = canPush + ctx.Repo.PullRequest.HeadInfo = ctx.Repo.Owner.Name + ":" + ctx.Repo.BranchName + } else if repo.AllowsPulls() { + // Or, this is repository accepts pull requests between branches. + canCompare = true + ctx.Data["BaseRepo"] = repo + ctx.Repo.PullRequest.BaseRepo = repo + ctx.Repo.PullRequest.Allowed = canPush + ctx.Repo.PullRequest.SameRepo = true + ctx.Repo.PullRequest.HeadInfo = ctx.Repo.BranchName + } + ctx.Data["CanCompareOrPull"] = canCompare + ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest + + if ctx.Query("go-get") == "1" { + ctx.Data["GoGetImport"] = ComposeGoGetImport(owner.Name, repo.Name) + prefix := setting.AppURL + path.Join(owner.Name, repo.Name, "src", "branch", ctx.Repo.BranchName) + ctx.Data["GoDocDirectory"] = prefix + "{/dir}" + ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}" + } + next.ServeHTTP(w, req) + }) } } @@ -636,7 +633,7 @@ const ( // RepoRef handles repository reference names when the ref name is not // explicitly given -func RepoRef() macaron.Handler { +func RepoRef() func(http.Handler) http.Handler { // since no ref name is explicitly specified, ok to just use branch return RepoRefByType(RepoRefBranch) } @@ -715,132 +712,135 @@ func getRefName(ctx *Context, pathType RepoRefType) string { // RepoRefByType handles repository reference name for a specific type // of repository reference -func RepoRefByType(refType RepoRefType) macaron.Handler { - return func(ctx *Context) { - // Empty repository does not have reference information. - if ctx.Repo.Repository.IsEmpty { - return - } - - var ( - refName string - err error - ) - - if ctx.Repo.GitRepo == nil { - repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) - ctx.Repo.GitRepo, err = git.OpenRepository(repoPath) - if err != nil { - ctx.ServerError("RepoRef Invalid repo "+repoPath, err) +func RepoRefByType(refType RepoRefType) func(http.Handler) http.Handler { + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + ctx := GetContext(req) + // Empty repository does not have reference information. + if ctx.Repo.Repository.IsEmpty { return } - // We opened it, we should close it - defer func() { - // If it's been set to nil then assume someone else has closed it. - if ctx.Repo.GitRepo != nil { - ctx.Repo.GitRepo.Close() - } - }() - } - // Get default branch. - if len(ctx.Params("*")) == 0 { - refName = ctx.Repo.Repository.DefaultBranch - ctx.Repo.BranchName = refName - if !ctx.Repo.GitRepo.IsBranchExist(refName) { - brs, err := ctx.Repo.GitRepo.GetBranches() + var ( + refName string + err error + ) + + if ctx.Repo.GitRepo == nil { + repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) + ctx.Repo.GitRepo, err = git.OpenRepository(repoPath) if err != nil { - ctx.ServerError("GetBranches", err) - return - } else if len(brs) == 0 { - err = fmt.Errorf("No branches in non-empty repository %s", - ctx.Repo.GitRepo.Path) - ctx.ServerError("GetBranches", err) + ctx.ServerError("RepoRef Invalid repo "+repoPath, err) return } - refName = brs[0] - } - ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName) - if err != nil { - ctx.ServerError("GetBranchCommit", err) - return + // We opened it, we should close it + defer func() { + // If it's been set to nil then assume someone else has closed it. + if ctx.Repo.GitRepo != nil { + ctx.Repo.GitRepo.Close() + } + }() } - ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() - ctx.Repo.IsViewBranch = true - - } else { - refName = getRefName(ctx, refType) - ctx.Repo.BranchName = refName - if refType.RefTypeIncludesBranches() && ctx.Repo.GitRepo.IsBranchExist(refName) { - ctx.Repo.IsViewBranch = true + // Get default branch. + if len(ctx.Params("*")) == 0 { + refName = ctx.Repo.Repository.DefaultBranch + ctx.Repo.BranchName = refName + if !ctx.Repo.GitRepo.IsBranchExist(refName) { + brs, err := ctx.Repo.GitRepo.GetBranches() + if err != nil { + ctx.ServerError("GetBranches", err) + return + } else if len(brs) == 0 { + err = fmt.Errorf("No branches in non-empty repository %s", + ctx.Repo.GitRepo.Path) + ctx.ServerError("GetBranches", err) + return + } + refName = brs[0] + } ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName) if err != nil { ctx.ServerError("GetBranchCommit", err) return } ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() + ctx.Repo.IsViewBranch = true - } else if refType.RefTypeIncludesTags() && ctx.Repo.GitRepo.IsTagExist(refName) { - ctx.Repo.IsViewTag = true - ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetTagCommit(refName) - if err != nil { - ctx.ServerError("GetTagCommit", err) + } else { + refName = getRefName(ctx, refType) + ctx.Repo.BranchName = refName + if refType.RefTypeIncludesBranches() && ctx.Repo.GitRepo.IsBranchExist(refName) { + ctx.Repo.IsViewBranch = true + + ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName) + if err != nil { + ctx.ServerError("GetBranchCommit", err) + return + } + ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() + + } else if refType.RefTypeIncludesTags() && ctx.Repo.GitRepo.IsTagExist(refName) { + ctx.Repo.IsViewTag = true + ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetTagCommit(refName) + if err != nil { + ctx.ServerError("GetTagCommit", err) + return + } + ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() + } else if len(refName) >= 7 && len(refName) <= 40 { + ctx.Repo.IsViewCommit = true + ctx.Repo.CommitID = refName + + ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName) + if err != nil { + ctx.NotFound("GetCommit", err) + return + } + // If short commit ID add canonical link header + if len(refName) < 40 { + ctx.Header().Set("Link", fmt.Sprintf("<%s>; rel=\"canonical\"", + util.URLJoin(setting.AppURL, strings.Replace(ctx.Req.URL.RequestURI(), refName, ctx.Repo.Commit.ID.String(), 1)))) + } + } else { + ctx.NotFound("RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName)) return } - ctx.Repo.CommitID = ctx.Repo.Commit.ID.String() - } else if len(refName) >= 7 && len(refName) <= 40 { - ctx.Repo.IsViewCommit = true - ctx.Repo.CommitID = refName - ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName) - if err != nil { - ctx.NotFound("GetCommit", err) + if refType == RepoRefLegacy { + // redirect from old URL scheme to new URL scheme + ctx.Redirect(path.Join( + setting.AppSubURL, + strings.TrimSuffix(ctx.Req.URL.Path, ctx.Params("*")), + ctx.Repo.BranchNameSubURL(), + ctx.Repo.TreePath)) return } - // If short commit ID add canonical link header - if len(refName) < 40 { - ctx.Header().Set("Link", fmt.Sprintf("<%s>; rel=\"canonical\"", - util.URLJoin(setting.AppURL, strings.Replace(ctx.Req.URL.RequestURI(), refName, ctx.Repo.Commit.ID.String(), 1)))) - } - } else { - ctx.NotFound("RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName)) - return } - if refType == RepoRefLegacy { - // redirect from old URL scheme to new URL scheme - ctx.Redirect(path.Join( - setting.AppSubURL, - strings.TrimSuffix(ctx.Req.URL.Path, ctx.Params("*")), - ctx.Repo.BranchNameSubURL(), - ctx.Repo.TreePath)) + ctx.Data["BranchName"] = ctx.Repo.BranchName + ctx.Data["BranchNameSubURL"] = ctx.Repo.BranchNameSubURL() + ctx.Data["CommitID"] = ctx.Repo.CommitID + ctx.Data["TreePath"] = ctx.Repo.TreePath + ctx.Data["IsViewBranch"] = ctx.Repo.IsViewBranch + ctx.Data["IsViewTag"] = ctx.Repo.IsViewTag + ctx.Data["IsViewCommit"] = ctx.Repo.IsViewCommit + ctx.Data["CanCreateBranch"] = ctx.Repo.CanCreateBranch() + + ctx.Repo.CommitsCount, err = ctx.Repo.GetCommitsCount() + if err != nil { + ctx.ServerError("GetCommitsCount", err) return } - } + ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount - ctx.Data["BranchName"] = ctx.Repo.BranchName - ctx.Data["BranchNameSubURL"] = ctx.Repo.BranchNameSubURL() - ctx.Data["CommitID"] = ctx.Repo.CommitID - ctx.Data["TreePath"] = ctx.Repo.TreePath - ctx.Data["IsViewBranch"] = ctx.Repo.IsViewBranch - ctx.Data["IsViewTag"] = ctx.Repo.IsViewTag - ctx.Data["IsViewCommit"] = ctx.Repo.IsViewCommit - ctx.Data["CanCreateBranch"] = ctx.Repo.CanCreateBranch() - - ctx.Repo.CommitsCount, err = ctx.Repo.GetCommitsCount() - if err != nil { - ctx.ServerError("GetCommitsCount", err) - return - } - ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount - - ctx.Next() + next.ServeHTTP(w, req) + }) } } // GitHookService checks if repository Git hooks service has been enabled. -func GitHookService() macaron.Handler { +func GitHookService() func(ctx *Context) { return func(ctx *Context) { if !ctx.User.CanEditGitHook() { ctx.NotFound("GitHookService", nil) @@ -850,7 +850,7 @@ func GitHookService() macaron.Handler { } // UnitTypes returns a macaron middleware to set unit types to context variables. -func UnitTypes() macaron.Handler { +func UnitTypes() func(ctx *Context) { return func(ctx *Context) { ctx.Data["UnitTypeCode"] = models.UnitTypeCode ctx.Data["UnitTypeIssues"] = models.UnitTypeIssues |