mirror of
https://github.com/go-gitea/gitea
synced 2025-01-31 12:04:28 +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:
parent
604365efd7
commit
81352542fd
@ -56,16 +56,11 @@ func repoArchiverForRelativePath(relativePath string) (*RepoArchiver, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument}
|
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument}
|
||||||
}
|
}
|
||||||
nameExts := strings.SplitN(parts[2], ".", 2)
|
commitID, archiveType := git.SplitArchiveNameType(parts[2])
|
||||||
if len(nameExts) != 2 {
|
if archiveType == git.ArchiveUnknown {
|
||||||
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument}
|
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument}
|
||||||
}
|
}
|
||||||
|
return &RepoArchiver{RepoID: repoID, CommitID: commitID, Type: archiveType}, nil
|
||||||
return &RepoArchiver{
|
|
||||||
RepoID: repoID,
|
|
||||||
CommitID: parts[1] + nameExts[0],
|
|
||||||
Type: git.ToArchiveType(nameExts[1]),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRepoArchiver get an archiver
|
// GetRepoArchiver get an archiver
|
||||||
|
@ -80,6 +80,10 @@ func RefNameFromTag(shortName string) RefName {
|
|||||||
return RefName(TagPrefix + shortName)
|
return RefName(TagPrefix + shortName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RefNameFromCommit(shortName string) RefName {
|
||||||
|
return RefName(shortName)
|
||||||
|
}
|
||||||
|
|
||||||
func (ref RefName) String() string {
|
func (ref RefName) String() string {
|
||||||
return string(ref)
|
return string(ref)
|
||||||
}
|
}
|
||||||
|
@ -16,37 +16,35 @@ import (
|
|||||||
type ArchiveType int
|
type ArchiveType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ZIP zip archive type
|
ArchiveUnknown ArchiveType = iota
|
||||||
ZIP ArchiveType = iota + 1
|
ArchiveZip // 1
|
||||||
// TARGZ tar gz archive type
|
ArchiveTarGz // 2
|
||||||
TARGZ
|
ArchiveBundle // 3
|
||||||
// BUNDLE bundle archive type
|
|
||||||
BUNDLE
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// String converts an ArchiveType to string
|
// String converts an ArchiveType to string: the extension of the archive file without prefix dot
|
||||||
func (a ArchiveType) String() string {
|
func (a ArchiveType) String() string {
|
||||||
switch a {
|
switch a {
|
||||||
case ZIP:
|
case ArchiveZip:
|
||||||
return "zip"
|
return "zip"
|
||||||
case TARGZ:
|
case ArchiveTarGz:
|
||||||
return "tar.gz"
|
return "tar.gz"
|
||||||
case BUNDLE:
|
case ArchiveBundle:
|
||||||
return "bundle"
|
return "bundle"
|
||||||
}
|
}
|
||||||
return "unknown"
|
return "unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToArchiveType(s string) ArchiveType {
|
func SplitArchiveNameType(s string) (string, ArchiveType) {
|
||||||
switch s {
|
switch {
|
||||||
case "zip":
|
case strings.HasSuffix(s, ".zip"):
|
||||||
return ZIP
|
return strings.TrimSuffix(s, ".zip"), ArchiveZip
|
||||||
case "tar.gz":
|
case strings.HasSuffix(s, ".tar.gz"):
|
||||||
return TARGZ
|
return strings.TrimSuffix(s, ".tar.gz"), ArchiveTarGz
|
||||||
case "bundle":
|
case strings.HasSuffix(s, ".bundle"):
|
||||||
return BUNDLE
|
return strings.TrimSuffix(s, ".bundle"), ArchiveBundle
|
||||||
}
|
}
|
||||||
return 0
|
return s, ArchiveUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateArchive create archive content to the target path
|
// CreateArchive create archive content to the target path
|
||||||
|
32
modules/git/repo_archive_test.go
Normal file
32
modules/git/repo_archive_test.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package git
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestArchiveType(t *testing.T) {
|
||||||
|
name, archiveType := SplitArchiveNameType("test.tar.gz")
|
||||||
|
assert.Equal(t, "test", name)
|
||||||
|
assert.Equal(t, "tar.gz", archiveType.String())
|
||||||
|
|
||||||
|
name, archiveType = SplitArchiveNameType("a/b/test.zip")
|
||||||
|
assert.Equal(t, "a/b/test", name)
|
||||||
|
assert.Equal(t, "zip", archiveType.String())
|
||||||
|
|
||||||
|
name, archiveType = SplitArchiveNameType("1234.bundle")
|
||||||
|
assert.Equal(t, "1234", name)
|
||||||
|
assert.Equal(t, "bundle", archiveType.String())
|
||||||
|
|
||||||
|
name, archiveType = SplitArchiveNameType("test")
|
||||||
|
assert.Equal(t, "test", name)
|
||||||
|
assert.Equal(t, "unknown", archiveType.String())
|
||||||
|
|
||||||
|
name, archiveType = SplitArchiveNameType("test.xz")
|
||||||
|
assert.Equal(t, "test.xz", name)
|
||||||
|
assert.Equal(t, "unknown", archiveType.String())
|
||||||
|
}
|
@ -1115,9 +1115,7 @@ blame.ignore_revs = Ignoring revisions in <a href="%s">.git-blame-ignore-revs</a
|
|||||||
blame.ignore_revs.failed = Failed to ignore revisions in <a href="%s">.git-blame-ignore-revs</a>.
|
blame.ignore_revs.failed = Failed to ignore revisions in <a href="%s">.git-blame-ignore-revs</a>.
|
||||||
user_search_tooltip = Shows a maximum of 30 users
|
user_search_tooltip = Shows a maximum of 30 users
|
||||||
|
|
||||||
tree_path_not_found_commit = Path %[1]s doesn't exist in commit %[2]s
|
tree_path_not_found = Path %[1]s doesn't exist in %[2]s
|
||||||
tree_path_not_found_branch = Path %[1]s doesn't exist in branch %[2]s
|
|
||||||
tree_path_not_found_tag = Path %[1]s doesn't exist in tag %[2]s
|
|
||||||
|
|
||||||
transfer.accept = Accept Transfer
|
transfer.accept = Accept Transfer
|
||||||
transfer.accept_desc = Transfer to "%s"
|
transfer.accept_desc = Transfer to "%s"
|
||||||
|
@ -17,11 +17,11 @@ func DownloadArchive(ctx *context.APIContext) {
|
|||||||
var tp git.ArchiveType
|
var tp git.ArchiveType
|
||||||
switch ballType := ctx.PathParam("ball_type"); ballType {
|
switch ballType := ctx.PathParam("ball_type"); ballType {
|
||||||
case "tarball":
|
case "tarball":
|
||||||
tp = git.TARGZ
|
tp = git.ArchiveTarGz
|
||||||
case "zipball":
|
case "zipball":
|
||||||
tp = git.ZIP
|
tp = git.ArchiveZip
|
||||||
case "bundle":
|
case "bundle":
|
||||||
tp = git.BUNDLE
|
tp = git.ArchiveBundle
|
||||||
default:
|
default:
|
||||||
ctx.Error(http.StatusBadRequest, "", fmt.Sprintf("Unknown archive type: %s", ballType))
|
ctx.Error(http.StatusBadRequest, "", fmt.Sprintf("Unknown archive type: %s", ballType))
|
||||||
return
|
return
|
||||||
@ -36,7 +36,7 @@ func DownloadArchive(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, ctx.PathParam("*"), tp)
|
r, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, ctx.PathParam("*")+"."+tp.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("NewRequest", err)
|
ctx.ServerError("NewRequest", err)
|
||||||
return
|
return
|
||||||
|
@ -293,14 +293,7 @@ func GetArchive(ctx *context.APIContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func archiveDownload(ctx *context.APIContext) {
|
func archiveDownload(ctx *context.APIContext) {
|
||||||
uri := ctx.PathParam("*")
|
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, ctx.PathParam("*"))
|
||||||
ext, tp, err := archiver_service.ParseFileName(uri)
|
|
||||||
if err != nil {
|
|
||||||
ctx.Error(http.StatusBadRequest, "ParseFileName", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, strings.TrimSuffix(uri, ext), tp)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, archiver_service.ErrUnknownArchiveFormat{}) {
|
if errors.Is(err, archiver_service.ErrUnknownArchiveFormat{}) {
|
||||||
ctx.Error(http.StatusBadRequest, "unknown archive format", err)
|
ctx.Error(http.StatusBadRequest, "unknown archive format", err)
|
||||||
|
@ -24,7 +24,7 @@ func ShowFileFeed(ctx *context.Context, repo *repo.Repository, formatType string
|
|||||||
}
|
}
|
||||||
commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(
|
commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(
|
||||||
git.CommitsByFileAndRangeOptions{
|
git.CommitsByFileAndRangeOptions{
|
||||||
Revision: ctx.Repo.RefName,
|
Revision: ctx.Repo.RefFullName.ShortName(), // FIXME: legacy code used ShortName
|
||||||
File: fileName,
|
File: fileName,
|
||||||
Page: 1,
|
Page: 1,
|
||||||
})
|
})
|
||||||
|
@ -222,7 +222,7 @@ func FileHistory(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
commitsCount, err := ctx.Repo.GitRepo.FileCommitsCount(ctx.Repo.RefName, fileName)
|
commitsCount, err := ctx.Repo.GitRepo.FileCommitsCount(ctx.Repo.RefFullName.ShortName(), fileName) // FIXME: legacy code used ShortName
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("FileCommitsCount", err)
|
ctx.ServerError("FileCommitsCount", err)
|
||||||
return
|
return
|
||||||
@ -238,7 +238,7 @@ func FileHistory(ctx *context.Context) {
|
|||||||
|
|
||||||
commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(
|
commits, err := ctx.Repo.GitRepo.CommitsByFileAndRange(
|
||||||
git.CommitsByFileAndRangeOptions{
|
git.CommitsByFileAndRangeOptions{
|
||||||
Revision: ctx.Repo.RefName,
|
Revision: ctx.Repo.RefFullName.ShortName(), // FIXME: legacy code used ShortName
|
||||||
File: fileName,
|
File: fileName,
|
||||||
Page: page,
|
Page: page,
|
||||||
})
|
})
|
||||||
|
@ -4,25 +4,14 @@
|
|||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/services/context"
|
"code.gitea.io/gitea/services/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleGitError(ctx *context.Context, msg string, err error) {
|
func HandleGitError(ctx *context.Context, msg string, err error) {
|
||||||
if git.IsErrNotExist(err) {
|
if git.IsErrNotExist(err) {
|
||||||
refType := ""
|
ctx.Data["NotFoundPrompt"] = ctx.Locale.Tr("repo.tree_path_not_found", ctx.Repo.TreePath, ctx.Repo.RefTypeNameSubURL())
|
||||||
switch {
|
ctx.Data["NotFoundGoBackURL"] = ctx.Repo.RepoLink + "/src/" + ctx.Repo.RefTypeNameSubURL()
|
||||||
case ctx.Repo.IsViewBranch:
|
|
||||||
refType = "branch"
|
|
||||||
case ctx.Repo.IsViewTag:
|
|
||||||
refType = "tag"
|
|
||||||
case ctx.Repo.IsViewCommit:
|
|
||||||
refType = "commit"
|
|
||||||
}
|
|
||||||
ctx.Data["NotFoundPrompt"] = ctx.Locale.Tr("repo.tree_path_not_found_"+refType, ctx.Repo.TreePath, url.PathEscape(ctx.Repo.RefName))
|
|
||||||
ctx.Data["NotFoundGoBackURL"] = ctx.Repo.RepoLink + "/src/" + refType + "/" + url.PathEscape(ctx.Repo.RefName)
|
|
||||||
ctx.NotFound(msg, err)
|
ctx.NotFound(msg, err)
|
||||||
} else {
|
} else {
|
||||||
ctx.ServerError(msg, err)
|
ctx.ServerError(msg, err)
|
||||||
|
@ -463,13 +463,7 @@ func RedirectDownload(ctx *context.Context) {
|
|||||||
|
|
||||||
// Download an archive of a repository
|
// Download an archive of a repository
|
||||||
func Download(ctx *context.Context) {
|
func Download(ctx *context.Context) {
|
||||||
uri := ctx.PathParam("*")
|
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, ctx.PathParam("*"))
|
||||||
ext, tp, err := archiver_service.ParseFileName(uri)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("ParseFileName", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, strings.TrimSuffix(uri, ext), tp)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, archiver_service.ErrUnknownArchiveFormat{}) {
|
if errors.Is(err, archiver_service.ErrUnknownArchiveFormat{}) {
|
||||||
ctx.Error(http.StatusBadRequest, err.Error())
|
ctx.Error(http.StatusBadRequest, err.Error())
|
||||||
@ -527,15 +521,9 @@ func download(ctx *context.Context, archiveName string, archiver *repo_model.Rep
|
|||||||
// a request that's already in-progress, but the archiver service will just
|
// a request that's already in-progress, but the archiver service will just
|
||||||
// kind of drop it on the floor if this is the case.
|
// kind of drop it on the floor if this is the case.
|
||||||
func InitiateDownload(ctx *context.Context) {
|
func InitiateDownload(ctx *context.Context) {
|
||||||
uri := ctx.PathParam("*")
|
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, ctx.PathParam("*"))
|
||||||
ext, tp, err := archiver_service.ParseFileName(uri)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("ParseFileName", err)
|
ctx.Error(http.StatusBadRequest, "invalid archive request")
|
||||||
return
|
|
||||||
}
|
|
||||||
aReq, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, strings.TrimSuffix(uri, ext), tp)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("archiver_service.NewRequest", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if aReq == nil {
|
if aReq == nil {
|
||||||
|
@ -42,7 +42,7 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
|
|||||||
}
|
}
|
||||||
defer dataRc.Close()
|
defer dataRc.Close()
|
||||||
|
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.file.title", ctx.Repo.Repository.Name+"/"+path.Base(ctx.Repo.TreePath), ctx.Repo.RefName)
|
ctx.Data["Title"] = ctx.Tr("repo.file.title", ctx.Repo.Repository.Name+"/"+path.Base(ctx.Repo.TreePath), ctx.Repo.RefFullName.ShortName())
|
||||||
ctx.Data["FileIsSymlink"] = entry.IsLink()
|
ctx.Data["FileIsSymlink"] = entry.IsLink()
|
||||||
ctx.Data["FileName"] = blob.Name()
|
ctx.Data["FileName"] = blob.Name()
|
||||||
ctx.Data["RawFileLink"] = ctx.Repo.RepoLink + "/raw/" + ctx.Repo.RefTypeNameSubURL() + "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
|
ctx.Data["RawFileLink"] = ctx.Repo.RepoLink + "/raw/" + ctx.Repo.RefTypeNameSubURL() + "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
|
||||||
|
@ -135,7 +135,7 @@ func prepareToRenderDirectory(ctx *context.Context) {
|
|||||||
|
|
||||||
if ctx.Repo.TreePath != "" {
|
if ctx.Repo.TreePath != "" {
|
||||||
ctx.Data["HideRepoInfo"] = true
|
ctx.Data["HideRepoInfo"] = true
|
||||||
ctx.Data["Title"] = ctx.Tr("repo.file.title", ctx.Repo.Repository.Name+"/"+path.Base(ctx.Repo.TreePath), ctx.Repo.RefName)
|
ctx.Data["Title"] = ctx.Tr("repo.file.title", ctx.Repo.Repository.Name+"/"+path.Base(ctx.Repo.TreePath), ctx.Repo.RefFullName.ShortName())
|
||||||
}
|
}
|
||||||
|
|
||||||
subfolder, readmeFile, err := findReadmeFileInEntries(ctx, entries, true)
|
subfolder, readmeFile, err := findReadmeFileInEntries(ctx, entries, true)
|
||||||
|
@ -58,7 +58,7 @@ type Repository struct {
|
|||||||
IsViewTag bool
|
IsViewTag bool
|
||||||
IsViewCommit bool
|
IsViewCommit bool
|
||||||
|
|
||||||
RefName string
|
RefFullName git.RefName
|
||||||
BranchName string
|
BranchName string
|
||||||
TagName string
|
TagName string
|
||||||
TreePath string
|
TreePath string
|
||||||
@ -392,33 +392,25 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
|
|||||||
|
|
||||||
// RepoAssignment returns a middleware to handle repository assignment
|
// RepoAssignment returns a middleware to handle repository assignment
|
||||||
func RepoAssignment(ctx *Context) {
|
func RepoAssignment(ctx *Context) {
|
||||||
if _, repoAssignmentOnce := ctx.Data["repoAssignmentExecuted"]; repoAssignmentOnce {
|
if ctx.Data["Repository"] != nil {
|
||||||
// FIXME: it should panic in dev/test modes to have a clear behavior
|
setting.PanicInDevOrTesting("RepoAssignment should not be executed twice")
|
||||||
if !setting.IsProd || setting.IsInTesting {
|
|
||||||
panic("RepoAssignment should not be executed twice")
|
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx.Data["repoAssignmentExecuted"] = true
|
|
||||||
|
|
||||||
var (
|
|
||||||
owner *user_model.User
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
|
var err error
|
||||||
userName := ctx.PathParam("username")
|
userName := ctx.PathParam("username")
|
||||||
repoName := ctx.PathParam("reponame")
|
repoName := ctx.PathParam("reponame")
|
||||||
repoName = strings.TrimSuffix(repoName, ".git")
|
repoName = strings.TrimSuffix(repoName, ".git")
|
||||||
if setting.Other.EnableFeed {
|
if setting.Other.EnableFeed {
|
||||||
|
ctx.Data["EnableFeed"] = true
|
||||||
repoName = strings.TrimSuffix(repoName, ".rss")
|
repoName = strings.TrimSuffix(repoName, ".rss")
|
||||||
repoName = strings.TrimSuffix(repoName, ".atom")
|
repoName = strings.TrimSuffix(repoName, ".atom")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the user is the same as the repository owner
|
// Check if the user is the same as the repository owner
|
||||||
if ctx.IsSigned && ctx.Doer.LowerName == strings.ToLower(userName) {
|
if ctx.IsSigned && ctx.Doer.LowerName == strings.ToLower(userName) {
|
||||||
owner = ctx.Doer
|
ctx.Repo.Owner = ctx.Doer
|
||||||
} else {
|
} else {
|
||||||
owner, err = user_model.GetUserByName(ctx, userName)
|
ctx.Repo.Owner, err = user_model.GetUserByName(ctx, userName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if user_model.IsErrUserNotExist(err) {
|
if user_model.IsErrUserNotExist(err) {
|
||||||
// go-get does not support redirects
|
// go-get does not support redirects
|
||||||
@ -441,8 +433,7 @@ func RepoAssignment(ctx *Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.Repo.Owner = owner
|
ctx.ContextUser = ctx.Repo.Owner
|
||||||
ctx.ContextUser = owner
|
|
||||||
ctx.Data["ContextUser"] = ctx.ContextUser
|
ctx.Data["ContextUser"] = ctx.ContextUser
|
||||||
|
|
||||||
// redirect link to wiki
|
// redirect link to wiki
|
||||||
@ -466,10 +457,10 @@ func RepoAssignment(ctx *Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get repository.
|
// 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 err != nil {
|
||||||
if repo_model.IsErrRepoNotExist(err) {
|
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 {
|
if err == nil {
|
||||||
RedirectToRepo(ctx.Base, redirectRepoID)
|
RedirectToRepo(ctx.Base, redirectRepoID)
|
||||||
} else if repo_model.IsErrRedirectNotExist(err) {
|
} else if repo_model.IsErrRedirectNotExist(err) {
|
||||||
@ -486,7 +477,7 @@ func RepoAssignment(ctx *Context) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
repo.Owner = owner
|
repo.Owner = ctx.Repo.Owner
|
||||||
|
|
||||||
repoAssignment(ctx, repo)
|
repoAssignment(ctx, repo)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
@ -495,11 +486,7 @@ func RepoAssignment(ctx *Context) {
|
|||||||
|
|
||||||
ctx.Repo.RepoLink = repo.Link()
|
ctx.Repo.RepoLink = repo.Link()
|
||||||
ctx.Data["RepoLink"] = ctx.Repo.RepoLink
|
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)
|
unit, err := ctx.Repo.Repository.GetUnit(ctx, unit_model.TypeExternalTracker)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -526,7 +513,7 @@ func RepoAssignment(ctx *Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["Title"] = owner.Name + "/" + repo.Name
|
ctx.Data["Title"] = repo.Owner.Name + "/" + repo.Name
|
||||||
ctx.Data["Repository"] = repo
|
ctx.Data["Repository"] = repo
|
||||||
ctx.Data["Owner"] = ctx.Repo.Repository.Owner
|
ctx.Data["Owner"] = ctx.Repo.Repository.Owner
|
||||||
ctx.Data["CanWriteCode"] = ctx.Repo.CanWrite(unit_model.TypeCode)
|
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
|
// Disable everything when the repo is being created
|
||||||
if ctx.Repo.Repository.IsBeingCreated() || ctx.Repo.Repository.IsBroken() {
|
if ctx.Repo.Repository.IsBeingCreated() || ctx.Repo.Repository.IsBroken() {
|
||||||
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
|
|
||||||
if !isHomeOrSettings {
|
if !isHomeOrSettings {
|
||||||
ctx.Redirect(ctx.Repo.RepoLink)
|
ctx.Redirect(ctx.Repo.RepoLink)
|
||||||
}
|
}
|
||||||
@ -604,9 +590,7 @@ func RepoAssignment(ctx *Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Repo.GitRepo != nil {
|
if ctx.Repo.GitRepo != nil {
|
||||||
if !setting.IsProd || setting.IsInTesting {
|
setting.PanicInDevOrTesting("RepoAssignment: GitRepo should be nil")
|
||||||
panic("RepoAssignment: GitRepo should be nil")
|
|
||||||
}
|
|
||||||
_ = ctx.Repo.GitRepo.Close()
|
_ = ctx.Repo.GitRepo.Close()
|
||||||
ctx.Repo.GitRepo = nil
|
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") {
|
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)
|
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.Repo.Repository.MarkAsBrokenEmpty()
|
||||||
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
|
|
||||||
// Only allow access to base of repo or settings
|
// Only allow access to base of repo or settings
|
||||||
if !isHomeOrSettings {
|
if !isHomeOrSettings {
|
||||||
ctx.Redirect(ctx.Repo.RepoLink)
|
ctx.Redirect(ctx.Repo.RepoLink)
|
||||||
@ -629,7 +612,6 @@ func RepoAssignment(ctx *Context) {
|
|||||||
|
|
||||||
// Stop at this point when the repo is empty.
|
// Stop at this point when the repo is empty.
|
||||||
if ctx.Repo.Repository.IsEmpty {
|
if ctx.Repo.Repository.IsEmpty {
|
||||||
ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,22 +637,6 @@ func RepoAssignment(ctx *Context) {
|
|||||||
|
|
||||||
ctx.Data["BranchesCount"] = branchesTotal
|
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.
|
// People who have push access or have forked repository can propose a new pull request.
|
||||||
canPush := ctx.Repo.CanWrite(unit_model.TypeCode) ||
|
canPush := ctx.Repo.CanWrite(unit_model.TypeCode) ||
|
||||||
(ctx.IsSigned && repo_model.HasForkedRepo(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID))
|
(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" {
|
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)
|
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}"
|
||||||
@ -844,26 +810,39 @@ type RepoRefByTypeOptions struct {
|
|||||||
IgnoreNotExistErr bool
|
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
|
// RepoRefByType handles repository reference name for a specific type
|
||||||
// of repository reference
|
// of repository reference
|
||||||
func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func(*Context) {
|
func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func(*Context) {
|
||||||
opt := util.OptionalArg(opts)
|
opt := util.OptionalArg(opts)
|
||||||
return func(ctx *Context) {
|
return func(ctx *Context) {
|
||||||
|
var err error
|
||||||
refType := detectRefType
|
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
|
||||||
ctx.Repo.IsViewBranch = true
|
ctx.Repo.IsViewBranch = true
|
||||||
ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
|
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"] = ""
|
ctx.Data["TreePath"] = ""
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
refName string
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
if ctx.Repo.GitRepo == nil {
|
if ctx.Repo.GitRepo == nil {
|
||||||
ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository)
|
ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -873,22 +852,23 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get default branch.
|
// Get default branch.
|
||||||
|
var refShortName string
|
||||||
reqPath := ctx.PathParam("*")
|
reqPath := ctx.PathParam("*")
|
||||||
if reqPath == "" {
|
if reqPath == "" {
|
||||||
refName = ctx.Repo.Repository.DefaultBranch
|
refShortName = ctx.Repo.Repository.DefaultBranch
|
||||||
if !ctx.Repo.GitRepo.IsBranchExist(refName) {
|
if !ctx.Repo.GitRepo.IsBranchExist(refShortName) {
|
||||||
brs, _, err := ctx.Repo.GitRepo.GetBranches(0, 1)
|
brs, _, err := ctx.Repo.GitRepo.GetBranches(0, 1)
|
||||||
if err == nil && len(brs) != 0 {
|
if err == nil && len(brs) != 0 {
|
||||||
refName = brs[0].Name
|
refShortName = brs[0].Name
|
||||||
} else if len(brs) == 0 {
|
} else if len(brs) == 0 {
|
||||||
log.Error("No branches in non-empty repository %s", ctx.Repo.GitRepo.Path)
|
log.Error("No branches in non-empty repository %s", ctx.Repo.GitRepo.Path)
|
||||||
} else {
|
} else {
|
||||||
log.Error("GetBranches error: %v", err)
|
log.Error("GetBranches error: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.Repo.RefName = refName
|
ctx.Repo.RefFullName = git.RefNameFromBranch(refShortName)
|
||||||
ctx.Repo.BranchName = refName
|
ctx.Repo.BranchName = refShortName
|
||||||
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refName)
|
ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetBranchCommit(refShortName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
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") {
|
} 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
|
} else { // there is a path in request
|
||||||
guessLegacyPath := refType == RepoRefUnknown
|
guessLegacyPath := refType == RepoRefUnknown
|
||||||
if guessLegacyPath {
|
if guessLegacyPath {
|
||||||
refName, refType = getRefNameLegacy(ctx.Base, ctx.Repo, reqPath, "")
|
refShortName, refType = getRefNameLegacy(ctx.Base, ctx.Repo, reqPath, "")
|
||||||
} else {
|
} 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)
|
isRenamedBranch, has := ctx.Data["IsRenamedBranch"].(bool)
|
||||||
if isRenamedBranch && has {
|
if isRenamedBranch && has {
|
||||||
renamedBranchName := ctx.Data["RenamedBranchName"].(string)
|
renamedBranchName := ctx.Data["RenamedBranchName"].(string)
|
||||||
ctx.Flash.Info(ctx.Tr("repo.branch.renamed", refName, renamedBranchName))
|
ctx.Flash.Info(ctx.Tr("repo.branch.renamed", refShortName, renamedBranchName))
|
||||||
link := setting.AppSubURL + strings.Replace(ctx.Req.URL.EscapedPath(), util.PathEscapeSegments(refName), util.PathEscapeSegments(renamedBranchName), 1)
|
link := setting.AppSubURL + strings.Replace(ctx.Req.URL.EscapedPath(), util.PathEscapeSegments(refShortName), util.PathEscapeSegments(renamedBranchName), 1)
|
||||||
ctx.Redirect(link)
|
ctx.Redirect(link)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if refType == RepoRefBranch && ctx.Repo.GitRepo.IsBranchExist(refName) {
|
if refType == RepoRefBranch && ctx.Repo.GitRepo.IsBranchExist(refShortName) {
|
||||||
ctx.Repo.IsViewBranch = true
|
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 {
|
if err != nil {
|
||||||
ctx.ServerError("GetBranchCommit", err)
|
ctx.ServerError("GetBranchCommit", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
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.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 err != nil {
|
||||||
if git.IsErrNotExist(err) {
|
if git.IsErrNotExist(err) {
|
||||||
ctx.NotFound("GetTagCommit", err)
|
ctx.NotFound("GetTagCommit", err)
|
||||||
@ -940,25 +922,26 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx.Repo.CommitID = ctx.Repo.Commit.ID.String()
|
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.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 {
|
if err != nil {
|
||||||
ctx.NotFound("GetCommit", err)
|
ctx.NotFound("GetCommit", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 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(refShortName) < 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))
|
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))
|
ctx.RespHeader().Set("Link", fmt.Sprintf(`<%s>; rel="canonical"`, canonicalURL))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if opt.IgnoreNotExistErr {
|
if opt.IgnoreNotExistErr {
|
||||||
return
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -975,15 +958,19 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["BranchName"] = ctx.Repo.BranchName
|
ctx.Data["RefFullName"] = ctx.Repo.RefFullName
|
||||||
ctx.Data["RefName"] = ctx.Repo.RefName
|
|
||||||
ctx.Data["RefTypeNameSubURL"] = ctx.Repo.RefTypeNameSubURL()
|
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["TreePath"] = ctx.Repo.TreePath
|
||||||
|
|
||||||
ctx.Data["IsViewBranch"] = ctx.Repo.IsViewBranch
|
ctx.Data["IsViewBranch"] = ctx.Repo.IsViewBranch
|
||||||
|
ctx.Data["BranchName"] = ctx.Repo.BranchName
|
||||||
|
|
||||||
ctx.Data["IsViewTag"] = ctx.Repo.IsViewTag
|
ctx.Data["IsViewTag"] = ctx.Repo.IsViewTag
|
||||||
|
ctx.Data["TagName"] = ctx.Repo.TagName
|
||||||
|
|
||||||
ctx.Data["IsViewCommit"] = ctx.Repo.IsViewCommit
|
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.Data["CanCreateBranch"] = ctx.Repo.CanCreateBranch() // only used by the branch selector dropdown: AllowCreateNewRef
|
||||||
|
|
||||||
ctx.Repo.CommitsCount, err = ctx.Repo.GetCommitsCount()
|
ctx.Repo.CommitsCount, err = ctx.Repo.GetCommitsCount()
|
||||||
|
@ -31,19 +31,20 @@ import (
|
|||||||
// handle elsewhere.
|
// handle elsewhere.
|
||||||
type ArchiveRequest struct {
|
type ArchiveRequest struct {
|
||||||
RepoID int64
|
RepoID int64
|
||||||
refName string
|
|
||||||
Type git.ArchiveType
|
Type git.ArchiveType
|
||||||
CommitID string
|
CommitID string
|
||||||
|
|
||||||
|
archiveRefShortName string // the ref short name to download the archive, for example: "master", "v1.0.0", "commit id"
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrUnknownArchiveFormat request archive format is not supported
|
// ErrUnknownArchiveFormat request archive format is not supported
|
||||||
type ErrUnknownArchiveFormat struct {
|
type ErrUnknownArchiveFormat struct {
|
||||||
RequestFormat string
|
RequestNameType string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error implements error
|
// Error implements error
|
||||||
func (err ErrUnknownArchiveFormat) Error() string {
|
func (err ErrUnknownArchiveFormat) Error() string {
|
||||||
return fmt.Sprintf("unknown format: %s", err.RequestFormat)
|
return fmt.Sprintf("unknown format: %s", err.RequestNameType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is implements error
|
// Is implements error
|
||||||
@ -54,12 +55,12 @@ func (ErrUnknownArchiveFormat) Is(err error) bool {
|
|||||||
|
|
||||||
// RepoRefNotFoundError is returned when a requested reference (commit, tag) was not found.
|
// RepoRefNotFoundError is returned when a requested reference (commit, tag) was not found.
|
||||||
type RepoRefNotFoundError struct {
|
type RepoRefNotFoundError struct {
|
||||||
RefName string
|
RefShortName string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error implements error.
|
// Error implements error.
|
||||||
func (e RepoRefNotFoundError) Error() string {
|
func (e RepoRefNotFoundError) Error() string {
|
||||||
return fmt.Sprintf("unrecognized repository reference: %s", e.RefName)
|
return fmt.Sprintf("unrecognized repository reference: %s", e.RefShortName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e RepoRefNotFoundError) Is(err error) bool {
|
func (e RepoRefNotFoundError) Is(err error) bool {
|
||||||
@ -67,43 +68,23 @@ func (e RepoRefNotFoundError) Is(err error) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseFileName(uri string) (ext string, tp git.ArchiveType, err error) {
|
|
||||||
switch {
|
|
||||||
case strings.HasSuffix(uri, ".zip"):
|
|
||||||
ext = ".zip"
|
|
||||||
tp = git.ZIP
|
|
||||||
case strings.HasSuffix(uri, ".tar.gz"):
|
|
||||||
ext = ".tar.gz"
|
|
||||||
tp = git.TARGZ
|
|
||||||
case strings.HasSuffix(uri, ".bundle"):
|
|
||||||
ext = ".bundle"
|
|
||||||
tp = git.BUNDLE
|
|
||||||
default:
|
|
||||||
return "", 0, ErrUnknownArchiveFormat{RequestFormat: uri}
|
|
||||||
}
|
|
||||||
return ext, tp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRequest creates an archival request, based on the URI. The
|
// NewRequest creates an archival request, based on the URI. The
|
||||||
// resulting ArchiveRequest is suitable for being passed to Await()
|
// resulting ArchiveRequest is suitable for being passed to Await()
|
||||||
// if it's determined that the request still needs to be satisfied.
|
// if it's determined that the request still needs to be satisfied.
|
||||||
func NewRequest(repoID int64, repo *git.Repository, refName string, fileType git.ArchiveType) (*ArchiveRequest, error) {
|
func NewRequest(repoID int64, repo *git.Repository, archiveRefExt string) (*ArchiveRequest, error) {
|
||||||
if fileType < git.ZIP || fileType > git.BUNDLE {
|
// here the archiveRefShortName is not a clear ref, it could be a tag, branch or commit id
|
||||||
return nil, ErrUnknownArchiveFormat{RequestFormat: fileType.String()}
|
archiveRefShortName, archiveType := git.SplitArchiveNameType(archiveRefExt)
|
||||||
}
|
if archiveType == git.ArchiveUnknown {
|
||||||
|
return nil, ErrUnknownArchiveFormat{archiveRefExt}
|
||||||
r := &ArchiveRequest{
|
|
||||||
RepoID: repoID,
|
|
||||||
refName: refName,
|
|
||||||
Type: fileType,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get corresponding commit.
|
// Get corresponding commit.
|
||||||
commitID, err := repo.ConvertToGitID(r.refName)
|
commitID, err := repo.ConvertToGitID(archiveRefShortName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, RepoRefNotFoundError{RefName: r.refName}
|
return nil, RepoRefNotFoundError{RefShortName: archiveRefShortName}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r := &ArchiveRequest{RepoID: repoID, archiveRefShortName: archiveRefShortName, Type: archiveType}
|
||||||
r.CommitID = commitID.String()
|
r.CommitID = commitID.String()
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
@ -111,11 +92,11 @@ func NewRequest(repoID int64, repo *git.Repository, refName string, fileType git
|
|||||||
// GetArchiveName returns the name of the caller, based on the ref used by the
|
// GetArchiveName returns the name of the caller, based on the ref used by the
|
||||||
// caller to create this request.
|
// caller to create this request.
|
||||||
func (aReq *ArchiveRequest) GetArchiveName() string {
|
func (aReq *ArchiveRequest) GetArchiveName() string {
|
||||||
return strings.ReplaceAll(aReq.refName, "/", "-") + "." + aReq.Type.String()
|
return strings.ReplaceAll(aReq.archiveRefShortName, "/", "-") + "." + aReq.Type.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Await awaits the completion of an ArchiveRequest. If the archive has
|
// Await awaits the completion of an ArchiveRequest. If the archive has
|
||||||
// already been prepared the method returns immediately. Otherwise an archiver
|
// already been prepared the method returns immediately. Otherwise, an archiver
|
||||||
// process will be started and its completion awaited. On success the returned
|
// process will be started and its completion awaited. On success the returned
|
||||||
// RepoArchiver may be used to download the archive. Note that even if the
|
// RepoArchiver may be used to download the archive. Note that even if the
|
||||||
// context is cancelled/times out a started archiver will still continue to run
|
// context is cancelled/times out a started archiver will still continue to run
|
||||||
@ -208,8 +189,8 @@ func doArchive(ctx context.Context, r *ArchiveRequest) (*repo_model.RepoArchiver
|
|||||||
|
|
||||||
rd, w := io.Pipe()
|
rd, w := io.Pipe()
|
||||||
defer func() {
|
defer func() {
|
||||||
w.Close()
|
_ = w.Close()
|
||||||
rd.Close()
|
_ = rd.Close()
|
||||||
}()
|
}()
|
||||||
done := make(chan error, 1) // Ensure that there is some capacity which will ensure that the goroutine below can always finish
|
done := make(chan error, 1) // Ensure that there is some capacity which will ensure that the goroutine below can always finish
|
||||||
repo, err := repo_model.GetRepositoryByID(ctx, archiver.RepoID)
|
repo, err := repo_model.GetRepositoryByID(ctx, archiver.RepoID)
|
||||||
@ -230,7 +211,7 @@ func doArchive(ctx context.Context, r *ArchiveRequest) (*repo_model.RepoArchiver
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if archiver.Type == git.BUNDLE {
|
if archiver.Type == git.ArchiveBundle {
|
||||||
err = gitRepo.CreateBundle(
|
err = gitRepo.CreateBundle(
|
||||||
ctx,
|
ctx,
|
||||||
archiver.CommitID,
|
archiver.CommitID,
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/git"
|
|
||||||
"code.gitea.io/gitea/services/contexttest"
|
"code.gitea.io/gitea/services/contexttest"
|
||||||
|
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
@ -31,47 +30,47 @@ func TestArchive_Basic(t *testing.T) {
|
|||||||
contexttest.LoadGitRepo(t, ctx)
|
contexttest.LoadGitRepo(t, ctx)
|
||||||
defer ctx.Repo.GitRepo.Close()
|
defer ctx.Repo.GitRepo.Close()
|
||||||
|
|
||||||
bogusReq, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit, git.ZIP)
|
bogusReq, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit+".zip")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, bogusReq)
|
assert.NotNil(t, bogusReq)
|
||||||
assert.EqualValues(t, firstCommit+".zip", bogusReq.GetArchiveName())
|
assert.EqualValues(t, firstCommit+".zip", bogusReq.GetArchiveName())
|
||||||
|
|
||||||
// Check a series of bogus requests.
|
// Check a series of bogus requests.
|
||||||
// Step 1, valid commit with a bad extension.
|
// Step 1, valid commit with a bad extension.
|
||||||
bogusReq, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit, 100)
|
bogusReq, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit+".unknown")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, bogusReq)
|
assert.Nil(t, bogusReq)
|
||||||
|
|
||||||
// Step 2, missing commit.
|
// Step 2, missing commit.
|
||||||
bogusReq, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, "dbffff", git.ZIP)
|
bogusReq, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, "dbffff.zip")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, bogusReq)
|
assert.Nil(t, bogusReq)
|
||||||
|
|
||||||
// Step 3, doesn't look like branch/tag/commit.
|
// Step 3, doesn't look like branch/tag/commit.
|
||||||
bogusReq, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, "db", git.ZIP)
|
bogusReq, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, "db.zip")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Nil(t, bogusReq)
|
assert.Nil(t, bogusReq)
|
||||||
|
|
||||||
bogusReq, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, "master", git.ZIP)
|
bogusReq, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, "master.zip")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, bogusReq)
|
assert.NotNil(t, bogusReq)
|
||||||
assert.EqualValues(t, "master.zip", bogusReq.GetArchiveName())
|
assert.EqualValues(t, "master.zip", bogusReq.GetArchiveName())
|
||||||
|
|
||||||
bogusReq, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, "test/archive", git.ZIP)
|
bogusReq, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, "test/archive.zip")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, bogusReq)
|
assert.NotNil(t, bogusReq)
|
||||||
assert.EqualValues(t, "test-archive.zip", bogusReq.GetArchiveName())
|
assert.EqualValues(t, "test-archive.zip", bogusReq.GetArchiveName())
|
||||||
|
|
||||||
// Now two valid requests, firstCommit with valid extensions.
|
// Now two valid requests, firstCommit with valid extensions.
|
||||||
zipReq, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit, git.ZIP)
|
zipReq, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit+".zip")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, zipReq)
|
assert.NotNil(t, zipReq)
|
||||||
|
|
||||||
tgzReq, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit, git.TARGZ)
|
tgzReq, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit+".tar.gz")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, tgzReq)
|
assert.NotNil(t, tgzReq)
|
||||||
|
|
||||||
secondReq, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, secondCommit, git.ZIP)
|
secondReq, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, secondCommit+".bundle")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, secondReq)
|
assert.NotNil(t, secondReq)
|
||||||
|
|
||||||
@ -91,7 +90,7 @@ func TestArchive_Basic(t *testing.T) {
|
|||||||
// Sleep two seconds to make sure the queue doesn't change.
|
// Sleep two seconds to make sure the queue doesn't change.
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
zipReq2, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit, git.ZIP)
|
zipReq2, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit+".zip")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// This zipReq should match what's sitting in the queue, as we haven't
|
// This zipReq should match what's sitting in the queue, as we haven't
|
||||||
// let it release yet. From the consumer's point of view, this looks like
|
// let it release yet. From the consumer's point of view, this looks like
|
||||||
@ -106,12 +105,12 @@ func TestArchive_Basic(t *testing.T) {
|
|||||||
// Now we'll submit a request and TimedWaitForCompletion twice, before and
|
// Now we'll submit a request and TimedWaitForCompletion twice, before and
|
||||||
// after we release it. We should trigger both the timeout and non-timeout
|
// after we release it. We should trigger both the timeout and non-timeout
|
||||||
// cases.
|
// cases.
|
||||||
timedReq, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, secondCommit, git.TARGZ)
|
timedReq, err := NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, secondCommit+".tar.gz")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, timedReq)
|
assert.NotNil(t, timedReq)
|
||||||
doArchive(db.DefaultContext, timedReq)
|
doArchive(db.DefaultContext, timedReq)
|
||||||
|
|
||||||
zipReq2, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit, git.ZIP)
|
zipReq2, err = NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, firstCommit+".zip")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
// Now, we're guaranteed to have released the original zipReq from the queue.
|
// Now, we're guaranteed to have released the original zipReq from the queue.
|
||||||
// Ensure that we don't get handed back the released entry somehow, but they
|
// Ensure that we don't get handed back the released entry somehow, but they
|
||||||
@ -129,6 +128,6 @@ func TestArchive_Basic(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestErrUnknownArchiveFormat(t *testing.T) {
|
func TestErrUnknownArchiveFormat(t *testing.T) {
|
||||||
err := ErrUnknownArchiveFormat{RequestFormat: "master"}
|
err := ErrUnknownArchiveFormat{RequestNameType: "xxx"}
|
||||||
assert.ErrorIs(t, err, ErrUnknownArchiveFormat{})
|
assert.ErrorIs(t, err, ErrUnknownArchiveFormat{})
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
</button>
|
</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .EnableFeed}}
|
{{if .EnableFeed}}
|
||||||
<a role="button" class="btn interact-bg tw-p-2" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .DefaultBranchBranch.DBBranch.Name}}" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">{{svg "octicon-rss"}}</a>
|
<a role="button" class="btn interact-bg tw-p-2" href="{{$.RepoLink}}/rss/branch/{{PathEscapeSegments .DefaultBranchBranch.DBBranch.Name}}" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">{{svg "octicon-rss"}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if not $.DisableDownloadSourceArchives}}
|
{{if not $.DisableDownloadSourceArchives}}
|
||||||
<div class="ui dropdown btn interact-bg tw-p-2" data-tooltip-content="{{ctx.Locale.Tr "repo.branch.download" ($.DefaultBranchBranch.DBBranch.Name)}}">
|
<div class="ui dropdown btn interact-bg tw-p-2" data-tooltip-content="{{ctx.Locale.Tr "repo.branch.download" ($.DefaultBranchBranch.DBBranch.Name)}}">
|
||||||
@ -162,7 +162,7 @@
|
|||||||
</button>
|
</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if $.EnableFeed}}
|
{{if $.EnableFeed}}
|
||||||
<a role="button" class="btn interact-bg tw-p-2" href="{{$.FeedURL}}/rss/branch/{{PathEscapeSegments .DBBranch.Name}}" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">{{svg "octicon-rss"}}</a>
|
<a role="button" class="btn interact-bg tw-p-2" href="{{$.RepoLink}}/rss/branch/{{PathEscapeSegments .DBBranch.Name}}" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">{{svg "octicon-rss"}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if and (not .DBBranch.IsDeleted) (not $.DisableDownloadSourceArchives)}}
|
{{if and (not .DBBranch.IsDeleted) (not $.DisableDownloadSourceArchives)}}
|
||||||
<div class="ui dropdown btn interact-bg tw-p-2" data-tooltip-content="{{ctx.Locale.Tr "repo.branch.download" (.DBBranch.Name)}}">
|
<div class="ui dropdown btn interact-bg tw-p-2" data-tooltip-content="{{ctx.Locale.Tr "repo.branch.download" (.DBBranch.Name)}}">
|
||||||
|
@ -32,12 +32,14 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{if and (not $.DisableDownloadSourceArchives) $.RefName}}
|
{{if and (not $.DisableDownloadSourceArchives) $.RefFullName}}
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<div class="flex-items-block clone-panel-list">
|
<div class="flex-items-block clone-panel-list">
|
||||||
<a class="item muted archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.zip" rel="nofollow">{{svg "octicon-file-zip"}} {{ctx.Locale.Tr "repo.download_zip"}}</a>
|
{{/* FIXME: here it only uses the shortname in the ref to build the link, it can't distinguish the branch/tag/commit with the same name
|
||||||
<a class="item muted archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip"}} {{ctx.Locale.Tr "repo.download_tar"}}</a>
|
in the future, it's better to use something like "/archive/branch/the-name.zip", "/archive/tag/the-name.zip" */}}
|
||||||
<a class="item muted archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.bundle" rel="nofollow">{{svg "octicon-package"}} {{ctx.Locale.Tr "repo.download_bundle"}}</a>
|
<a class="item muted archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefFullName.ShortName}}.zip" rel="nofollow">{{svg "octicon-file-zip"}} {{ctx.Locale.Tr "repo.download_zip"}}</a>
|
||||||
|
<a class="item muted archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefFullName.ShortName}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip"}} {{ctx.Locale.Tr "repo.download_tar"}}</a>
|
||||||
|
<a class="item muted archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefFullName.ShortName}}.bundle" rel="nofollow">{{svg "octicon-package"}} {{ctx.Locale.Tr "repo.download_bundle"}}</a>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
<a download class="btn-octicon" data-tooltip-content="{{ctx.Locale.Tr "repo.download_file"}}" href="{{$.RawFileLink}}">{{svg "octicon-download"}}</a>
|
<a download class="btn-octicon" data-tooltip-content="{{ctx.Locale.Tr "repo.download_file"}}" href="{{$.RawFileLink}}">{{svg "octicon-download"}}</a>
|
||||||
<a id="copy-content" class="btn-octicon {{if not .CanCopyContent}} disabled{{end}}"{{if or .IsImageFile (and .HasSourceRenderedToggle (not .IsDisplayingSource))}} data-link="{{$.RawFileLink}}"{{end}} data-tooltip-content="{{if .CanCopyContent}}{{ctx.Locale.Tr "copy_content"}}{{else}}{{ctx.Locale.Tr "copy_type_unsupported"}}{{end}}">{{svg "octicon-copy"}}</a>
|
<a id="copy-content" class="btn-octicon {{if not .CanCopyContent}} disabled{{end}}"{{if or .IsImageFile (and .HasSourceRenderedToggle (not .IsDisplayingSource))}} data-link="{{$.RawFileLink}}"{{end}} data-tooltip-content="{{if .CanCopyContent}}{{ctx.Locale.Tr "copy_content"}}{{else}}{{ctx.Locale.Tr "copy_type_unsupported"}}{{end}}">{{svg "octicon-copy"}}</a>
|
||||||
{{if .EnableFeed}}
|
{{if .EnableFeed}}
|
||||||
<a class="btn-octicon" href="{{$.FeedURL}}/rss/{{$.RefTypeNameSubURL}}/{{PathEscapeSegments .TreePath}}" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">
|
<a class="btn-octicon" href="{{$.RepoLink}}/rss/{{$.RefTypeNameSubURL}}/{{PathEscapeSegments .TreePath}}" data-tooltip-content="{{ctx.Locale.Tr "rss_feed"}}">
|
||||||
{{svg "octicon-rss"}}
|
{{svg "octicon-rss"}}
|
||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -60,7 +60,9 @@ func TestEmptyRepoAddFile(t *testing.T) {
|
|||||||
session := loginUser(t, "user30")
|
session := loginUser(t, "user30")
|
||||||
req := NewRequest(t, "GET", "/user30/empty")
|
req := NewRequest(t, "GET", "/user30/empty")
|
||||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||||
assert.Contains(t, resp.Body.String(), "empty-repo-guide")
|
bodyString := resp.Body.String()
|
||||||
|
assert.Contains(t, bodyString, "empty-repo-guide")
|
||||||
|
assert.True(t, test.IsNormalPageCompleted(bodyString))
|
||||||
|
|
||||||
req = NewRequest(t, "GET", "/user30/empty/_new/"+setting.Repository.DefaultBranch)
|
req = NewRequest(t, "GET", "/user30/empty/_new/"+setting.Repository.DefaultBranch)
|
||||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user