diff options
author | Ethan Koenig <ethantkoenig@gmail.com> | 2017-10-29 19:04:25 -0700 |
---|---|---|
committer | Lunny Xiao <xiaolunwen@gmail.com> | 2017-10-30 10:04:25 +0800 |
commit | 513375c429435ba60a667b219bdfb00e5b760b38 (patch) | |
tree | 9f516c8d0ebbdc66808c9017df7db2ff9aa34b57 /modules/context/repo.go | |
parent | 6e98812ecf4efb6f53d72414ca8f67b14fac6595 (diff) | |
download | gitea-513375c429435ba60a667b219bdfb00e5b760b38.tar.gz gitea-513375c429435ba60a667b219bdfb00e5b760b38.zip |
Make URL scheme unambiguous (#2408)
* Make URL scheme unambiguous
Redirect old routes to new routes
* Fix redirects to new URL scheme, and update template
* Fix branches/_new endpoints, and update integration test
Diffstat (limited to 'modules/context/repo.go')
-rw-r--r-- | modules/context/repo.go | 120 |
1 files changed, 99 insertions, 21 deletions
diff --git a/modules/context/repo.go b/modules/context/repo.go index 704dc59f93..b2b58c4f26 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/git" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/cache" + "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "github.com/Unknwon/com" @@ -117,6 +118,20 @@ func (r *Repository) GetCommitsCount() (int64, error) { }) } +// BranchNameSubURL sub-URL for the BranchName field +func (r *Repository) BranchNameSubURL() string { + switch { + case r.IsViewBranch: + return "branch/" + r.BranchName + case r.IsViewTag: + return "tag/" + r.BranchName + case r.IsViewCommit: + return "commit/" + r.BranchName + } + log.Error(4, "Unknown view type for repo: %v", r) + return "" +} + // GetEditorconfig returns the .editorconfig definition if found in the // HEAD of the default repo branch. func (r *Repository) GetEditorconfig() (*editorconfig.Editorconfig, error) { @@ -444,8 +459,81 @@ func RepoAssignment() macaron.Handler { } } -// RepoRef handles repository reference name including those contain `/`. +// RepoRefType type of repo reference +type RepoRefType int + +const ( + // RepoRefLegacy unknown type, make educated guess and redirect. + // for backward compatibility with previous URL scheme + RepoRefLegacy RepoRefType = iota + // RepoRefBranch branch + RepoRefBranch + // RepoRefTag tag + RepoRefTag + // RepoRefCommit commit + RepoRefCommit +) + +// RepoRef handles repository reference names when the ref name is not +// explicitly given func RepoRef() macaron.Handler { + // since no ref name is explicitly specified, ok to just use branch + return RepoRefByType(RepoRefBranch) +} + +func getRefNameFromPath(ctx *Context, path string, isExist func(string) bool) string { + refName := "" + parts := strings.Split(path, "/") + for i, part := range parts { + refName = strings.TrimPrefix(refName+"/"+part, "/") + if isExist(refName) { + ctx.Repo.TreePath = strings.Join(parts[i+1:], "/") + return refName + } + } + return "" +} + +func getRefName(ctx *Context, pathType RepoRefType) string { + path := ctx.Params("*") + switch pathType { + case RepoRefLegacy: + if refName := getRefName(ctx, RepoRefBranch); len(refName) > 0 { + return refName + } + if refName := getRefName(ctx, RepoRefTag); len(refName) > 0 { + return refName + } + return getRefName(ctx, RepoRefCommit) + case RepoRefBranch: + return getRefNameFromPath(ctx, path, ctx.Repo.GitRepo.IsBranchExist) + case RepoRefTag: + return getRefNameFromPath(ctx, path, ctx.Repo.GitRepo.IsTagExist) + case RepoRefCommit: + parts := strings.Split(path, "/") + if len(parts) > 0 && len(parts[0]) == 40 { + ctx.Repo.TreePath = strings.Join(parts[1:], "/") + return parts[0] + } + default: + log.Error(4, "Unrecognized path type: %v", path) + } + return "" +} + +// URL to redirect to for deprecated URL scheme +func repoRefRedirect(ctx *Context) string { + urlPath := ctx.Req.URL.String() + idx := strings.LastIndex(urlPath, ctx.Params("*")) + if idx < 0 { + idx = len(urlPath) + } + return path.Join(urlPath[:idx], ctx.Repo.BranchNameSubURL()) +} + +// 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.IsBare { @@ -470,6 +558,7 @@ func RepoRef() macaron.Handler { // 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 { @@ -492,25 +581,8 @@ func RepoRef() macaron.Handler { ctx.Repo.IsViewBranch = true } else { - hasMatched := false - parts := strings.Split(ctx.Params("*"), "/") - for i, part := range parts { - refName = strings.TrimPrefix(refName+"/"+part, "/") - - if ctx.Repo.GitRepo.IsBranchExist(refName) || - ctx.Repo.GitRepo.IsTagExist(refName) { - if i < len(parts)-1 { - ctx.Repo.TreePath = strings.Join(parts[i+1:], "/") - } - hasMatched = true - break - } - } - if !hasMatched && len(parts[0]) == 40 { - refName = parts[0] - ctx.Repo.TreePath = strings.Join(parts[1:], "/") - } - + refName = getRefName(ctx, refType) + ctx.Repo.BranchName = refName if ctx.Repo.GitRepo.IsBranchExist(refName) { ctx.Repo.IsViewBranch = true @@ -542,10 +614,16 @@ func RepoRef() macaron.Handler { ctx.Handle(404, "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(repoRefRedirect(ctx)) + return + } } - ctx.Repo.BranchName = refName 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 |