Skip to content

Commit

Permalink
refactor ref type
Browse files Browse the repository at this point in the history
  • Loading branch information
lunny committed Jan 14, 2025
1 parent 98d7e04 commit e2cc853
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 81 deletions.
15 changes: 15 additions & 0 deletions modules/git/ref.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"regexp"
"strings"

"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)

Expand Down Expand Up @@ -84,6 +85,20 @@ func RefNameFromCommit(shortName string) RefName {
return RefName(shortName)
}

func RefNameFromTypeAndShortName(tp RefType, shortName string) RefName {
switch tp {
case RefTypeBranch:
return RefNameFromBranch(shortName)
case RefTypeTag:
return RefNameFromTag(shortName)
case RefTypeCommit:
return RefNameFromCommit(shortName)
default:
setting.PanicInDevOrTesting("Unknown RefType: %v", tp)
return ""
}
}

func (ref RefName) String() string {
return string(ref)
}
Expand Down
3 changes: 2 additions & 1 deletion routers/web/repo/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
func FindFiles(ctx *context.Context) {
path := ctx.PathParam("*")
ctx.Data["TreeLink"] = ctx.Repo.RepoLink + "/src/" + util.PathEscapeSegments(path)
ctx.Data["DataLink"] = ctx.Repo.RepoLink + "/tree-list/" + util.PathEscapeSegments(path)
ctx.Data["DataLink"] = ctx.Repo.RepoLink + "/tree-list/" + util.PathEscapeSegments(path) +
"?ref_type=" + ctx.FormTrim("ref_type") + "&ref_name=" + ctx.FormTrim("ref_name")
ctx.HTML(http.StatusOK, tplFindFiles)
}
69 changes: 34 additions & 35 deletions routers/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/metrics"
"code.gitea.io/gitea/modules/public"
Expand Down Expand Up @@ -1156,11 +1157,9 @@ func registerRoutes(m *web.Router) {

m.Group("/{username}/{reponame}", func() {
m.Get("/find/*", repo.FindFiles)
m.Group("/tree-list", func() {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.TreeList)
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.TreeList)
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.TreeList)
})
m.Get("/find", repo.FindFiles)
m.Get("/tree-list/*", context.RepoRefByQueries(), repo.TreeList)
m.Get("/tree-list", context.RepoRefByQueries(), repo.TreeList)
m.Get("/compare", repo.MustBeNotEmpty, repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.CompareDiff)
m.Combo("/compare/*", repo.MustBeNotEmpty, repo.SetEditorconfigIfExists).
Get(repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.CompareDiff).
Expand Down Expand Up @@ -1313,9 +1312,9 @@ func registerRoutes(m *web.Router) {

m.Group("/branches", func() {
m.Group("/_new", func() {
m.Post("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.CreateBranch)
m.Post("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.CreateBranch)
m.Post("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.CreateBranch)
m.Post("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.CreateBranch)
m.Post("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.CreateBranch)
m.Post("/commit/*", context.RepoRefByType(git.RefTypeCommit), repo.CreateBranch)
}, web.Bind(forms.NewBranchForm{}))
m.Post("/delete", repo.DeleteBranchPost)
m.Post("/restore", repo.RestoreBranchPost)
Expand All @@ -1334,7 +1333,7 @@ func registerRoutes(m *web.Router) {
m.Get(".rss", feedEnabled, repo.TagsListFeedRSS)
m.Get(".atom", feedEnabled, repo.TagsListFeedAtom)
}, ctxDataSet("EnableFeed", setting.Other.EnableFeed),
repo.MustBeNotEmpty, context.RepoRefByType(context.RepoRefTag, context.RepoRefByTypeOptions{IgnoreNotExistErr: true}))
repo.MustBeNotEmpty, context.RepoRefByType(git.RefTypeTag, context.RepoRefByTypeOptions{IgnoreNotExistErr: true}))
m.Post("/tags/delete", repo.DeleteTag, reqSignIn,
repo.MustBeNotEmpty, context.RepoMustNotBeArchived(), reqRepoCodeWriter, context.RepoRef())
}, optSignIn, context.RepoAssignment, reqRepoCodeReader)
Expand All @@ -1348,7 +1347,7 @@ func registerRoutes(m *web.Router) {
m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS)
m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom)
}, ctxDataSet("EnableFeed", setting.Other.EnableFeed),
repo.MustBeNotEmpty, context.RepoRefByType(context.RepoRefTag, context.RepoRefByTypeOptions{IgnoreNotExistErr: true}))
repo.MustBeNotEmpty, context.RepoRefByType(git.RefTypeTag, context.RepoRefByTypeOptions{IgnoreNotExistErr: true}))
m.Get("/releases/attachments/{uuid}", repo.MustBeNotEmpty, repo.GetAttachment)
m.Get("/releases/download/{vTag}/{fileName}", repo.MustBeNotEmpty, repo.RedirectDownload)
m.Group("/releases", func() {
Expand Down Expand Up @@ -1521,42 +1520,42 @@ func registerRoutes(m *web.Router) {
}, repo.MustBeNotEmpty, context.RepoRef())

m.Group("/media", func() {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.SingleDownloadOrLFS)
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.SingleDownloadOrLFS)
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.SingleDownloadOrLFS)
m.Get("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.SingleDownloadOrLFS)
m.Get("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.SingleDownloadOrLFS)
m.Get("/commit/*", context.RepoRefByType(git.RefTypeCommit), repo.SingleDownloadOrLFS)
m.Get("/blob/{sha}", repo.DownloadByIDOrLFS)
// "/*" route is deprecated, and kept for backward compatibility
m.Get("/*", context.RepoRefByType(context.RepoRefUnknown), repo.SingleDownloadOrLFS)
m.Get("/*", context.RepoRefByType(""), repo.SingleDownloadOrLFS)
}, repo.MustBeNotEmpty)

