mirror of
https://github.com/go-gitea/gitea
synced 2025-07-22 18:28:37 +00:00
Refactor context RefName and RepoAssignment (#33226)
The `ctx.Repo.RefName` was used to be a "short name", it causes a lot of ambiguity. This PR does some refactoring and use `RefFullName` to replace the legacy `RefName`, and simplify RepoAssignment
This commit is contained in:
@@ -58,10 +58,10 @@ type Repository struct {
|
||||
IsViewTag bool
|
||||
IsViewCommit bool
|
||||
|
||||
RefName string
|
||||
BranchName string
|
||||
TagName string
|
||||
TreePath string
|
||||
RefFullName git.RefName
|
||||
BranchName string
|
||||
TagName string
|
||||
TreePath string
|
||||
|
||||
// Commit it is always set to the commit for the branch or tag
|
||||
Commit *git.Commit
|
||||
@@ -392,33 +392,25 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
|
||||
|
||||
// RepoAssignment returns a middleware to handle repository assignment
|
||||
func RepoAssignment(ctx *Context) {
|
||||
if _, repoAssignmentOnce := ctx.Data["repoAssignmentExecuted"]; repoAssignmentOnce {
|
||||
// FIXME: it should panic in dev/test modes to have a clear behavior
|
||||
if !setting.IsProd || setting.IsInTesting {
|
||||
panic("RepoAssignment should not be executed twice")
|
||||
}
|
||||
return
|
||||
if ctx.Data["Repository"] != nil {
|
||||
setting.PanicInDevOrTesting("RepoAssignment should not be executed twice")
|
||||
}
|
||||
ctx.Data["repoAssignmentExecuted"] = true
|
||||
|
||||
var (
|
||||
owner *user_model.User
|
||||
err error
|
||||
)
|
||||
|
||||
var err error
|
||||
userName := ctx.PathParam("username")
|
||||
repoName := ctx.PathParam("reponame")
|
||||
repoName = strings.TrimSuffix(repoName, ".git")
|
||||
if setting.Other.EnableFeed {
|
||||
ctx.Data["EnableFeed"] = true
|
||||
repoName = strings.TrimSuffix(repoName, ".rss")
|
||||
repoName = strings.TrimSuffix(repoName, ".atom")
|
||||
}
|
||||
|
||||
// Check if the user is the same as the repository owner
|
||||
if ctx.IsSigned && ctx.Doer.LowerName == strings.ToLower(userName) {
|
||||
owner = ctx.Doer
|
||||
ctx.Repo.Owner = ctx.Doer
|
||||
} else {
|
||||
owner, err = user_model.GetUserByName(ctx, userName)
|
||||
ctx.Repo.Owner, err = user_model.GetUserByName(ctx, userName)
|
||||
if err != nil {
|
||||
if user_model.IsErrUserNotExist(err) {
|
||||
// go-get does not support redirects
|
||||
@@ -441,8 +433,7 @@ func RepoAssignment(ctx *Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx.Repo.Owner = owner
|
||||
ctx.ContextUser = owner
|
||||
ctx.ContextUser = ctx.Repo.Owner
|
||||
ctx.Data["ContextUser"] = ctx.ContextUser
|
||||
|
||||
// redirect link to wiki
|
||||
@@ -466,10 +457,10 @@ func RepoAssignment(ctx *Context) {
|
||||
}
|
||||
|
||||
// Get repository.
|
||||
repo, err := repo_model.GetRepositoryByName(ctx, owner.ID, repoName)
|
||||
repo, err := repo_model.GetRepositoryByName(ctx, ctx.Repo.Owner.ID, repoName)
|
||||
if err != nil {
|
||||
if repo_model.IsErrRepoNotExist(err) {
|
||||
redirectRepoID, err := repo_model.LookupRedirect(ctx, owner.ID, repoName)
|
||||
redirectRepoID, err := repo_model.LookupRedirect(ctx, ctx.Repo.Owner.ID, repoName)
|
||||
if err == nil {
|
||||
RedirectToRepo(ctx.Base, redirectRepoID)
|
||||
} else if repo_model.IsErrRedirectNotExist(err) {
|
||||
@@ -486,7 +477,7 @@ func RepoAssignment(ctx *Context) {
|
||||
}
|
||||
return
|
||||
}
|
||||
repo.Owner = owner
|
||||
repo.Owner = ctx.Repo.Owner
|
||||
|
||||
repoAssignment(ctx, repo)
|
||||
if ctx.Written() {
|
||||
@@ -495,11 +486,7 @@ func RepoAssignment(ctx *Context) {
|
||||
|
||||
ctx.Repo.RepoLink = repo.Link()
|
||||
ctx.Data["RepoLink"] = ctx.Repo.RepoLink
|
||||
|
||||
if setting.Other.EnableFeed {
|
||||
ctx.Data["EnableFeed"] = true
|
||||
ctx.Data["FeedURL"] = ctx.Repo.RepoLink
|
||||
}
|
||||
ctx.Data["FeedURL"] = ctx.Repo.RepoLink
|
||||
|
||||
unit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeExternalTracker)
|
||||
if err == nil {
|
||||
@@ -526,7 +513,7 @@ func RepoAssignment(ctx *Context) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Title"] = owner.Name + "/" + repo.Name
|
||||
ctx.Data["Title"] = repo.Owner.Name + "/" + repo.Name
|
||||
ctx.Data["Repository"] = repo
|
||||
ctx.Data["Owner"] = ctx.Repo.Repository.Owner
|
||||
ctx.Data["CanWriteCode"] = ctx.Repo.CanWrite(unit_model.TypeCode)
|
||||
@@ -596,7 +583,6 @@ func RepoAssignment(ctx *Context) {
|
||||
|
||||
// Disable everything when the repo is being created
|
||||
if ctx.Repo.Repository.IsBeingCreated() || ctx.Repo.Repository.IsBroken() {
|
||||
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
|
||||
if !isHomeOrSettings {
|
||||
ctx.Redirect(ctx.Repo.RepoLink)
|
||||
}
|
||||
@@ -604,9 +590,7 @@ func RepoAssignment(ctx *Context) {
|
||||
}
|
||||
|
||||
if ctx.Repo.GitRepo != nil {
|
||||
if !setting.IsProd || setting.IsInTesting {
|
||||
panic("RepoAssignment: GitRepo should be nil")
|
||||
}
|
||||
setting.PanicInDevOrTesting("RepoAssignment: GitRepo should be nil")
|
||||
_ = ctx.Repo.GitRepo.Close()
|
||||
ctx.Repo.GitRepo = nil
|
||||
}
|
||||
@@ -616,7 +600,6 @@ func RepoAssignment(ctx *Context) {
|
||||
if strings.Contains(err.Error(), "repository does not exist") || strings.Contains(err.Error(), "no such file or directory") {
|
||||
log.Error("Repository %-v has a broken repository on the file system: %s Error: %v", ctx.Repo.Repository, ctx.Repo.Repository.RepoPath(), err)
|
||||
ctx.Repo.Repository.MarkAsBrokenEmpty()
|
||||
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
|
||||
// Only allow access to base of repo or settings
|
||||
if !isHomeOrSettings {
|
||||
ctx.Redirect(ctx.Repo.RepoLink)
|
||||
@@ -629,7 +612,6 @@ func RepoAssignment(ctx *Context) {
|
||||
|
||||
// Stop at this point when the repo is empty.
|
||||
if ctx.Repo.Repository.IsEmpty {
|
||||
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
|
||||
return
|
||||
}
|
||||
|
||||
@@ -655,22 +637,6 @@ func RepoAssignment(ctx *Context) {
|
||||
|
||||
ctx.Data["BranchesCount"] = branchesTotal
|
||||
|
||||
// If no branch is set in the request URL, try to guess a default one.
|
||||
if len(ctx.Repo.BranchName) == 0 {
|
||||
if len(ctx.Repo.Repository.DefaultBranch) > 0 && ctx.Repo.GitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
|
||||
ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
|
||||
} else {
|
||||
ctx.Repo.BranchName, _ = gitrepo.GetDefaultBranch(ctx, ctx.Repo.Repository)
|
||||
if ctx.Repo.BranchName == "" {
|
||||
// If it still can't get a default branch, fall back to default branch from setting.
|
||||
// Something might be wrong. Either site admin should fix the repo sync or Gitea should fix a potential bug.
|
||||
ctx.Repo.BranchName = setting.Repository.DefaultBranch
|
||||
}
|
||||
}
|
||||
ctx.Repo.RefName = ctx.Repo.BranchName
|
||||
}
|
||||
ctx.Data["BranchName"] = ctx.Repo.BranchName
|
||||
|
||||
// People who have push access or have forked repository can propose a new pull request.
|
||||
canPush := ctx.Repo.CanWrite(unit_model.TypeCode) ||
|
||||
(ctx.IsSigned && repo_model.HasForkedRepo(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID))
|
||||
@@ -713,7 +679,7 @@ func RepoAssignment(ctx *Context) {
|
||||
}
|
||||
|
||||
if ctx.FormString("go-get") == "1" {
|
||||
ctx.Data["GoGetImport"] = ComposeGoGetImport(ctx, owner.Name, repo.Name)
|
||||
ctx.Data["GoGetImport"] = ComposeGoGetImport(ctx, repo.Owner.Name, repo.Name)
|
||||
fullURLPrefix := repo.HTMLURL() + "/src/branch/" + util.PathEscapeSegments(ctx.Repo.BranchName)
|
||||
ctx.Data["GoDocDirectory"] = fullURLPrefix + "{/dir}"
|
||||
ctx.Data["GoDocFile"] = fullURLPrefix + "{/dir}/{file}#L{line}"
|
||||
@@ -844,26 +810,39 @@ 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) {
|
||||
opt := util.OptionalArg(opts)
|
||||
return func(ctx *Context) {
|
||||
var err error
|
||||
refType := detectRefType
|
||||
// Empty repository does not have reference information.
|
||||
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)
|
||||
// these variables are used by the template to "add/upload" new files
|
||||
ctx.Data["BranchName"] = ctx.Repo.BranchName
|
||||
ctx.Data["TreePath"] = ""
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
refName string
|
||||
err error
|
||||
)
|
||||
|
||||
if ctx.Repo.GitRepo == nil {
|
||||
ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository)
|
||||
if err != nil {
|
||||
@@ -873,22 +852,23 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
|
||||
}
|
||||
|
||||
// Get default branch.
|
||||
var refShortName string
|
||||
reqPath := ctx.PathParam("*")
|
||||
if reqPath == "" {
|
||||
refName = ctx.Repo.Repository.DefaultBranch
|
||||
if !ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||
refShortName = ctx.Repo.Repository.DefaultBranch
|
||||
if !ctx.Repo.GitRepo.IsBranchExist(refShortName) {
|
||||
brs, _, err := ctx.Repo.GitRepo.GetBranches(0, 1)
|
||||
if err == nil && len(brs) != 0 {
|
||||
refName = brs[0].Name
|
||||
refShortName = brs[0].Name
|
||||
} else if len(brs) == 0 {
|
||||
log.Error("No branches in non-empty repository %s", ctx.Repo.GitRepo.Path)
|
||||
} else {
|
||||
log.Error("GetBranches error: %v", err)
|
||||
}
|
||||
}
|
||||
ctx.Repo.RefName = refName
|
||||
ctx.Repo.BranchName = refName
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
|
||||
ctx.Repo.RefFullName = git.RefNameFromBranch(refShortName)
|
||||
ctx.Repo.BranchName = refShortName
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refShortName)
|
||||
if err == nil {
|
||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||
} else if strings.Contains(err.Error(), "fatal: not a git repository") || strings.Contains(err.Error(), "object does not exist") {
|
||||
@@ -902,35 +882,37 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
|
||||
} else { // there is a path in request
|
||||
guessLegacyPath := refType == RepoRefUnknown
|
||||
if guessLegacyPath {
|
||||
refName, refType = getRefNameLegacy(ctx.Base, ctx.Repo, reqPath, "")
|
||||
refShortName, refType = getRefNameLegacy(ctx.Base, ctx.Repo, reqPath, "")
|
||||
} else {
|
||||
refName = getRefName(ctx.Base, ctx.Repo, reqPath, refType)
|
||||
refShortName = getRefName(ctx.Base, ctx.Repo, reqPath, refType)
|
||||
}
|
||||
ctx.Repo.RefName = refName
|
||||
ctx.Repo.RefFullName = repoRefFullName(refShortName, refType)
|
||||
isRenamedBranch, has := ctx.Data["IsRenamedBranch"].(bool)
|
||||
if isRenamedBranch && has {
|
||||
renamedBranchName := ctx.Data["RenamedBranchName"].(string)
|
||||
ctx.Flash.Info(ctx.Tr("repo.branch.renamed", refName, renamedBranchName))
|
||||
link := setting.AppSubURL + strings.Replace(ctx.Req.URL.EscapedPath(), util.PathEscapeSegments(refName), util.PathEscapeSegments(renamedBranchName), 1)
|
||||
ctx.Flash.Info(ctx.Tr("repo.branch.renamed", refShortName, renamedBranchName))
|
||||
link := setting.AppSubURL + strings.Replace(ctx.Req.URL.EscapedPath(), util.PathEscapeSegments(refShortName), util.PathEscapeSegments(renamedBranchName), 1)
|
||||
ctx.Redirect(link)
|
||||
return
|
||||
}
|
||||
|
||||
if refType == RepoRefBranch && ctx.Repo.GitRepo.IsBranchExist(refName) {
|
||||
if refType == RepoRefBranch && ctx.Repo.GitRepo.IsBranchExist(refShortName) {
|
||||
ctx.Repo.IsViewBranch = true
|
||||
ctx.Repo.BranchName = refName
|
||||
ctx.Repo.BranchName = refShortName
|
||||
ctx.Repo.RefFullName = git.RefNameFromBranch(refShortName)
|
||||
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refShortName)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetBranchCommit", err)
|
||||
return
|
||||
}
|
||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||
} else if refType == RepoRefTag && ctx.Repo.GitRepo.IsTagExist(refName) {
|
||||
} else if refType == RepoRefTag && ctx.Repo.GitRepo.IsTagExist(refShortName) {
|
||||
ctx.Repo.IsViewTag = true
|
||||
ctx.Repo.TagName = refName
|
||||
ctx.Repo.RefFullName = git.RefNameFromTag(refShortName)
|
||||
ctx.Repo.TagName = refShortName
|
||||
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetTagCommit(refName)
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetTagCommit(refShortName)
|
||||
if err != nil {
|
||||
if git.IsErrNotExist(err) {
|
||||
ctx.NotFound("GetTagCommit", err)
|
||||
@@ -940,25 +922,26 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
|
||||
return
|
||||
}
|
||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
||||
} else if git.IsStringLikelyCommitID(ctx.Repo.GetObjectFormat(), refName, 7) {
|
||||
} else if git.IsStringLikelyCommitID(ctx.Repo.GetObjectFormat(), refShortName, 7) {
|
||||
ctx.Repo.IsViewCommit = true
|
||||
ctx.Repo.CommitID = refName
|
||||
ctx.Repo.RefFullName = git.RefNameFromCommit(refShortName)
|
||||
ctx.Repo.CommitID = refShortName
|
||||
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName)
|
||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refShortName)
|
||||
if err != nil {
|
||||
ctx.NotFound("GetCommit", err)
|
||||
return
|
||||
}
|
||||
// If short commit ID add canonical link header
|
||||
if len(refName) < ctx.Repo.GetObjectFormat().FullLength() {
|
||||
canonicalURL := util.URLJoin(httplib.GuessCurrentAppURL(ctx), strings.Replace(ctx.Req.URL.RequestURI(), util.PathEscapeSegments(refName), url.PathEscape(ctx.Repo.Commit.ID.String()), 1))
|
||||
if len(refShortName) < ctx.Repo.GetObjectFormat().FullLength() {
|
||||
canonicalURL := util.URLJoin(httplib.GuessCurrentAppURL(ctx), strings.Replace(ctx.Req.URL.RequestURI(), util.PathEscapeSegments(refShortName), url.PathEscape(ctx.Repo.Commit.ID.String()), 1))
|
||||
ctx.RespHeader().Set("Link", fmt.Sprintf(`<%s>; rel="canonical"`, canonicalURL))
|
||||
}
|
||||
} else {
|
||||
if opt.IgnoreNotExistErr {
|
||||
return
|
||||
}
|
||||
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", refShortName))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -975,15 +958,19 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Data["BranchName"] = ctx.Repo.BranchName
|
||||
ctx.Data["RefName"] = ctx.Repo.RefName
|
||||
ctx.Data["RefFullName"] = ctx.Repo.RefFullName
|
||||
ctx.Data["RefTypeNameSubURL"] = ctx.Repo.RefTypeNameSubURL()
|
||||
ctx.Data["TagName"] = ctx.Repo.TagName
|
||||
ctx.Data["CommitID"] = ctx.Repo.CommitID
|
||||
ctx.Data["TreePath"] = ctx.Repo.TreePath
|
||||
|
||||
ctx.Data["IsViewBranch"] = ctx.Repo.IsViewBranch
|
||||
ctx.Data["BranchName"] = ctx.Repo.BranchName
|
||||
|
||||
ctx.Data["IsViewTag"] = ctx.Repo.IsViewTag
|
||||
ctx.Data["TagName"] = ctx.Repo.TagName
|
||||
|
||||
ctx.Data["IsViewCommit"] = ctx.Repo.IsViewCommit
|
||||
ctx.Data["CommitID"] = ctx.Repo.CommitID
|
||||
|
||||
ctx.Data["CanCreateBranch"] = ctx.Repo.CanCreateBranch() // only used by the branch selector dropdown: AllowCreateNewRef
|
||||
|
||||
ctx.Repo.CommitsCount, err = ctx.Repo.GetCommitsCount()
|
||||
|
Reference in New Issue
Block a user