Merge branch 'main' into main

This commit is contained in:
Tomeamis 2023-12-06 12:22:17 +01:00 committed by GitHub
commit f4b715cac7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 215 additions and 132 deletions

View File

@ -33,7 +33,7 @@ CERT_FILE = cert.pem
KEY_FILE = key.pem KEY_FILE = key.pem
``` ```
请注意,如果您的证书由第三方证书颁发机构签名(即不是自签名的),则 cert.pem 应包含证书链。服务器证书必须是 cert.pem 中的第一个条目,后跟中介(如果有)。不必包含根证书,因为连接客户端必须已经拥有根证书才能建立信任关系。要了解有关配置值的更多信息,请查看 [配置备忘单](../config-cheat-sheet#server-server)。 请注意,如果您的证书由第三方证书颁发机构签名(即不是自签名的),则 cert.pem 应包含证书链。服务器证书必须是 cert.pem 中的第一个条目,后跟中介(如果有)。不必包含根证书,因为连接客户端必须已经拥有根证书才能建立信任关系。要了解有关配置值的更多信息,请查看 [配置备忘单](administration/config-cheat-sheet#server-server)。
对于“CERT_FILE”或“KEY_FILE”字段当文件路径是相对路径时文件路径相对于“GITEA_CUSTOM”环境变量。它也可以是绝对路径。 对于“CERT_FILE”或“KEY_FILE”字段当文件路径是相对路径时文件路径相对于“GITEA_CUSTOM”环境变量。它也可以是绝对路径。

View File

@ -19,10 +19,7 @@ menu:
## Enabling/configuring API access ## Enabling/configuring API access
By default, `ENABLE_SWAGGER` is true, and By default, `ENABLE_SWAGGER` is true, and `MAX_RESPONSE_ITEMS` is set to 50. See [Config Cheat Sheet](administration/config-cheat-sheet.md) for more information.
`MAX_RESPONSE_ITEMS` is set to 50. See [Config Cheat
Sheet](administration/config-cheat-sheet.md) for more
information.
## Authentication ## Authentication

View File

@ -19,8 +19,7 @@ menu:
## 开启/配置 API 访问 ## 开启/配置 API 访问
通常情况下, `ENABLE_SWAGGER` 默认开启并且参数 `MAX_RESPONSE_ITEMS` 默认为 50。您可以从 [Config Cheat 通常情况下, `ENABLE_SWAGGER` 默认开启并且参数 `MAX_RESPONSE_ITEMS` 默认为 50。您可以从 [Config Cheat Sheet](administration/config-cheat-sheet.md) 中获取更多配置相关信息。
Sheet](administration/config-cheat-sheet.md) 中获取更多配置相关信息。
## 通过 API 认证 ## 通过 API 认证

View File

@ -117,7 +117,7 @@ chmod 770 /etc/gitea
- 使用 `gitea generate secret` 创建 `SECRET_KEY``INTERNAL_TOKEN` - 使用 `gitea generate secret` 创建 `SECRET_KEY``INTERNAL_TOKEN`
- 提供所有必要的密钥 - 提供所有必要的密钥
详情参考 [命令行文档](/zh-cn/command-line/) 中有关 `gitea generate secret` 的内容。 详情参考 [命令行文档](administration/command-line.md) 中有关 `gitea generate secret` 的内容。
### 配置 Gitea 工作路径 ### 配置 Gitea 工作路径
@ -209,6 +209,6 @@ remote: ./hooks/pre-receive.d/gitea: line 2: [...]: No such file or directory
如果您没有使用 Gitea 内置的 SSH 服务器,您还需要通过在管理选项中运行任务 `Update the '.ssh/authorized_keys' file with Gitea SSH keys.` 来重新编写授权密钥文件。 如果您没有使用 Gitea 内置的 SSH 服务器,您还需要通过在管理选项中运行任务 `Update the '.ssh/authorized_keys' file with Gitea SSH keys.` 来重新编写授权密钥文件。
> 更多经验总结,请参考英文版 [Troubleshooting](/en-us/install-from-binary/#troubleshooting) > 更多经验总结,请参考英文版 [Troubleshooting](https://docs.gitea.com/installation/install-from-binary#troubleshooting)
如果从本页中没有找到你需要的内容,请访问 [帮助页面](help/support.md) 如果从本页中没有找到你需要的内容,请访问 [帮助页面](help/support.md)

View File

@ -64,7 +64,7 @@ git checkout v@version@ # or git checkout pr-xyz
- `go` @minGoVersion@ 或更高版本,请参阅 [这里](https://golang.org/dl/) - `go` @minGoVersion@ 或更高版本,请参阅 [这里](https://golang.org/dl/)
- `node` @minNodeVersion@ 或更高版本,并且安装 `npm`, 请参阅 [这里](https://nodejs.org/zh-cn/download/) - `node` @minNodeVersion@ 或更高版本,并且安装 `npm`, 请参阅 [这里](https://nodejs.org/zh-cn/download/)
- `make`, 请参阅 [这里](/zh-cn/hacking-on-gitea/) - `make`, 请参阅 [这里](development/hacking-on-gitea.md)
为了尽可能简化编译过程,提供了各种 [make任务](https://github.com/go-gitea/gitea/blob/main/Makefile)。 为了尽可能简化编译过程,提供了各种 [make任务](https://github.com/go-gitea/gitea/blob/main/Makefile)。

View File

@ -32,7 +32,12 @@ func AddGitSizeAndLFSSizeToRepositoryTable(x *xorm.Engine) error {
return err return err
} }
_, err = sess.Exec(`UPDATE repository SET git_size = size - lfs_size`) _, err = sess.Exec(`UPDATE repository SET size = 0 WHERE size IS NULL`)
if err != nil {
return err
}
_, err = sess.Exec(`UPDATE repository SET git_size = size - lfs_size WHERE size > lfs_size`)
if err != nil { if err != nil {
return err return err
} }

View File

@ -11,6 +11,7 @@ import (
"io" "io"
"os" "os"
"regexp" "regexp"
"strings"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
@ -18,8 +19,10 @@ import (
// BlamePart represents block of blame - continuous lines with one sha // BlamePart represents block of blame - continuous lines with one sha
type BlamePart struct { type BlamePart struct {
Sha string Sha string
Lines []string Lines []string
PreviousSha string
PreviousPath string
} }
// BlameReader returns part of file blame one by one // BlameReader returns part of file blame one by one
@ -43,30 +46,38 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
var blamePart *BlamePart var blamePart *BlamePart
if r.lastSha != nil { if r.lastSha != nil {
blamePart = &BlamePart{*r.lastSha, make([]string, 0)} blamePart = &BlamePart{
Sha: *r.lastSha,
Lines: make([]string, 0),
}
} }
var line []byte var lineBytes []byte
var isPrefix bool var isPrefix bool
var err error var err error
for err != io.EOF { for err != io.EOF {
line, isPrefix, err = r.bufferedReader.ReadLine() lineBytes, isPrefix, err = r.bufferedReader.ReadLine()
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
return blamePart, err return blamePart, err
} }
if len(line) == 0 { if len(lineBytes) == 0 {
// isPrefix will be false // isPrefix will be false
continue continue
} }
lines := shaLineRegex.FindSubmatch(line) line := string(lineBytes)
lines := shaLineRegex.FindStringSubmatch(line)
if lines != nil { if lines != nil {
sha1 := string(lines[1]) sha1 := lines[1]
if blamePart == nil { if blamePart == nil {
blamePart = &BlamePart{sha1, make([]string, 0)} blamePart = &BlamePart{
Sha: sha1,
Lines: make([]string, 0),
}
} }
if blamePart.Sha != sha1 { if blamePart.Sha != sha1 {
@ -81,9 +92,11 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
return blamePart, nil return blamePart, nil
} }
} else if line[0] == '\t' { } else if line[0] == '\t' {
code := line[1:] blamePart.Lines = append(blamePart.Lines, line[1:])
} else if strings.HasPrefix(line, "previous ") {
blamePart.Lines = append(blamePart.Lines, string(code)) parts := strings.SplitN(line[len("previous "):], " ", 2)
blamePart.PreviousSha = parts[0]
blamePart.PreviousPath = parts[1]
} }
// need to munch to end of line... // need to munch to end of line...

View File

@ -24,15 +24,17 @@ func TestReadingBlameOutput(t *testing.T) {
parts := []*BlamePart{ parts := []*BlamePart{
{ {
"72866af952e98d02a73003501836074b286a78f6", Sha: "72866af952e98d02a73003501836074b286a78f6",
[]string{ Lines: []string{
"# test_repo", "# test_repo",
"Test repository for testing migration from github to gitea", "Test repository for testing migration from github to gitea",
}, },
}, },
{ {
"f32b0a9dfd09a60f616f29158f772cedd89942d2", Sha: "f32b0a9dfd09a60f616f29158f772cedd89942d2",
[]string{"", "Do not make any changes to this repo it is used for unit testing"}, Lines: []string{"", "Do not make any changes to this repo it is used for unit testing"},
PreviousSha: "72866af952e98d02a73003501836074b286a78f6",
PreviousPath: "README.md",
}, },
} }
@ -64,16 +66,18 @@ func TestReadingBlameOutput(t *testing.T) {
full := []*BlamePart{ full := []*BlamePart{
{ {
"af7486bd54cfc39eea97207ca666aa69c9d6df93", Sha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
[]string{"line", "line"}, Lines: []string{"line", "line"},
}, },
{ {
"45fb6cbc12f970b04eacd5cd4165edd11c8d7376", Sha: "45fb6cbc12f970b04eacd5cd4165edd11c8d7376",
[]string{"changed line"}, Lines: []string{"changed line"},
PreviousSha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
PreviousPath: "blame.txt",
}, },
{ {
"af7486bd54cfc39eea97207ca666aa69c9d6df93", Sha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
[]string{"line", "line", ""}, Lines: []string{"line", "line", ""},
}, },
} }
@ -89,8 +93,8 @@ func TestReadingBlameOutput(t *testing.T) {
Bypass: false, Bypass: false,
Parts: []*BlamePart{ Parts: []*BlamePart{
{ {
"af7486bd54cfc39eea97207ca666aa69c9d6df93", Sha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
[]string{"line", "line", "changed line", "line", "line", ""}, Lines: []string{"line", "line", "changed line", "line", "line", ""},
}, },
}, },
}, },

View File

@ -43,8 +43,9 @@ func (c *Commit) Message() string {
} }
// Summary returns first line of commit message. // Summary returns first line of commit message.
// The string is forced to be valid UTF8
func (c *Commit) Summary() string { func (c *Commit) Summary() string {
return strings.Split(strings.TrimSpace(c.CommitMessage), "\n")[0] return strings.ToValidUTF8(strings.Split(strings.TrimSpace(c.CommitMessage), "\n")[0], "?")
} }
// ParentID returns oid of n-th parent (0-based index). // ParentID returns oid of n-th parent (0-based index).

View File

@ -211,10 +211,11 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
skip, limit := indexer_internal.ParsePaginator(options.Paginator, maxTotalHits) skip, limit := indexer_internal.ParsePaginator(options.Paginator, maxTotalHits)
searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(options.Keyword, &meilisearch.SearchRequest{ searchRes, err := b.inner.Client.Index(b.inner.VersionedIndexName()).Search(options.Keyword, &meilisearch.SearchRequest{
Filter: query.Statement(), Filter: query.Statement(),
Limit: int64(limit), Limit: int64(limit),
Offset: int64(skip), Offset: int64(skip),
Sort: sortBy, Sort: sortBy,
MatchingStrategy: "all",
}) })
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -230,6 +230,7 @@ func RenderMarkdownToHtml(ctx context.Context, input string) template.HTML { //n
output, err := markdown.RenderString(&markup.RenderContext{ output, err := markdown.RenderString(&markup.RenderContext{
Ctx: ctx, Ctx: ctx,
URLPrefix: setting.AppSubURL, URLPrefix: setting.AppSubURL,
Metas: map[string]string{"mode": "document"},
}, input) }, input)
if err != nil { if err != nil {
log.Error("RenderString: %v", err) log.Error("RenderString: %v", err)

View File

@ -0,0 +1,10 @@
SAX2 is Free!
I hereby abandon any property rights to SAX 2.0 (the Simple API for
XML), and release all of the SAX 2.0 source code, compiled code, and
documentation contained in this distribution into the Public Domain.
SAX comes with NO WARRANTY or guarantee of fitness for any
purpose.
David Megginson, david@megginson.com
2000-05-05

37
options/license/radvd Normal file
View File

@ -0,0 +1,37 @@
The author(s) grant permission for redistribution and use in source and
binary forms, with or without modification, of the software and documentation
provided that the following conditions are met:
0. If you receive a version of the software that is specifically labelled
as not being for redistribution (check the version message and/or README),
you are not permitted to redistribute that version of the software in any
way or form.
1. All terms of all other applicable copyrights and licenses must be
followed.
2. Redistributions of source code must retain the authors' copyright
notice(s), this list of conditions, and the following disclaimer.
3. Redistributions in binary form must reproduce the authors' copyright
notice(s), this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
4. All advertising materials mentioning features or use of this software
must display the following acknowledgement with the name(s) of the
authors as specified in the copyright notice(s) substituted where
indicated:
This product includes software developed by the authors which are
mentioned at the start of the source files and other contributors.
5. Neither the name(s) of the author(s) nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -2312,7 +2312,7 @@ settings.dismiss_stale_approvals_desc = When new commits that change the content
settings.require_signed_commits = Require Signed Commits settings.require_signed_commits = Require Signed Commits
settings.require_signed_commits_desc = Reject pushes to this branch if they are unsigned or unverifiable. settings.require_signed_commits_desc = Reject pushes to this branch if they are unsigned or unverifiable.
settings.protect_branch_name_pattern = Protected Branch Name Pattern settings.protect_branch_name_pattern = Protected Branch Name Pattern
settings.protect_branch_name_pattern_desc = "Protected branch name patterns. See <a href="github.com/gobwas/glob">the documentation</a> for pattern syntax. Examples: main, release/**" settings.protect_branch_name_pattern_desc = "Protected branch name patterns. See <a href="https://github.com/gobwas/glob">the documentation</a> for pattern syntax. Examples: main, release/**"
settings.protect_patterns = Patterns settings.protect_patterns = Patterns
settings.protect_protected_file_patterns = "Protected file patterns (separated using semicolon ';'):" settings.protect_protected_file_patterns = "Protected file patterns (separated using semicolon ';'):"
settings.protect_protected_file_patterns_desc = "Protected files are not allowed to be changed directly even if user has rights to add, edit, or delete files in this branch. Multiple patterns can be separated using semicolon (';'). See <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>." settings.protect_protected_file_patterns_desc = "Protected files are not allowed to be changed directly even if user has rights to add, edit, or delete files in this branch. Multiple patterns can be separated using semicolon (';'). See <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> documentation for pattern syntax. Examples: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>."

View File

@ -3305,7 +3305,7 @@ error.unit_not_allowed=Não tem permissão para aceder a esta parte do repositó
title=Pacotes title=Pacotes
desc=Gerir pacotes do repositório. desc=Gerir pacotes do repositório.
empty=Ainda não há pacotes. empty=Ainda não há pacotes.
empty.documentation=Para obter mais informação sobre o registo de pacotes, veja <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/usage/packages/overview/">a documentação</a>. empty.documentation=Para obter mais informação sobre o registo de pacotes, veja <a target="_blank" rel="noopener noreferrer" href="%s">a documentação</a>.
empty.repo=Carregou um pacote mas este não é apresentado aqui? Vá às <a href="%[1]s">configurações do pacote</a> e ligue-o a este repositório. empty.repo=Carregou um pacote mas este não é apresentado aqui? Vá às <a href="%[1]s">configurações do pacote</a> e ligue-o a este repositório.
registry.documentation=Para mais informação sobre o registo %s, veja <a target="_blank" rel="noopener noreferrer" href="%s">a documentação</a>. registry.documentation=Para mais informação sobre o registo %s, veja <a target="_blank" rel="noopener noreferrer" href="%s">a documentação</a>.
filter.type=Tipo filter.type=Tipo

View File

@ -520,7 +520,10 @@ func CommonRoutes() *web.Route {
r.Get("", rpm.DownloadPackageFile) r.Get("", rpm.DownloadPackageFile)
r.Delete("", reqPackageAccess(perm.AccessModeWrite), rpm.DeletePackageFile) r.Delete("", reqPackageAccess(perm.AccessModeWrite), rpm.DeletePackageFile)
}) })
r.Get("/repodata/{filename}", rpm.GetRepositoryFile) r.Group("/repodata/{filename}", func() {
r.Head("", rpm.CheckRepositoryFileExistence)
r.Get("", rpm.GetRepositoryFile)
})
}, reqPackageAccess(perm.AccessModeRead)) }, reqPackageAccess(perm.AccessModeRead))
r.Group("/rubygems", func() { r.Group("/rubygems", func() {
r.Get("/specs.4.8.gz", rubygems.EnumeratePackages) r.Get("/specs.4.8.gz", rubygems.EnumeratePackages)

View File

@ -57,6 +57,30 @@ func GetRepositoryKey(ctx *context.Context) {
}) })
} }
func CheckRepositoryFileExistence(ctx *context.Context) {
pv, err := rpm_service.GetOrCreateRepositoryVersion(ctx, ctx.Package.Owner.ID)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
pf, err := packages_model.GetFileForVersionByName(ctx, pv.ID, ctx.Params("filename"), packages_model.EmptyFileKey)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
ctx.Status(http.StatusNotFound)
} else {
apiError(ctx, http.StatusInternalServerError, err)
}
return
}
ctx.SetServeHeaders(&context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
ctx.Status(http.StatusOK)
}
// Gets a pre-generated repository metadata file // Gets a pre-generated repository metadata file
func GetRepositoryFile(ctx *context.Context) { func GetRepositoryFile(ctx *context.Context) {
pv, err := rpm_service.GetOrCreateRepositoryVersion(ctx, ctx.Package.Owner.ID) pv, err := rpm_service.GetOrCreateRepositoryVersion(ctx, ctx.Package.Owner.ID)

View File

@ -133,11 +133,6 @@ func ListReleases(ctx *context.APIContext) {
// in: query // in: query
// description: filter (exclude / include) pre-releases // description: filter (exclude / include) pre-releases
// type: boolean // type: boolean
// - name: per_page
// in: query
// description: page size of results, deprecated - use limit
// type: integer
// deprecated: true
// - name: page // - name: page
// in: query // in: query
// description: page number of results to return (1-based) // description: page number of results to return (1-based)
@ -152,9 +147,6 @@ func ListReleases(ctx *context.APIContext) {
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
listOptions := utils.GetListOptions(ctx) listOptions := utils.GetListOptions(ctx)
if listOptions.PageSize == 0 && ctx.FormInt("per_page") != 0 {
listOptions.PageSize = ctx.FormInt("per_page")
}
opts := repo_model.FindReleasesOptions{ opts := repo_model.FindReleasesOptions{
ListOptions: listOptions, ListOptions: listOptions,

View File

@ -200,6 +200,7 @@ func List(ctx *context.Context) {
pager.AddParamString("actor", fmt.Sprint(actorID)) pager.AddParamString("actor", fmt.Sprint(actorID))
pager.AddParamString("status", fmt.Sprint(status)) pager.AddParamString("status", fmt.Sprint(status))
ctx.Data["Page"] = pager ctx.Data["Page"] = pager
ctx.Data["HasWorkflowsOrRuns"] = len(workflows) > 0 || len(runs) > 0
ctx.HTML(http.StatusOK, tplListActions) ctx.HTML(http.StatusOK, tplListActions)
} }

View File

@ -114,12 +114,12 @@ func RefBlame(ctx *context.Context) {
return return
} }
commitNames, previousCommits := processBlameParts(ctx, result.Parts) commitNames := processBlameParts(ctx, result.Parts)
if ctx.Written() { if ctx.Written() {
return return
} }
renderBlame(ctx, result.Parts, commitNames, previousCommits) renderBlame(ctx, result.Parts, commitNames)
ctx.HTML(http.StatusOK, tplRepoHome) ctx.HTML(http.StatusOK, tplRepoHome)
} }
@ -185,12 +185,9 @@ func fillBlameResult(br *git.BlameReader, r *blameResult) error {
return nil return nil
} }
func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) (map[string]*user_model.UserCommit, map[string]string) { func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) map[string]*user_model.UserCommit {
// store commit data by SHA to look up avatar info etc // store commit data by SHA to look up avatar info etc
commitNames := make(map[string]*user_model.UserCommit) commitNames := make(map[string]*user_model.UserCommit)
// previousCommits contains links from SHA to parent SHA,
// if parent also contains the current TreePath.
previousCommits := make(map[string]string)
// and as blameParts can reference the same commits multiple // and as blameParts can reference the same commits multiple
// times, we cache the lookup work locally // times, we cache the lookup work locally
commits := make([]*git.Commit, 0, len(blameParts)) commits := make([]*git.Commit, 0, len(blameParts))
@ -214,29 +211,11 @@ func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) (map[st
} else { } else {
ctx.ServerError("Repo.GitRepo.GetCommit", err) ctx.ServerError("Repo.GitRepo.GetCommit", err)
} }
return nil, nil return nil
} }
commitCache[sha] = commit commitCache[sha] = commit
} }
// find parent commit
if commit.ParentCount() > 0 {
psha := commit.Parents[0]
previousCommit, ok := commitCache[psha.String()]
if !ok {
previousCommit, _ = commit.Parent(0)
if previousCommit != nil {
commitCache[psha.String()] = previousCommit
}
}
// only store parent commit ONCE, if it has the file
if previousCommit != nil {
if haz1, _ := previousCommit.HasFile(ctx.Repo.TreePath); haz1 {
previousCommits[commit.ID.String()] = previousCommit.ID.String()
}
}
}
commits = append(commits, commit) commits = append(commits, commit)
} }
@ -245,10 +224,10 @@ func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) (map[st
commitNames[c.ID.String()] = c commitNames[c.ID.String()] = c
} }
return commitNames, previousCommits return commitNames
} }
func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames map[string]*user_model.UserCommit, previousCommits map[string]string) { func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames map[string]*user_model.UserCommit) {
repoLink := ctx.Repo.RepoLink repoLink := ctx.Repo.RepoLink
language := "" language := ""
@ -295,7 +274,6 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
} }
commit := commitNames[part.Sha] commit := commitNames[part.Sha]
previousSha := previousCommits[part.Sha]
if index == 0 { if index == 0 {
// Count commit number // Count commit number
commitCnt++ commitCnt++
@ -313,8 +291,8 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
br.Avatar = gotemplate.HTML(avatar) br.Avatar = gotemplate.HTML(avatar)
br.RepoLink = repoLink br.RepoLink = repoLink
br.PartSha = part.Sha br.PartSha = part.Sha
br.PreviousSha = previousSha br.PreviousSha = part.PreviousSha
br.PreviousShaURL = fmt.Sprintf("%s/blame/commit/%s/%s", repoLink, url.PathEscape(previousSha), util.PathEscapeSegments(ctx.Repo.TreePath)) br.PreviousShaURL = fmt.Sprintf("%s/blame/commit/%s/%s", repoLink, url.PathEscape(part.PreviousSha), util.PathEscapeSegments(part.PreviousPath))
br.CommitURL = fmt.Sprintf("%s/commit/%s", repoLink, url.PathEscape(part.Sha)) br.CommitURL = fmt.Sprintf("%s/commit/%s", repoLink, url.PathEscape(part.Sha))
br.CommitMessage = commit.CommitMessage br.CommitMessage = commit.CommitMessage
br.CommitSince = commitSince br.CommitSince = commitSince

View File

@ -174,6 +174,7 @@ func TagsList(ctx *context.Context) {
// Disable the showCreateNewBranch form in the dropdown on this page. // Disable the showCreateNewBranch form in the dropdown on this page.
ctx.Data["CanCreateBranch"] = false ctx.Data["CanCreateBranch"] = false
ctx.Data["HideBranchesInDropdown"] = true ctx.Data["HideBranchesInDropdown"] = true
ctx.Data["CanCreateRelease"] = ctx.Repo.CanWrite(unit.TypeReleases) && !ctx.Repo.Repository.IsArchived
listOptions := db.ListOptions{ listOptions := db.ListOptions{
Page: ctx.FormInt("page"), Page: ctx.FormInt("page"),

View File

@ -711,21 +711,14 @@ func checkCitationFile(ctx *context.Context, entry *git.TreeEntry) {
} }
for _, entry := range allEntries { for _, entry := range allEntries {
if entry.Name() == "CITATION.cff" || entry.Name() == "CITATION.bib" { if entry.Name() == "CITATION.cff" || entry.Name() == "CITATION.bib" {
ctx.Data["CitiationExist"] = true
// Read Citation file contents // Read Citation file contents
blob := entry.Blob() if content, err := entry.Blob().GetBlobContent(setting.UI.MaxDisplayFileSize); err != nil {
dataRc, err := blob.DataAsync() log.Error("checkCitationFile: GetBlobContent: %v", err)
if err != nil { } else {
ctx.ServerError("DataAsync", err) ctx.Data["CitiationExist"] = true
return ctx.PageData["citationFileContent"] = content
break
} }
defer dataRc.Close()
ctx.PageData["citationFileContent"], err = blob.GetBlobContent(setting.UI.MaxDisplayFileSize)
if err != nil {
ctx.ServerError("GetBlobContent", err)
return
}
break
} }
} }
} }

View File

@ -130,3 +130,25 @@ func (r *indexerNotifier) IssueChangeTitle(ctx context.Context, doer *user_model
func (r *indexerNotifier) IssueChangeRef(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldRef string) { func (r *indexerNotifier) IssueChangeRef(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldRef string) {
issue_indexer.UpdateIssueIndexer(ctx, issue.ID) issue_indexer.UpdateIssueIndexer(ctx, issue.ID)
} }
func (r *indexerNotifier) IssueChangeStatus(ctx context.Context, doer *user_model.User, commitID string, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) {
issue_indexer.UpdateIssueIndexer(ctx, issue.ID)
}
func (r *indexerNotifier) IssueChangeAssignee(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) {
issue_indexer.UpdateIssueIndexer(ctx, issue.ID)
}
func (r *indexerNotifier) IssueChangeMilestone(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, oldMilestoneID int64) {
issue_indexer.UpdateIssueIndexer(ctx, issue.ID)
}
func (r *indexerNotifier) IssueChangeLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue,
addedLabels, removedLabels []*issues_model.Label,
) {
issue_indexer.UpdateIssueIndexer(ctx, issue.ID)
}
func (r *indexerNotifier) IssueClearLabels(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) {
issue_indexer.UpdateIssueIndexer(ctx, issue.ID)
}

View File

@ -862,7 +862,7 @@ func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error {
line := comment.Line line := comment.Line
if line != 0 { if line != 0 {
comment.Position = 1 comment.Position = 1
} else { } else if comment.DiffHunk != "" {
_, _, line, _ = git.ParseDiffHunkString(comment.DiffHunk) _, _, line, _ = git.ParseDiffHunkString(comment.DiffHunk)
} }

View File

@ -67,7 +67,7 @@ func GetOrCreateKeyPair(ctx context.Context, ownerID int64) (string, string, err
} }
func generateKeypair() (string, string, error) { func generateKeypair() (string, string, error) {
e, err := openpgp.NewEntity(setting.AppName, "Debian Registry", "", nil) e, err := openpgp.NewEntity("", "Debian Registry", "", nil)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }

View File

@ -22,7 +22,6 @@ import (
"code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/json"
packages_module "code.gitea.io/gitea/modules/packages" packages_module "code.gitea.io/gitea/modules/packages"
rpm_module "code.gitea.io/gitea/modules/packages/rpm" rpm_module "code.gitea.io/gitea/modules/packages/rpm"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
packages_service "code.gitea.io/gitea/services/packages" packages_service "code.gitea.io/gitea/services/packages"
@ -68,7 +67,7 @@ func GetOrCreateKeyPair(ctx context.Context, ownerID int64) (string, string, err
} }
func generateKeypair() (string, string, error) { func generateKeypair() (string, string, error) {
e, err := openpgp.NewEntity(setting.AppName, "RPM Registry", "", nil) e, err := openpgp.NewEntity("", "RPM Registry", "", nil)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -126,7 +125,7 @@ type packageData struct {
type packageCache = map[*packages_model.PackageFile]*packageData type packageCache = map[*packages_model.PackageFile]*packageData
// BuildSpecificRepositoryFiles builds metadata files for the repository // BuildRepositoryFiles builds metadata files for the repository
func BuildRepositoryFiles(ctx context.Context, ownerID int64) error { func BuildRepositoryFiles(ctx context.Context, ownerID int64) error {
pv, err := GetOrCreateRepositoryVersion(ctx, ownerID) pv, err := GetOrCreateRepositoryVersion(ctx, ownerID)
if err != nil { if err != nil {

View File

@ -35,7 +35,9 @@ var pushQueue *queue.WorkerPoolQueue[[]*repo_module.PushUpdateOptions]
func handler(items ...[]*repo_module.PushUpdateOptions) [][]*repo_module.PushUpdateOptions { func handler(items ...[]*repo_module.PushUpdateOptions) [][]*repo_module.PushUpdateOptions {
for _, opts := range items { for _, opts := range items {
if err := pushUpdates(opts); err != nil { if err := pushUpdates(opts); err != nil {
log.Error("pushUpdate failed: %v", err) // Username and repository stays the same between items in opts.
pushUpdate := opts[0]
log.Error("pushUpdate[%s/%s] failed: %v", pushUpdate.RepoUserName, pushUpdate.RepoName, err)
} }
} }
return nil return nil

View File

@ -28,7 +28,7 @@
</div> </div>
<div class="flex-item-trailing"> <div class="flex-item-trailing">
{{if .PrimaryLanguage}} {{if .PrimaryLanguage}}
<a class="muted" href="{{$.Link}}?q={{$.Keyword}}&sort={{$.SortType}}&language={{.PrimaryLanguage.Language}}"> <a class="muted" href="{{$.Link}}?q={{$.Keyword}}&sort={{$.SortType}}&language={{.PrimaryLanguage.Language}}{{if $.TabName}}&tab={{$.TabName}}{{end}}">
<span class="flex-text-inline"><i class="color-icon gt-mr-3" style="background-color: {{.PrimaryLanguage.Color}}"></i>{{.PrimaryLanguage.Language}}</span> <span class="flex-text-inline"><i class="color-icon gt-mr-3" style="background-color: {{.PrimaryLanguage.Color}}"></i>{{.PrimaryLanguage.Language}}</span>
</a> </a>
{{end}} {{end}}

View File

@ -4,7 +4,7 @@
<div class="ui container"> <div class="ui container">
{{template "base/alert" .}} {{template "base/alert" .}}
{{if .workflows}} {{if .HasWorkflowsOrRuns}}
<div class="ui stackable grid"> <div class="ui stackable grid">
<div class="four wide column"> <div class="four wide column">
<div class="ui fluid vertical menu"> <div class="ui fluid vertical menu">

View File

@ -1,5 +1,5 @@
<div class="flex-list"> <div class="flex-list">
{{if eq (len .Runs) 0}} {{if not .Runs}}
<div class="empty-placeholder"> <div class="empty-placeholder">
{{svg "octicon-no-entry" 48}} {{svg "octicon-no-entry" 48}}
<h2>{{if $.IsFiltered}}{{ctx.Locale.Tr "actions.runs.no_results"}}{{else}}{{ctx.Locale.Tr "actions.runs.no_runs"}}{{end}}</h2> <h2>{{if $.IsFiltered}}{{ctx.Locale.Tr "actions.runs.no_results"}}{{else}}{{ctx.Locale.Tr "actions.runs.no_runs"}}{{end}}</h2>

View File

@ -108,25 +108,27 @@
</tr> </tr>
{{if and (eq .GetType 3) $hasmatch}} {{if and (eq .GetType 3) $hasmatch}}
{{$match := index $section.Lines $line.Match}} {{$match := index $section.Lines $line.Match}}
{{if or (gt (len $line.Comments) 0) (gt (len $match.Comments) 0)}} {{if or $line.Comments $match.Comments}}
<tr class="add-comment" data-line-type="{{.GetHTMLDiffLineType}}"> <tr class="add-comment" data-line-type="{{.GetHTMLDiffLineType}}">
<td class="add-comment-left" colspan="4"> <td class="add-comment-left" colspan="4">
{{if gt (len $line.Comments) 0}} {{if $line.Comments}}
{{if eq $line.GetCommentSide "previous"}} {{if eq $line.GetCommentSide "previous"}}
{{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}} {{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}}
{{end}} {{end}}
{{end}} {{end}}
{{if gt (len $match.Comments) 0}} {{if $match.Comments}}
{{if eq $match.GetCommentSide "previous"}} {{if eq $match.GetCommentSide "previous"}}
{{template "repo/diff/conversation" dict "." $.root "comments" $match.Comments}} {{template "repo/diff/conversation" dict "." $.root "comments" $match.Comments}}
{{end}} {{end}}
{{end}} {{end}}
</td> </td>
<td class="add-comment-right" colspan="4"> <td class="add-comment-right" colspan="4">
{{if eq $line.GetCommentSide "proposed"}} {{if $line.Comments}}
{{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}} {{if eq $line.GetCommentSide "proposed"}}
{{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}}
{{end}}
{{end}} {{end}}
{{if gt (len $match.Comments) 0}} {{if $match.Comments}}
{{if eq $match.GetCommentSide "proposed"}} {{if eq $match.GetCommentSide "proposed"}}
{{template "repo/diff/conversation" dict "." $.root "comments" $match.Comments}} {{template "repo/diff/conversation" dict "." $.root "comments" $match.Comments}}
{{end}} {{end}}
@ -134,13 +136,11 @@
</td> </td>
</tr> </tr>
{{end}} {{end}}
{{else if gt (len $line.Comments) 0}} {{else if $line.Comments}}
<tr class="add-comment" data-line-type="{{.GetHTMLDiffLineType}}"> <tr class="add-comment" data-line-type="{{.GetHTMLDiffLineType}}">
<td class="add-comment-left" colspan="4"> <td class="add-comment-left" colspan="4">
{{if gt (len $line.Comments) 0}} {{if eq $line.GetCommentSide "previous"}}
{{if eq $line.GetCommentSide "previous"}} {{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}}
{{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}}
{{end}}
{{end}} {{end}}
</td> </td>
<td class="add-comment-right" colspan="4"> <td class="add-comment-right" colspan="4">

View File

@ -60,7 +60,7 @@
*/}}</td> */}}</td>
{{end}} {{end}}
</tr> </tr>
{{if gt (len $line.Comments) 0}} {{if $line.Comments}}
<tr class="add-comment" data-line-type="{{.GetHTMLDiffLineType}}"> <tr class="add-comment" data-line-type="{{.GetHTMLDiffLineType}}">
<td class="add-comment-left add-comment-right" colspan="5"> <td class="add-comment-left add-comment-right" colspan="5">
{{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}} {{template "repo/diff/conversation" dict "." $.root "comments" $line.Comments}}

View File

@ -81,12 +81,12 @@
{{end}} {{end}}
{{if and (not .IsEmpty) ($.Permission.CanRead $.UnitTypeCode)}} {{if and (not .IsEmpty) ($.Permission.CanRead $.UnitTypeCode)}}
<div class="ui labeled button <div class="ui labeled button
{{if or (not $.IsSigned) (and (not $.CanSignedUserFork) (eq (len $.UserAndOrgForks) 0))}} {{if or (not $.IsSigned) (and (not $.CanSignedUserFork) (not $.UserAndOrgForks))}}
disabled disabled
{{end}}" {{end}}"
{{if not $.IsSigned}} {{if not $.IsSigned}}
data-tooltip-content="{{ctx.Locale.Tr "repo.fork_guest_user"}}" data-tooltip-content="{{ctx.Locale.Tr "repo.fork_guest_user"}}"
{{else if and (not $.CanSignedUserFork) (eq (len $.UserAndOrgForks) 0)}} {{else if and (not $.CanSignedUserFork) (not $.UserAndOrgForks)}}
data-tooltip-content="{{ctx.Locale.Tr "repo.fork_from_self"}}" data-tooltip-content="{{ctx.Locale.Tr "repo.fork_from_self"}}"
{{end}} {{end}}
> >
@ -98,7 +98,7 @@
href="{{AppSubUrl}}/{{(index $.UserAndOrgForks 0).FullName}}" href="{{AppSubUrl}}/{{(index $.UserAndOrgForks 0).FullName}}"
{{/*else is not required here, because the button shouldn't link to any site if you can't create a fork*/}} {{/*else is not required here, because the button shouldn't link to any site if you can't create a fork*/}}
{{end}} {{end}}
{{else if eq (len $.UserAndOrgForks) 0}} {{else if not $.UserAndOrgForks}}
href="{{AppSubUrl}}/repo/fork/{{.ID}}" href="{{AppSubUrl}}/repo/fork/{{.ID}}"
{{else}} {{else}}
data-modal="#fork-repo-modal" data-modal="#fork-repo-modal"

View File

@ -1,6 +1,6 @@
<div id="issue-filters" class="issue-list-toolbar"> <div id="issue-filters" class="issue-list-toolbar">
<div class="issue-list-toolbar-left"> <div class="issue-list-toolbar-left">
{{if and ($.CanWriteIssuesOrPulls) (gt (len .Issues) 0)}} {{if and $.CanWriteIssuesOrPulls .Issues}}
<input type="checkbox" autocomplete="off" class="issue-checkbox-all gt-mr-4" title="{{ctx.Locale.Tr "repo.issues.action_check_all"}}"> <input type="checkbox" autocomplete="off" class="issue-checkbox-all gt-mr-4" title="{{ctx.Locale.Tr "repo.issues.action_check_all"}}">
{{end}} {{end}}
{{template "repo/issue/openclose" .}} {{template "repo/issue/openclose" .}}

View File

@ -339,7 +339,7 @@
</div> </div>
</div> </div>
{{end}} {{end}}
{{if gt (len .WorkingUsers) 0}} {{if .WorkingUsers}}
<div class="divider"></div> <div class="divider"></div>
<div class="ui comments"> <div class="ui comments">
<span class="text"><strong>{{ctx.Locale.Tr "repo.issues.time_spent_from_all_authors" ($.Issue.TotalTrackedTime | Sec2Time) | Safe}}</strong></span> <span class="text"><strong>{{ctx.Locale.Tr "repo.issues.time_spent_from_all_authors" ($.Issue.TotalTrackedTime | Sec2Time) | Safe}}</strong></span>

View File

@ -140,7 +140,7 @@
{{ctx.Locale.TrN $waitingOfficial "repo.pulls.waiting_count_1" "repo.pulls.waiting_count_n" $waitingOfficial}} {{ctx.Locale.TrN $waitingOfficial "repo.pulls.waiting_count_1" "repo.pulls.waiting_count_n" $waitingOfficial}}
</span> </span>
{{end}} {{end}}
{{if and (not .PullRequest.HasMerged) (gt (len .PullRequest.ConflictedFiles) 0)}} {{if and (not .PullRequest.HasMerged) .PullRequest.ConflictedFiles}}
<span class="conflicting flex-text-inline"> <span class="conflicting flex-text-inline">
{{svg "octicon-x" 14}} {{svg "octicon-x" 14}}
{{ctx.Locale.TrN (len .PullRequest.ConflictedFiles) "repo.pulls.num_conflicting_files_1" "repo.pulls.num_conflicting_files_n" (len .PullRequest.ConflictedFiles)}} {{ctx.Locale.TrN (len .PullRequest.ConflictedFiles) "repo.pulls.num_conflicting_files_1" "repo.pulls.num_conflicting_files_n" (len .PullRequest.ConflictedFiles)}}

View File

@ -11728,12 +11728,6 @@
"name": "pre-release", "name": "pre-release",
"in": "query" "in": "query"
}, },
{
"type": "integer",
"description": "page size of results, deprecated - use limit",
"name": "per_page",
"in": "query"
},
{ {
"type": "integer", "type": "integer",
"description": "page number of results to return (1-based)", "description": "page number of results to return (1-based)",

View File

@ -106,7 +106,7 @@
{{else if .GetOpType.InActions "comment_issue" "approve_pull_request" "reject_pull_request" "comment_pull"}} {{else if .GetOpType.InActions "comment_issue" "approve_pull_request" "reject_pull_request" "comment_pull"}}
<a href="{{.GetCommentLink ctx}}" class="text truncate issue title">{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}</a> <a href="{{.GetCommentLink ctx}}" class="text truncate issue title">{{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}}</a>
{{$comment := index .GetIssueInfos 1}} {{$comment := index .GetIssueInfos 1}}
{{if gt (len $comment) 0}} {{if $comment}}
<div class="markup gt-font-14">{{RenderMarkdownToHtml ctx $comment}}</div> <div class="markup gt-font-14">{{RenderMarkdownToHtml ctx $comment}}</div>
{{end}} {{end}}
{{else if .GetOpType.InActions "merge_pull_request"}} {{else if .GetOpType.InActions "merge_pull_request"}}

View File

@ -24,7 +24,7 @@
</div> </div>
<div class="gt-p-0"> <div class="gt-p-0">
<div id="notification_table"> <div id="notification_table">
{{if eq (len .Notifications) 0}} {{if not .Notifications}}
<div class="gt-df gt-ac gt-fc gt-p-4"> <div class="gt-df gt-ac gt-fc gt-p-4">
{{svg "octicon-inbox" 56 "gt-mb-4"}} {{svg "octicon-inbox" 56 "gt-mb-4"}}
{{if eq .Status 1}} {{if eq .Status 1}}

View File

@ -63,7 +63,7 @@
</div> </div>
</div> </div>
<div class="divider"></div> <div class="divider"></div>
{{if eq (len .Issues) 0}} {{if not .Issues}}
{{ctx.Locale.Tr "notification.no_subscriptions"}} {{ctx.Locale.Tr "notification.no_subscriptions"}}
{{else}} {{else}}
{{template "shared/issuelist" dict "." . "listType" "dashboard"}} {{template "shared/issuelist" dict "." . "listType" "dashboard"}}

View File

@ -55,7 +55,7 @@
{{if .Verified}} {{if .Verified}}
<span class="flex-text-block" data-tooltip-content="{{ctx.Locale.Tr "settings.gpg_key_verified_long"}}">{{svg "octicon-verified"}} <strong>{{ctx.Locale.Tr "settings.gpg_key_verified"}}</strong></span> <span class="flex-text-block" data-tooltip-content="{{ctx.Locale.Tr "settings.gpg_key_verified_long"}}">{{svg "octicon-verified"}} <strong>{{ctx.Locale.Tr "settings.gpg_key_verified"}}</strong></span>
{{end}} {{end}}
{{if gt (len .Emails) 0}} {{if .Emails}}
<span class="flex-text-block" data-tooltip-content="{{ctx.Locale.Tr "settings.gpg_key_matched_identities_long"}}">{{svg "octicon-mail"}} {{ctx.Locale.Tr "settings.gpg_key_matched_identities"}} {{range .Emails}}<strong>{{.Email}} </strong>{{end}}</span> <span class="flex-text-block" data-tooltip-content="{{ctx.Locale.Tr "settings.gpg_key_matched_identities_long"}}">{{svg "octicon-mail"}} {{ctx.Locale.Tr "settings.gpg_key_matched_identities"}} {{range .Emails}}<strong>{{.Email}} </strong>{{end}}</span>
{{end}} {{end}}
<div class="flex-item-body"> <div class="flex-item-body">

View File

@ -149,12 +149,18 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`, user.Name, user.Name, setting.AppN
url := rootURL + "/repodata" url := rootURL + "/repodata"
req := NewRequest(t, "GET", url+"/dummy.xml") req := NewRequest(t, "HEAD", url+"/dummy.xml")
MakeRequest(t, req, http.StatusNotFound)
req = NewRequest(t, "GET", url+"/dummy.xml")
MakeRequest(t, req, http.StatusNotFound) MakeRequest(t, req, http.StatusNotFound)
t.Run("repomd.xml", func(t *testing.T) { t.Run("repomd.xml", func(t *testing.T) {
defer tests.PrintCurrentTest(t)() defer tests.PrintCurrentTest(t)()
req = NewRequest(t, "HEAD", url+"/repomd.xml")
MakeRequest(t, req, http.StatusOK)
req = NewRequest(t, "GET", url+"/repomd.xml") req = NewRequest(t, "GET", url+"/repomd.xml")
resp := MakeRequest(t, req, http.StatusOK) resp := MakeRequest(t, req, http.StatusOK)