1
1
mirror of https://github.com/go-gitea/gitea synced 2025-01-19 06:04:26 +00:00

Fix raw file API ref handling (#33172)

Fix #33164 and add more tests
This commit is contained in:
wxiaoguang 2025-01-10 09:31:49 +08:00 committed by GitHub
parent 8f8ad8e272
commit 65aae0912a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 48 additions and 43 deletions

View File

@ -293,8 +293,7 @@ func RepoRefForAPI(next http.Handler) http.Handler {
return return
} }
// NOTICE: the "ref" here for internal usage only (e.g. woodpecker) refName, _ := getRefNameLegacy(ctx.Base, ctx.Repo, ctx.PathParam("*"), ctx.FormTrim("ref"))
refName, _ := getRefNameLegacy(ctx.Base, ctx.Repo, ctx.FormTrim("ref"))
var err error var err error
if ctx.Repo.GitRepo.IsBranchExist(refName) { if ctx.Repo.GitRepo.IsBranchExist(refName) {

View File

@ -765,35 +765,30 @@ func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool
return "" return ""
} }
func getRefNameLegacy(ctx *Base, repo *Repository, optionalExtraRef ...string) (string, RepoRefType) { func getRefNameLegacy(ctx *Base, repo *Repository, reqPath, extraRef string) (string, RepoRefType) {
extraRef := util.OptionalArg(optionalExtraRef) reqRefPath := path.Join(extraRef, reqPath)
reqPath := ctx.PathParam("*") reqRefPathParts := strings.Split(reqRefPath, "/")
reqPath = path.Join(extraRef, reqPath) if refName := getRefName(ctx, repo, reqRefPath, RepoRefBranch); refName != "" {
if refName := getRefName(ctx, repo, RepoRefBranch); refName != "" {
return refName, RepoRefBranch return refName, RepoRefBranch
} }
if refName := getRefName(ctx, repo, RepoRefTag); refName != "" { if refName := getRefName(ctx, repo, reqRefPath, RepoRefTag); refName != "" {
return refName, RepoRefTag return refName, RepoRefTag
} }
if git.IsStringLikelyCommitID(git.ObjectFormatFromName(repo.Repository.ObjectFormatName), reqRefPathParts[0]) {
// For legacy support only full commit sha
parts := strings.Split(reqPath, "/")
if git.IsStringLikelyCommitID(git.ObjectFormatFromName(repo.Repository.ObjectFormatName), parts[0]) {
// FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists // FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
repo.TreePath = strings.Join(parts[1:], "/") repo.TreePath = strings.Join(reqRefPathParts[1:], "/")
return parts[0], RepoRefCommit return reqRefPathParts[0], RepoRefCommit
} }
if refName := getRefName(ctx, repo, reqPath, RepoRefBlob); refName != "" {
if refName := getRefName(ctx, repo, RepoRefBlob); len(refName) > 0 {
return refName, RepoRefBlob return refName, RepoRefBlob
} }
// FIXME: the old code falls back to default branch if "ref" doesn't exist, there could be an edge case:
// "README?ref=no-such" would read the README file from the default branch, but the user might expect a 404
repo.TreePath = reqPath repo.TreePath = reqPath
return repo.Repository.DefaultBranch, RepoRefBranch return repo.Repository.DefaultBranch, RepoRefBranch
} }
func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string { func getRefName(ctx *Base, repo *Repository, path string, pathType RepoRefType) string {
path := ctx.PathParam("*")
switch pathType { switch pathType {
case RepoRefBranch: case RepoRefBranch:
ref := getRefNameFromPath(repo, path, repo.GitRepo.IsBranchExist) ref := getRefNameFromPath(repo, path, repo.GitRepo.IsBranchExist)
@ -889,7 +884,8 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
} }
// Get default branch. // Get default branch.
if len(ctx.PathParam("*")) == 0 { reqPath := ctx.PathParam("*")
if reqPath == "" {
refName = ctx.Repo.Repository.DefaultBranch refName = ctx.Repo.Repository.DefaultBranch
if !ctx.Repo.GitRepo.IsBranchExist(refName) { if !ctx.Repo.GitRepo.IsBranchExist(refName) {
brs, _, err := ctx.Repo.GitRepo.GetBranches(0, 1) brs, _, err := ctx.Repo.GitRepo.GetBranches(0, 1)
@ -914,12 +910,12 @@ func RepoRefByType(detectRefType RepoRefType, opts ...RepoRefByTypeOptions) func
return return
} }
ctx.Repo.IsViewBranch = true ctx.Repo.IsViewBranch = true
} else { } else { // there is a path in request
guessLegacyPath := refType == RepoRefUnknown guessLegacyPath := refType == RepoRefUnknown
if guessLegacyPath { if guessLegacyPath {
refName, refType = getRefNameLegacy(ctx.Base, ctx.Repo) refName, refType = getRefNameLegacy(ctx.Base, ctx.Repo, reqPath, "")
} else { } else {
refName = getRefName(ctx.Base, ctx.Repo, refType) refName = getRefName(ctx.Base, ctx.Repo, reqPath, refType)
} }
ctx.Repo.RefName = refName ctx.Repo.RefName = refName
isRenamedBranch, has := ctx.Data["IsRenamedBranch"].(bool) isRenamedBranch, has := ctx.Data["IsRenamedBranch"].(bool)

View File

@ -18,6 +18,7 @@ import (
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
repo_service "code.gitea.io/gitea/services/repository" repo_service "code.gitea.io/gitea/services/repository"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -168,28 +169,37 @@ func testAPIGetContents(t *testing.T, u *url.URL) {
} }
func TestAPIGetContentsRefFormats(t *testing.T) { func TestAPIGetContentsRefFormats(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) { defer tests.PrepareTestEnv(t)()
file := "README.md"
sha := "65f1bf27bc3bf70f64657658635e66094edbcb4d"
content := "# repo1\n\nDescription for repo1"
noRef := setting.AppURL + "api/v1/repos/user2/repo1/raw/" + file file := "README.md"
refInPath := setting.AppURL + "api/v1/repos/user2/repo1/raw/" + sha + "/" + file sha := "65f1bf27bc3bf70f64657658635e66094edbcb4d"
refInQuery := setting.AppURL + "api/v1/repos/user2/repo1/raw/" + file + "?ref=" + sha content := "# repo1\n\nDescription for repo1"
resp := MakeRequest(t, NewRequest(t, http.MethodGet, noRef), http.StatusOK) resp := MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/"+file), http.StatusOK)
raw, err := io.ReadAll(resp.Body) raw, err := io.ReadAll(resp.Body)
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, content, string(raw)) assert.EqualValues(t, content, string(raw))
resp = MakeRequest(t, NewRequest(t, http.MethodGet, refInPath), http.StatusOK) resp = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/"+sha+"/"+file), http.StatusOK)
raw, err = io.ReadAll(resp.Body) raw, err = io.ReadAll(resp.Body)
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, content, string(raw)) assert.EqualValues(t, content, string(raw))
resp = MakeRequest(t, NewRequest(t, http.MethodGet, refInQuery), http.StatusOK) resp = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/"+file+"?ref="+sha), http.StatusOK)
raw, err = io.ReadAll(resp.Body) raw, err = io.ReadAll(resp.Body)
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, content, string(raw)) assert.EqualValues(t, content, string(raw))
})
resp = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/"+file+"?ref=master"), http.StatusOK)
raw, err = io.ReadAll(resp.Body)
assert.NoError(t, err)
assert.EqualValues(t, content, string(raw))
_ = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/docs/README.md?ref=main"), http.StatusNotFound)
_ = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/README.md?ref=main"), http.StatusOK)
_ = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/docs/README.md?ref=sub-home-md-img-check"), http.StatusOK)
_ = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/README.md?ref=sub-home-md-img-check"), http.StatusNotFound)
// FIXME: this is an incorrect behavior, non-existing branch falls back to default branch
_ = MakeRequest(t, NewRequest(t, http.MethodGet, "/api/v1/repos/user2/repo1/raw/README.md?ref=no-such"), http.StatusOK)
} }