m.Group("/raw", func() {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.SingleDownload)
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.SingleDownload)
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.SingleDownload)
m.Get("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.SingleDownload)
m.Get("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.SingleDownload)
m.Get("/commit/*", context.RepoRefByType(git.RefTypeCommit), repo.SingleDownload)
m.Get("/blob/{sha}", repo.DownloadByID)
// "/*" route is deprecated, and kept for backward compatibility
m.Get("/*", context.RepoRefByType(context.RepoRefUnknown), repo.SingleDownload)
m.Get("/*", context.RepoRefByType(""), repo.SingleDownload)
}, repo.MustBeNotEmpty)

m.Group("/render", func() {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.RenderFile)
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.RenderFile)
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.RenderFile)
m.Get("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.RenderFile)
m.Get("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.RenderFile)
m.Get("/commit/*", context.RepoRefByType(git.RefTypeCommit), repo.RenderFile)
m.Get("/blob/{sha}", repo.RenderFile)
}, repo.MustBeNotEmpty)

m.Group("/commits", func() {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.RefCommits)
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.RefCommits)
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.RefCommits)
m.Get("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.RefCommits)
m.Get("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.RefCommits)
m.Get("/commit/*", context.RepoRefByType(git.RefTypeCommit), repo.RefCommits)
// "/*" route is deprecated, and kept for backward compatibility
m.Get("/*", context.RepoRefByType(context.RepoRefUnknown), repo.RefCommits)
m.Get("/*", context.RepoRefByType(""), repo.RefCommits)
}, repo.MustBeNotEmpty)

m.Group("/blame", func() {
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.RefBlame)
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.RefBlame)
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.RefBlame)
m.Get("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.RefBlame)
m.Get("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.RefBlame)
m.Get("/commit/*", context.RepoRefByType(git.RefTypeCommit), repo.RefBlame)
}, repo.MustBeNotEmpty)

