mirror of https://github.com/go-gitea/gitea.git
Refactor RepoRefByType (#32413)
1. clarify the "filepath" could(should) contain "{ref}" 2. remove unclear RepoRefLegacy and RepoRefAny, use RepoRefUnknown to guess 3. by the way, avoid using AppURL
This commit is contained in:
parent
4a469c8e1b
commit
61c35590c7
|
@ -56,12 +56,12 @@ func GetRawFile(ctx *context.APIContext) {
|
||||||
// required: true
|
// required: true
|
||||||
// - name: filepath
|
// - name: filepath
|
||||||
// in: path
|
// in: path
|
||||||
// description: filepath of the file to get
|
// description: path of the file to get, it should be "{ref}/{filepath}". If there is no ref could be inferred, it will be treated as the default branch
|
||||||
// type: string
|
// type: string
|
||||||
// required: true
|
// required: true
|
||||||
// - name: ref
|
// - name: ref
|
||||||
// in: query
|
// in: query
|
||||||
// description: "The name of the commit/branch/tag. Default the repository’s default branch (usually master)"
|
// description: "The name of the commit/branch/tag. Default the repository’s default branch"
|
||||||
// type: string
|
// type: string
|
||||||
// required: false
|
// required: false
|
||||||
// responses:
|
// responses:
|
||||||
|
@ -109,12 +109,12 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
|
||||||
// required: true
|
// required: true
|
||||||
// - name: filepath
|
// - name: filepath
|
||||||
// in: path
|
// in: path
|
||||||
// description: filepath of the file to get
|
// description: path of the file to get, it should be "{ref}/{filepath}". If there is no ref could be inferred, it will be treated as the default branch
|
||||||
// type: string
|
// type: string
|
||||||
// required: true
|
// required: true
|
||||||
// - name: ref
|
// - name: ref
|
||||||
// in: query
|
// in: query
|
||||||
// description: "The name of the commit/branch/tag. Default the repository’s default branch (usually master)"
|
// description: "The name of the commit/branch/tag. Default the repository’s default branch"
|
||||||
// type: string
|
// type: string
|
||||||
// required: false
|
// required: false
|
||||||
// responses:
|
// responses:
|
||||||
|
|
|
@ -65,7 +65,7 @@ func goGet(ctx *context.Context) {
|
||||||
insecure = "--insecure "
|
insecure = "--insecure "
|
||||||
}
|
}
|
||||||
|
|
||||||
goGetImport := context.ComposeGoGetImport(ownerName, trimmedRepoName)
|
goGetImport := context.ComposeGoGetImport(ctx, ownerName, trimmedRepoName)
|
||||||
|
|
||||||
var cloneURL string
|
var cloneURL string
|
||||||
if setting.Repository.GoGetCloneURLProtocol == "ssh" {
|
if setting.Repository.GoGetCloneURLProtocol == "ssh" {
|
||||||
|
|
|
@ -1323,7 +1323,7 @@ func registerRoutes(m *web.Router) {
|
||||||
m.Get(".rss", feedEnabled, repo.TagsListFeedRSS)
|
m.Get(".rss", feedEnabled, repo.TagsListFeedRSS)
|
||||||
m.Get(".atom", feedEnabled, repo.TagsListFeedAtom)
|
m.Get(".atom", feedEnabled, repo.TagsListFeedAtom)
|
||||||
}, ctxDataSet("EnableFeed", setting.Other.EnableFeed),
|
}, ctxDataSet("EnableFeed", setting.Other.EnableFeed),
|
||||||
repo.MustBeNotEmpty, context.RepoRefByType(context.RepoRefTag, true))
|
repo.MustBeNotEmpty, context.RepoRefByType(context.RepoRefTag, context.RepoRefByTypeOptions{IgnoreNotExistErr: true}))
|
||||||
m.Post("/tags/delete", repo.DeleteTag, reqSignIn,
|
m.Post("/tags/delete", repo.DeleteTag, reqSignIn,
|
||||||
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef())
|
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef())
|
||||||
}, ignSignIn, context.RepoAssignment, reqRepoCodeReader)
|
}, ignSignIn, context.RepoAssignment, reqRepoCodeReader)
|
||||||
|
@ -1337,7 +1337,7 @@ func registerRoutes(m *web.Router) {
|
||||||
m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS)
|
m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS)
|
||||||
m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom)
|
m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom)
|
||||||
}, ctxDataSet("EnableFeed", setting.Other.EnableFeed),
|
}, ctxDataSet("EnableFeed", setting.Other.EnableFeed),
|
||||||
repo.MustBeNotEmpty, context.RepoRefByType(context.RepoRefTag, true))
|
repo.MustBeNotEmpty, context.RepoRefByType(context.RepoRefTag, context.RepoRefByTypeOptions{IgnoreNotExistErr: true}))
|
||||||
m.Get("/releases/attachments/{uuid}", repo.MustBeNotEmpty, repo.GetAttachment)
|
m.Get("/releases/attachments/{uuid}", repo.MustBeNotEmpty, repo.GetAttachment)
|
||||||
m.Get("/releases/download/{vTag}/{fileName}", repo.MustBeNotEmpty, repo.RedirectDownload)
|
m.Get("/releases/download/{vTag}/{fileName}", repo.MustBeNotEmpty, repo.RedirectDownload)
|
||||||
m.Group("/releases", func() {
|
m.Group("/releases", func() {
|
||||||
|
@ -1535,7 +1535,7 @@ func registerRoutes(m *web.Router) {
|
||||||
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.SingleDownloadOrLFS)
|
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.SingleDownloadOrLFS)
|
||||||
m.Get("/blob/{sha}", context.RepoRefByType(context.RepoRefBlob), repo.DownloadByIDOrLFS)
|
m.Get("/blob/{sha}", context.RepoRefByType(context.RepoRefBlob), repo.DownloadByIDOrLFS)
|
||||||
// "/*" route is deprecated, and kept for backward compatibility
|
// "/*" route is deprecated, and kept for backward compatibility
|
||||||
m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.SingleDownloadOrLFS)
|
m.Get("/*", context.RepoRefByType(context.RepoRefUnknown), repo.SingleDownloadOrLFS)
|
||||||
}, repo.MustBeNotEmpty)
|
}, repo.MustBeNotEmpty)
|
||||||
|
|
||||||
m.Group("/raw", func() {
|
m.Group("/raw", func() {
|
||||||
|
@ -1544,7 +1544,7 @@ func registerRoutes(m *web.Router) {
|
||||||
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.SingleDownload)
|
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.SingleDownload)
|
||||||
m.Get("/blob/{sha}", context.RepoRefByType(context.RepoRefBlob), repo.DownloadByID)
|
m.Get("/blob/{sha}", context.RepoRefByType(context.RepoRefBlob), repo.DownloadByID)
|
||||||
// "/*" route is deprecated, and kept for backward compatibility
|
// "/*" route is deprecated, and kept for backward compatibility
|
||||||
m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.SingleDownload)
|
m.Get("/*", context.RepoRefByType(context.RepoRefUnknown), repo.SingleDownload)
|
||||||
}, repo.MustBeNotEmpty)
|
}, repo.MustBeNotEmpty)
|
||||||
|
|
||||||
m.Group("/render", func() {
|
m.Group("/render", func() {
|
||||||
|
@ -1559,7 +1559,7 @@ func registerRoutes(m *web.Router) {
|
||||||
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.RefCommits)
|
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.RefCommits)
|
||||||
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.RefCommits)
|
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.RefCommits)
|
||||||
// "/*" route is deprecated, and kept for backward compatibility
|
// "/*" route is deprecated, and kept for backward compatibility
|
||||||
m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.RefCommits)
|
m.Get("/*", context.RepoRefByType(context.RepoRefUnknown), repo.RefCommits)
|
||||||
}, repo.MustBeNotEmpty)
|
}, repo.MustBeNotEmpty)
|
||||||
|
|
||||||
m.Group("/blame", func() {
|
m.Group("/blame", func() {
|
||||||
|
@ -1582,7 +1582,7 @@ func registerRoutes(m *web.Router) {
|
||||||
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.Home)
|
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.Home)
|
||||||
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.Home)
|
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.Home)
|
||||||
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.Home)
|
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.Home)
|
||||||
m.Get("/*", context.RepoRefByType(context.RepoRefLegacy), repo.Home) // "/*" route is deprecated, and kept for backward compatibility
|
m.Get("/*", context.RepoRefByType(context.RepoRefUnknown), repo.Home) // "/*" route is deprecated, and kept for backward compatibility
|
||||||
}, repo.SetEditorconfigIfExists)
|
}, repo.SetEditorconfigIfExists)
|
||||||
|
|
||||||
m.Get("/forks", context.RepoRef(), repo.Forks)
|
m.Get("/forks", context.RepoRef(), repo.Forks)
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"code.gitea.io/gitea/models/unit"
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/cache"
|
"code.gitea.io/gitea/modules/cache"
|
||||||
"code.gitea.io/gitea/modules/git"
|
|
||||||
"code.gitea.io/gitea/modules/gitrepo"
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
"code.gitea.io/gitea/modules/httpcache"
|
"code.gitea.io/gitea/modules/httpcache"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -306,24 +305,8 @@ func RepoRefForAPI(next http.Handler) http.Handler {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if ref := ctx.FormTrim("ref"); len(ref) > 0 {
|
// NOTICE: the "ref" here for internal usage only (e.g. woodpecker)
|
||||||
commit, err := ctx.Repo.GitRepo.GetCommit(ref)
|
refName, _ := getRefNameLegacy(ctx.Base, ctx.Repo, ctx.FormTrim("ref"))
|
||||||
if err != nil {
|
|
||||||
if git.IsErrNotExist(err) {
|
|
||||||
ctx.NotFound()
|
|
||||||
} else {
|
|
||||||
ctx.Error(http.StatusInternalServerError, "GetCommit", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Repo.Commit = commit
|
|
||||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
|
||||||
ctx.Repo.TreePath = ctx.PathParam("*")
|
|
||||||
next.ServeHTTP(w, req)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
refName := getRefName(ctx.Base, ctx.Repo, RepoRefAny)
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if ctx.Repo.GitRepo.IsBranchExist(refName) {
|
if ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/cache"
|
"code.gitea.io/gitea/modules/cache"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/gitrepo"
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
|
"code.gitea.io/gitea/modules/httplib"
|
||||||
code_indexer "code.gitea.io/gitea/modules/indexer/code"
|
code_indexer "code.gitea.io/gitea/modules/indexer/code"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
|
@ -306,11 +307,9 @@ func RetrieveTemplateRepo(ctx *Context, repo *repo_model.Repository) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComposeGoGetImport returns go-get-import meta content.
|
// ComposeGoGetImport returns go-get-import meta content.
|
||||||
func ComposeGoGetImport(owner, repo string) string {
|
func ComposeGoGetImport(ctx context.Context, owner, repo string) string {
|
||||||
/// setting.AppUrl is guaranteed to be parse as url
|
curAppURL, _ := url.Parse(httplib.GuessCurrentAppURL(ctx))
|
||||||
appURL, _ := url.Parse(setting.AppURL)
|
return path.Join(curAppURL.Host, setting.AppSubURL, url.PathEscape(owner), url.PathEscape(repo))
|
||||||
|
|
||||||
return path.Join(appURL.Host, setting.AppSubURL, url.PathEscape(owner), url.PathEscape(repo))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EarlyResponseForGoGetMeta responses appropriate go-get meta with status 200
|
// EarlyResponseForGoGetMeta responses appropriate go-get meta with status 200
|
||||||
|
@ -332,7 +331,7 @@ func EarlyResponseForGoGetMeta(ctx *Context) {
|
||||||
} else {
|
} else {
|
||||||
cloneURL = repo_model.ComposeHTTPSCloneURL(username, reponame)
|
cloneURL = repo_model.ComposeHTTPSCloneURL(username, reponame)
|
||||||
}
|
}
|
||||||
goImportContent := fmt.Sprintf("%s git %s", ComposeGoGetImport(username, reponame), cloneURL)
|
goImportContent := fmt.Sprintf("%s git %s", ComposeGoGetImport(ctx, username, reponame), cloneURL)
|
||||||
htmlMeta := fmt.Sprintf(`<meta name="go-import" content="%s">`, html.EscapeString(goImportContent))
|
htmlMeta := fmt.Sprintf(`<meta name="go-import" content="%s">`, html.EscapeString(goImportContent))
|
||||||
ctx.PlainText(http.StatusOK, htmlMeta)
|
ctx.PlainText(http.StatusOK, htmlMeta)
|
||||||
}
|
}
|
||||||
|
@ -744,7 +743,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.FormString("go-get") == "1" {
|
if ctx.FormString("go-get") == "1" {
|
||||||
ctx.Data["GoGetImport"] = ComposeGoGetImport(owner.Name, repo.Name)
|
ctx.Data["GoGetImport"] = ComposeGoGetImport(ctx, owner.Name, repo.Name)
|
||||||
fullURLPrefix := repo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(ctx.Repo.BranchName)
|
fullURLPrefix := repo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(ctx.Repo.BranchName)
|
||||||
ctx.Data["GoDocDirectory"] = fullURLPrefix + "{/dir}"
|
ctx.Data["GoDocDirectory"] = fullURLPrefix + "{/dir}"
|
||||||
ctx.Data["GoDocFile"] = fullURLPrefix + "{/dir}/{file}#L{line}"
|
ctx.Data["GoDocFile"] = fullURLPrefix + "{/dir}/{file}#L{line}"
|
||||||
|
@ -756,19 +755,11 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
|
||||||
type RepoRefType int
|
type RepoRefType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// RepoRefLegacy unknown type, make educated guess and redirect.
|
// RepoRefUnknown is for legacy support, makes the code to "guess" the ref type
|
||||||
// for backward compatibility with previous URL scheme
|
RepoRefUnknown RepoRefType = iota
|
||||||
RepoRefLegacy RepoRefType = iota
|
|
||||||
// RepoRefAny is for usage where educated guess is needed
|
|
||||||
// but redirect can not be made
|
|
||||||
RepoRefAny
|
|
||||||
// RepoRefBranch branch
|
|
||||||
RepoRefBranch
|
RepoRefBranch
|
||||||
// RepoRefTag tag
|
|
||||||
RepoRefTag
|
RepoRefTag
|
||||||
// RepoRefCommit commit
|
|
||||||
RepoRefCommit
|
RepoRefCommit
|
||||||
// RepoRefBlob blob
|
|
||||||
RepoRefBlob
|
RepoRefBlob
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -781,22 +772,6 @@ func RepoRef() func(*Context) context.CancelFunc {
|
||||||
return RepoRefByType(RepoRefBranch)
|
return RepoRefByType(RepoRefBranch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefTypeIncludesBranches returns true if ref type can be a branch
|
|
||||||
func (rt RepoRefType) RefTypeIncludesBranches() bool {
|
|
||||||
if rt == RepoRefLegacy || rt == RepoRefAny || rt == RepoRefBranch {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// RefTypeIncludesTags returns true if ref type can be a tag
|
|
||||||
func (rt RepoRefType) RefTypeIncludesTags() bool {
|
|
||||||
if rt == RepoRefLegacy || rt == RepoRefAny || rt == RepoRefTag {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool) string {
|
func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool) string {
|
||||||
refName := ""
|
refName := ""
|
||||||
parts := strings.Split(path, "/")
|
parts := strings.Split(path, "/")
|
||||||
|
@ -810,28 +785,50 @@ func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isStringLikelyCommitID(objFmt git.ObjectFormat, s string, minLength ...int) bool {
|
||||||
|
minLen := util.OptionalArg(minLength, objFmt.FullLength())
|
||||||
|
if len(s) < minLen || len(s) > objFmt.FullLength() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range s {
|
||||||
|
isHex := (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
|
||||||
|
if !isHex {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRefNameLegacy(ctx *Base, repo *Repository, optionalExtraRef ...string) (string, RepoRefType) {
|
||||||
|
extraRef := util.OptionalArg(optionalExtraRef)
|
||||||
|
reqPath := ctx.PathParam("*")
|
||||||
|
reqPath = path.Join(extraRef, reqPath)
|
||||||
|
|
||||||
|
if refName := getRefName(ctx, repo, RepoRefBranch); refName != "" {
|
||||||
|
return refName, RepoRefBranch
|
||||||
|
}
|
||||||
|
if refName := getRefName(ctx, repo, RepoRefTag); refName != "" {
|
||||||
|
return refName, RepoRefTag
|
||||||
|
}
|
||||||
|
|
||||||
|
// For legacy support only full commit sha
|
||||||
|
parts := strings.Split(reqPath, "/")
|
||||||
|
if isStringLikelyCommitID(git.ObjectFormatFromName(repo.Repository.ObjectFormatName), parts[0]) {
|
||||||
|
// FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
|
||||||
|
repo.TreePath = strings.Join(parts[1:], "/")
|
||||||
|
return parts[0], RepoRefCommit
|
||||||
|
}
|
||||||
|
|
||||||
|
if refName := getRefName(ctx, repo, RepoRefBlob); len(refName) > 0 {
|
||||||
|
return refName, RepoRefBlob
|
||||||
|
}
|
||||||
|
repo.TreePath = reqPath
|
||||||
|
return repo.Repository.DefaultBranch, RepoRefBranch
|
||||||
|
}
|
||||||
|
|
||||||
func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
|
func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
|
||||||
path := ctx.PathParam("*")
|
path := ctx.PathParam("*")
|
||||||
switch pathType {
|
switch pathType {
|
||||||
case RepoRefLegacy, RepoRefAny:
|
|
||||||
if refName := getRefName(ctx, repo, RepoRefBranch); len(refName) > 0 {
|
|
||||||
return refName
|
|
||||||
}
|
|
||||||
if refName := getRefName(ctx, repo, RepoRefTag); len(refName) > 0 {
|
|
||||||
return refName
|
|
||||||
}
|
|
||||||
// For legacy and API support only full commit sha
|
|
||||||
parts := strings.Split(path, "/")
|
|
||||||
|
|
||||||
if len(parts) > 0 && len(parts[0]) == git.ObjectFormatFromName(repo.Repository.ObjectFormatName).FullLength() {
|
|
||||||
repo.TreePath = strings.Join(parts[1:], "/")
|
|
||||||
return parts[0]
|
|
||||||
}
|
|
||||||
if refName := getRefName(ctx, repo, RepoRefBlob); len(refName) > 0 {
|
|
||||||
return refName
|
|
||||||
}
|
|
||||||
repo.TreePath = path
|
|
||||||
return repo.Repository.DefaultBranch
|
|
||||||
case RepoRefBranch:
|
case RepoRefBranch:
|
||||||
ref := getRefNameFromPath(repo, path, repo.GitRepo.IsBranchExist)
|
ref := getRefNameFromPath(repo, path, repo.GitRepo.IsBranchExist)
|
||||||
if len(ref) == 0 {
|
if len(ref) == 0 {
|
||||||
|
@ -866,13 +863,13 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
|
||||||
return getRefNameFromPath(repo, path, repo.GitRepo.IsTagExist)
|
return getRefNameFromPath(repo, path, repo.GitRepo.IsTagExist)
|
||||||
case RepoRefCommit:
|
case RepoRefCommit:
|
||||||
parts := strings.Split(path, "/")
|
parts := strings.Split(path, "/")
|
||||||
|
if isStringLikelyCommitID(repo.GetObjectFormat(), parts[0], 7) {
|
||||||
if len(parts) > 0 && len(parts[0]) >= 7 && len(parts[0]) <= repo.GetObjectFormat().FullLength() {
|
// FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
|
||||||
repo.TreePath = strings.Join(parts[1:], "/")
|
repo.TreePath = strings.Join(parts[1:], "/")
|
||||||
return parts[0]
|
return parts[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(parts) > 0 && parts[0] == headRefName {
|
if parts[0] == headRefName {
|
||||||
// HEAD ref points to last default branch commit
|
// HEAD ref points to last default branch commit
|
||||||
commit, err := repo.GitRepo.GetBranchCommit(repo.Repository.DefaultBranch)
|
commit, err := repo.GitRepo.GetBranchCommit(repo.Repository.DefaultBranch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -888,15 +885,21 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
|
||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
default:
|
default:
|
||||||
log.Error("Unrecognized path type: %v", path)
|
panic(fmt.Sprintf("Unrecognized path type: %v", pathType))
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RepoRefByTypeOptions struct {
|
||||||
|
IgnoreNotExistErr bool
|
||||||
|
}
|
||||||
|
|
||||||
// RepoRefByType handles repository reference name for a specific type
|
// RepoRefByType handles repository reference name for a specific type
|
||||||
// of repository reference
|
// of repository reference
|
||||||
func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context) context.CancelFunc {
|
func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func(*Context) context.CancelFunc {
|
||||||
|
opt := util.OptionalArg(opts)
|
||||||
return func(ctx *Context) (cancel context.CancelFunc) {
|
return func(ctx *Context) (cancel context.CancelFunc) {
|
||||||
|
refType := detectRefType
|
||||||
// Empty repository does not have reference information.
|
// Empty repository does not have reference information.
|
||||||
if ctx.Repo.Repository.IsEmpty {
|
if ctx.Repo.Repository.IsEmpty {
|
||||||
// assume the user is viewing the (non-existent) default branch
|
// assume the user is viewing the (non-existent) default branch
|
||||||
|
@ -956,7 +959,12 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||||
}
|
}
|
||||||
ctx.Repo.IsViewBranch = true
|
ctx.Repo.IsViewBranch = true
|
||||||
} else {
|
} else {
|
||||||
refName = getRefName(ctx.Base, ctx.Repo, refType)
|
guessLegacyPath := refType == RepoRefUnknown
|
||||||
|
if guessLegacyPath {
|
||||||
|
refName, refType = getRefNameLegacy(ctx.Base, ctx.Repo)
|
||||||
|
} else {
|
||||||
|
refName = getRefName(ctx.Base, ctx.Repo, refType)
|
||||||
|
}
|
||||||
ctx.Repo.RefName = refName
|
ctx.Repo.RefName = refName
|
||||||
isRenamedBranch, has := ctx.Data["IsRenamedBranch"].(bool)
|
isRenamedBranch, has := ctx.Data["IsRenamedBranch"].(bool)
|
||||||
if isRenamedBranch && has {
|
if isRenamedBranch && has {
|
||||||
|
@ -967,7 +975,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||||
return cancel
|
return cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
if refType.RefTypeIncludesBranches() && ctx.Repo.GitRepo.IsBranchExist(refName) {
|
if refType == RepoRefBranch && ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||||
ctx.Repo.IsViewBranch = true
|
ctx.Repo.IsViewBranch = true
|
||||||
ctx.Repo.BranchName = refName
|
ctx.Repo.BranchName = refName
|
||||||
|
|
||||||
|
@ -977,7 +985,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||||
return cancel
|
return cancel
|
||||||
}
|
}
|
||||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||||
} else if refType.RefTypeIncludesTags() && ctx.Repo.GitRepo.IsTagExist(refName) {
|
} else if refType == RepoRefTag && ctx.Repo.GitRepo.IsTagExist(refName) {
|
||||||
ctx.Repo.IsViewTag = true
|
ctx.Repo.IsViewTag = true
|
||||||
ctx.Repo.TagName = refName
|
ctx.Repo.TagName = refName
|
||||||
|
|
||||||
|
@ -991,7 +999,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||||
return cancel
|
return cancel
|
||||||
}
|
}
|
||||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||||
} else if len(refName) >= 7 && len(refName) <= ctx.Repo.GetObjectFormat().FullLength() {
|
} else if isStringLikelyCommitID(ctx.Repo.GetObjectFormat(), refName, 7) {
|
||||||
ctx.Repo.IsViewCommit = true
|
ctx.Repo.IsViewCommit = true
|
||||||
ctx.Repo.CommitID = refName
|
ctx.Repo.CommitID = refName
|
||||||
|
|
||||||
|
@ -1002,18 +1010,18 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
|
||||||
}
|
}
|
||||||
// If short commit ID add canonical link header
|
// If short commit ID add canonical link header
|
||||||
if len(refName) < ctx.Repo.GetObjectFormat().FullLength() {
|
if len(refName) < ctx.Repo.GetObjectFormat().FullLength() {
|
||||||
ctx.RespHeader().Set("Link", fmt.Sprintf("<%s>; rel=\"canonical\"",
|
canonicalURL := util.URLJoin(httplib.GuessCurrentAppURL(ctx), strings.Replace(ctx.Req.URL.RequestURI(), util.PathEscapeSegments(refName), url.PathEscape(ctx.Repo.Commit.ID.String()), 1))
|
||||||
util.URLJoin(setting.AppURL, strings.Replace(ctx.Req.URL.RequestURI(), util.PathEscapeSegments(refName), url.PathEscape(ctx.Repo.Commit.ID.String()), 1))))
|
ctx.RespHeader().Set("Link", fmt.Sprintf(`<%s>; rel="canonical"`, canonicalURL))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if len(ignoreNotExistErr) > 0 && ignoreNotExistErr[0] {
|
if opt.IgnoreNotExistErr {
|
||||||
return cancel
|
return cancel
|
||||||
}
|
}
|
||||||
ctx.NotFound("RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
|
ctx.NotFound("RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
|
||||||
return cancel
|
return cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
if refType == RepoRefLegacy {
|
if guessLegacyPath {
|
||||||
// redirect from old URL scheme to new URL scheme
|
// redirect from old URL scheme to new URL scheme
|
||||||
prefix := strings.TrimPrefix(setting.AppSubURL+strings.ToLower(strings.TrimSuffix(ctx.Req.URL.Path, ctx.PathParam("*"))), strings.ToLower(ctx.Repo.RepoLink))
|
prefix := strings.TrimPrefix(setting.AppSubURL+strings.ToLower(strings.TrimSuffix(ctx.Req.URL.Path, ctx.PathParam("*"))), strings.ToLower(ctx.Repo.RepoLink))
|
||||||
redirect := path.Join(
|
redirect := path.Join(
|
||||||
|
|
|
@ -10727,14 +10727,14 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "filepath of the file to get",
|
"description": "path of the file to get, it should be \"{ref}/{filepath}\". If there is no ref could be inferred, it will be treated as the default branch",
|
||||||
"name": "filepath",
|
"name": "filepath",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The name of the commit/branch/tag. Default the repository’s default branch (usually master)",
|
"description": "The name of the commit/branch/tag. Default the repository’s default branch",
|
||||||
"name": "ref",
|
"name": "ref",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
}
|
}
|
||||||
|
@ -12818,14 +12818,14 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "filepath of the file to get",
|
"description": "path of the file to get, it should be \"{ref}/{filepath}\". If there is no ref could be inferred, it will be treated as the default branch",
|
||||||
"name": "filepath",
|
"name": "filepath",
|
||||||
"in": "path",
|
"in": "path",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The name of the commit/branch/tag. Default the repository’s default branch (usually master)",
|
"description": "The name of the commit/branch/tag. Default the repository’s default branch",
|
||||||
"name": "ref",
|
"name": "ref",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,18 +49,18 @@ func TestLinksNoLogin(t *testing.T) {
|
||||||
func TestRedirectsNoLogin(t *testing.T) {
|
func TestRedirectsNoLogin(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
|
||||||
redirects := map[string]string{
|
redirects := []struct{ from, to string }{
|
||||||
"/user2/repo1/commits/master": "/user2/repo1/commits/branch/master",
|
{"/user2/repo1/commits/master", "/user2/repo1/commits/branch/master"},
|
||||||
"/user2/repo1/src/master": "/user2/repo1/src/branch/master",
|
{"/user2/repo1/src/master", "/user2/repo1/src/branch/master"},
|
||||||
"/user2/repo1/src/master/file.txt": "/user2/repo1/src/branch/master/file.txt",
|
{"/user2/repo1/src/master/file.txt", "/user2/repo1/src/branch/master/file.txt"},
|
||||||
"/user2/repo1/src/master/directory/file.txt": "/user2/repo1/src/branch/master/directory/file.txt",
|
{"/user2/repo1/src/master/directory/file.txt", "/user2/repo1/src/branch/master/directory/file.txt"},
|
||||||
"/user/avatar/Ghost/-1": "/assets/img/avatar_default.png",
|
{"/user/avatar/Ghost/-1", "/assets/img/avatar_default.png"},
|
||||||
"/api/v1/swagger": "/api/swagger",
|
{"/api/v1/swagger", "/api/swagger"},
|
||||||
}
|
}
|
||||||
for link, redirectLink := range redirects {
|
for _, c := range redirects {
|
||||||
req := NewRequest(t, "GET", link)
|
req := NewRequest(t, "GET", c.from)
|
||||||
resp := MakeRequest(t, req, http.StatusSeeOther)
|
resp := MakeRequest(t, req, http.StatusSeeOther)
|
||||||
assert.EqualValues(t, path.Join(setting.AppSubURL, redirectLink), test.RedirectURL(resp))
|
assert.EqualValues(t, path.Join(setting.AppSubURL, c.to), test.RedirectURL(resp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue