mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	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
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user