m.Get("/blob_excerpt/{sha}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ExcerptBlob)
Expand All @@ -1568,20 +1567,20 @@ func registerRoutes(m *web.Router) {
m.Get("/cherry-pick/{sha:([a-f0-9]{7,64})$}", repo.SetEditorconfigIfExists, repo.CherryPick)
}, repo.MustBeNotEmpty, context.RepoRef())

m.Get("/rss/branch/*", context.RepoRefByType(context.RepoRefBranch), feedEnabled, feed.RenderBranchFeed)
m.Get("/atom/branch/*", context.RepoRefByType(context.RepoRefBranch), feedEnabled, feed.RenderBranchFeed)
m.Get("/rss/branch/*", context.RepoRefByType(git.RefTypeBranch), feedEnabled, feed.RenderBranchFeed)
m.Get("/atom/branch/*", context.RepoRefByType(git.RefTypeBranch), feedEnabled, feed.RenderBranchFeed)

m.Group("/src", func() {
m.Get("", func(ctx *context.Context) { ctx.Redirect(ctx.Repo.RepoLink) }) // there is no "{owner}/{repo}/src" page, so redirect to "{owner}/{repo}" to avoid 404
m.Get("/branch/*", context.RepoRefByType(context.RepoRefBranch), repo.Home)
m.Get("/tag/*", context.RepoRefByType(context.RepoRefTag), repo.Home)
m.Get("/commit/*", context.RepoRefByType(context.RepoRefCommit), repo.Home)
m.Get("/*", context.RepoRefByType(context.RepoRefUnknown), repo.Home) // "/*" route is deprecated, and kept for backward compatibility
m.Get("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.Home)
m.Get("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.Home)
m.Get("/commit/*", context.RepoRefByType(git.RefTypeCommit), repo.Home)
m.Get("/*", context.RepoRefByType(""), repo.Home) // "/*" route is deprecated, and kept for backward compatibility
}, repo.SetEditorconfigIfExists)

m.Get("/forks", context.RepoRef(), repo.Forks)
m.Get("/commit/{sha:([a-f0-9]{7,64})}.{ext:patch|diff}", repo.MustBeNotEmpty, repo.RawDiff)
m.Post("/lastcommit/*", context.RepoRefByType(context.RepoRefCommit), repo.LastCommit)
m.Post("/lastcommit/*", context.RepoRefByType(git.RefTypeCommit), repo.LastCommit)
}, optSignIn, context.RepoAssignment, reqRepoCodeReader)
// end "/{username}/{reponame}": repo code

Expand Down
114 changes: 70 additions & 44 deletions services/context/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -677,24 +677,13 @@ func RepoAssignment(ctx *Context) {
}
}

// RepoRefType type of repo reference
type RepoRefType int

const (
// RepoRefUnknown is for legacy support, makes the code to "guess" the ref type
RepoRefUnknown RepoRefType = iota
RepoRefBranch
RepoRefTag
RepoRefCommit
)

const headRefName = "HEAD"

// RepoRef handles repository reference names when the ref name is not
// explicitly given
func RepoRef() func(*Context) {
// since no ref name is explicitly specified, ok to just use branch
return RepoRefByType(RepoRefBranch)
return RepoRefByType(git.RefTypeBranch)
}

func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool) string {
Expand All @@ -710,29 +699,29 @@ func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool
return ""
}

func getRefNameLegacy(ctx *Base, repo *Repository, reqPath, extraRef string) (string, RepoRefType) {
func getRefNameLegacy(ctx *Base, repo *Repository, reqPath, extraRef string) (string, git.RefType) {
reqRefPath := path.Join(extraRef, reqPath)
reqRefPathParts := strings.Split(reqRefPath, "/")
if refName := getRefName(ctx, repo, reqRefPath, RepoRefBranch); refName != "" {
return refName, RepoRefBranch
if refName := getRefName(ctx, repo, reqRefPath, git.RefTypeBranch); refName != "" {
return refName, git.RefTypeBranch
}
if refName := getRefName(ctx, repo, reqRefPath, RepoRefTag); refName != "" {
return refName, RepoRefTag
if refName := getRefName(ctx, repo, reqRefPath, git.RefTypeTag); refName != "" {
return refName, git.RefTypeTag
}
if git.IsStringLikelyCommitID(git.ObjectFormatFromName(repo.Repository.ObjectFormatName), reqRefPathParts[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(reqRefPathParts[1:], "/")
return reqRefPathParts[0], RepoRefCommit
return reqRefPathParts[0], git.RefTypeCommit
}
// FIXME: the old code falls back to default branch if "ref" doesn't exist, there could be an edge case:
// "README?ref=no-such" would read the README file from the default branch, but the user might expect a 404
repo.TreePath = reqPath
return repo.Repository.DefaultBranch, RepoRefBranch
return repo.Repository.DefaultBranch, git.RefTypeBranch
}

func getRefName(ctx *Base, repo *Repository, path string, pathType RepoRefType) string {
switch pathType {
case RepoRefBranch:
func getRefName(ctx *Base, repo *Repository, path string, refType git.RefType) string {
switch refType {
case git.RefTypeBranch:
ref := getRefNameFromPath(repo, path, repo.GitRepo.IsBranchExist)
if len(ref) == 0 {
// check if ref is HEAD
Expand Down Expand Up @@ -762,9 +751,9 @@ func getRefName(ctx *Base, repo *Repository, path string, pathType RepoRefType)
}

return ref
case RepoRefTag:
case git.RefTypeTag:
return getRefNameFromPath(repo, path, repo.GitRepo.IsTagExist)
case RepoRefCommit:
case git.RefTypeCommit:
parts := strings.Split(path, "/")
if git.IsStringLikelyCommitID(repo.GetObjectFormat(), parts[0], 7) {
// FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
Expand All @@ -782,7 +771,7 @@ func getRefName(ctx *Base, repo *Repository, path string, pathType RepoRefType)
return commit.ID.String()
}
default:
panic(fmt.Sprintf("Unrecognized path type: %v", pathType))
panic(fmt.Sprintf("Unrecognized ref type: %v", refType))
}
return ""
}
Expand All @@ -791,23 +780,9 @@ type RepoRefByTypeOptions struct {
IgnoreNotExistErr bool
}

func repoRefFullName(shortName string, typ RepoRefType) git.RefName {
switch typ {
case RepoRefBranch:
return git.RefNameFromBranch(shortName)
case RepoRefTag:
return git.RefNameFromTag(shortName)
case RepoRefCommit:
return git.RefNameFromCommit(shortName)
default:
setting.PanicInDevOrTesting("Unknown RepoRefType: %v", typ)
return git.RefNameFromBranch("main") // just a dummy result, it shouldn't happen
}
}

// RepoRefByType handles repository reference name for a specific type
// of repository reference
func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func(*Context) {
func RepoRefByType(detectRefType git.RefType, opts ...RepoRefByTypeOptions) func(*Context) {
opt := util.OptionalArg(opts)
return func(ctx *Context) {
var err error
Expand Down Expand Up @@ -861,13 +836,13 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
}
ctx.Repo.IsViewBranch = true
} else { // there is a path in request
guessLegacyPath := refType == RepoRefUnknown
guessLegacyPath := refType == ""
if guessLegacyPath {
refShortName, refType = getRefNameLegacy(ctx.Base, ctx.Repo, reqPath, "")
} else {
refShortName = getRefName(ctx.Base, ctx.Repo, reqPath, refType)
}
ctx.Repo.RefFullName = repoRefFullName(refShortName, refType)
ctx.Repo.RefFullName = git.RefNameFromTypeAndShortName(refType, refShortName)
isRenamedBranch, has := ctx.Data["IsRenamedBranch"].(bool)
if isRenamedBranch && has {
renamedBranchName := ctx.Data["RenamedBranchName"].(string)
Expand All @@ -877,7 +852,7 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
return
}

if refType == RepoRefBranch && ctx.Repo.GitRepo.IsBranchExist(refShortName) {
if refType == git.RefTypeBranch && ctx.Repo.GitRepo.IsBranchExist(refShortName) {
ctx.Repo.IsViewBranch = true
ctx.Repo.BranchName = refShortName
ctx.Repo.RefFullName = git.RefNameFromBranch(refShortName)
Expand All @@ -888,7 +863,7 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
return
}
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
} else if refType == RepoRefTag && ctx.Repo.GitRepo.IsTagExist(refShortName) {
} else if refType == git.RefTypeTag && ctx.Repo.GitRepo.IsTagExist(refShortName) {
ctx.Repo.IsViewTag = true
ctx.Repo.RefFullName = git.RefNameFromTag(refShortName)
ctx.Repo.TagName = refShortName
Expand Down Expand Up @@ -964,6 +939,57 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
}
}

func RepoRefByQueries() func(ctx *Context) {
return func(ctx *Context) {
if ctx.Repo.Repository.IsEmpty {
// assume the user is viewing the (non-existent) default branch
ctx.Repo.IsViewBranch = true
ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
ctx.Repo.RefFullName = git.RefNameFromBranch(ctx.Repo.BranchName)
return
}

var err error
if ctx.Repo.GitRepo == nil {
ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository)
if err != nil {
ctx.ServerError(fmt.Sprintf("Open Repository %v failed", ctx.Repo.Repository.FullName()), err)
return
}
}

ctx.Repo.RefFullName = git.RefNameFromTypeAndShortName(git.RefType(ctx.FormTrim("ref_type")), ctx.FormTrim("ref_name"))
if ctx.Repo.RefFullName == "" {
ctx.Error(http.StatusBadRequest, "invalid ref type or name")
return
}

switch ctx.Repo.RefFullName.RefType() {
case git.RefTypeBranch:
ctx.Repo.IsViewBranch = true
ctx.Repo.BranchName = ctx.Repo.RefFullName.ShortName()
case git.RefTypeTag:
ctx.Repo.IsViewTag = true
ctx.Repo.TagName = ctx.Repo.RefFullName.ShortName()
case git.RefTypeCommit:
ctx.Repo.IsViewCommit = true
ctx.Repo.CommitID = ctx.Repo.RefFullName.ShortName()
}

ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(ctx.Repo.RefFullName.String())
if err != nil {
if git.IsErrNotExist(err) {
ctx.NotFound("GetCommit", err)
} else {
ctx.ServerError("GetCommit", err)
}
return
}
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
ctx.Repo.TreePath = ctx.PathParam("*")
}
}

// GitHookService checks if repository Git hooks service has been enabled.
func GitHookService() func(ctx *Context) {
return func(ctx *Context) {
Expand Down
2 changes: 1 addition & 1 deletion templates/repo/home.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@

<!-- Show go to file if on home page -->
{{if $isTreePathRoot}}
<a href="{{.Repository.Link}}/find/{{.RefTypeNameSubURL}}" class="ui compact basic button">{{ctx.Locale.Tr "repo.find_file.go_to_file"}}</a>
<a href="{{.Repository.Link}}/find/{{.TreePath}}?ref_type={{.RefFullName.RefType}}&ref_name={{.RefFullName.ShortName}}" class="ui compact basic button">{{ctx.Locale.Tr "repo.find_file.go_to_file"}}</a>
{{end}}

{{if and .CanWriteCode .IsViewBranch (not .Repository.IsMirror) (not .Repository.IsArchived) (not .IsViewFile)}}
Expand Down

0 comments on commit e2cc853

Please sign in to comment.