mirror of
https://github.com/go-gitea/gitea
synced 2025-08-01 15:18:37 +00:00
Fix repo file list partial reloading for submodules (#35183)
Fix the TODO and add more tests
This commit is contained in:
@@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
package git
|
package git
|
||||||
|
|
||||||
import "path"
|
|
||||||
|
|
||||||
// CommitInfo describes the first commit with the provided entry
|
// CommitInfo describes the first commit with the provided entry
|
||||||
type CommitInfo struct {
|
type CommitInfo struct {
|
||||||
Entry *TreeEntry
|
Entry *TreeEntry
|
||||||
@@ -12,15 +10,14 @@ type CommitInfo struct {
|
|||||||
SubmoduleFile *CommitSubmoduleFile
|
SubmoduleFile *CommitSubmoduleFile
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCommitInfoSubmoduleFile(repoLink string, entry *TreeEntry, commit *Commit, treePathDir string) (*CommitSubmoduleFile, error) {
|
func GetCommitInfoSubmoduleFile(repoLink, fullPath string, commit *Commit, refCommitID ObjectID) (*CommitSubmoduleFile, error) {
|
||||||
fullPath := path.Join(treePathDir, entry.Name())
|
|
||||||
submodule, err := commit.GetSubModule(fullPath)
|
submodule, err := commit.GetSubModule(fullPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if submodule == nil {
|
if submodule == nil {
|
||||||
// unable to find submodule from ".gitmodules" file
|
// unable to find submodule from ".gitmodules" file
|
||||||
return NewCommitSubmoduleFile(repoLink, fullPath, "", entry.ID.String()), nil
|
return NewCommitSubmoduleFile(repoLink, fullPath, "", refCommitID.String()), nil
|
||||||
}
|
}
|
||||||
return NewCommitSubmoduleFile(repoLink, fullPath, submodule.URL, entry.ID.String()), nil
|
return NewCommitSubmoduleFile(repoLink, fullPath, submodule.URL, refCommitID.String()), nil
|
||||||
}
|
}
|
||||||
|
@@ -73,7 +73,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit *
|
|||||||
|
|
||||||
// If the entry is a submodule, add a submodule file for this
|
// If the entry is a submodule, add a submodule file for this
|
||||||
if entry.IsSubModule() {
|
if entry.IsSubModule() {
|
||||||
commitsInfo[i].SubmoduleFile, err = getCommitInfoSubmoduleFile(repoLink, entry, commit, treePath)
|
commitsInfo[i].SubmoduleFile, err = GetCommitInfoSubmoduleFile(repoLink, path.Join(treePath, entry.Name()), commit, entry.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@@ -64,7 +64,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, repoLink string, commit *
|
|||||||
|
|
||||||
// If the entry is a submodule, add a submodule file for this
|
// If the entry is a submodule, add a submodule file for this
|
||||||
if entry.IsSubModule() {
|
if entry.IsSubModule() {
|
||||||
commitsInfo[i].SubmoduleFile, err = getCommitInfoSubmoduleFile(repoLink, entry, commit, treePath)
|
commitsInfo[i].SubmoduleFile, err = GetCommitInfoSubmoduleFile(repoLink, path.Join(treePath, entry.Name()), commit, entry.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@@ -125,9 +125,9 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
|
|||||||
t.Run("NonExistingSubmoduleAsNil", func(t *testing.T) {
|
t.Run("NonExistingSubmoduleAsNil", func(t *testing.T) {
|
||||||
commit, err := bareRepo1.GetCommit("HEAD")
|
commit, err := bareRepo1.GetCommit("HEAD")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
tree, err := commit.GetTreeEntryByPath("file1.txt")
|
treeEntry, err := commit.GetTreeEntryByPath("file1.txt")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
cisf, err := getCommitInfoSubmoduleFile("/any/repo-link", tree, commit, "")
|
cisf, err := GetCommitInfoSubmoduleFile("/any/repo-link", "file1.txt", commit, treeEntry.ID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, &CommitSubmoduleFile{
|
assert.Equal(t, &CommitSubmoduleFile{
|
||||||
repoLink: "/any/repo-link",
|
repoLink: "/any/repo-link",
|
||||||
|
@@ -19,8 +19,8 @@ import (
|
|||||||
unit_model "code.gitea.io/gitea/models/unit"
|
unit_model "code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
giturl "code.gitea.io/gitea/modules/git/url"
|
|
||||||
"code.gitea.io/gitea/modules/gitrepo"
|
"code.gitea.io/gitea/modules/gitrepo"
|
||||||
|
"code.gitea.io/gitea/modules/htmlutil"
|
||||||
"code.gitea.io/gitea/modules/httplib"
|
"code.gitea.io/gitea/modules/httplib"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
@@ -258,35 +258,41 @@ func handleRepoEmptyOrBroken(ctx *context.Context) {
|
|||||||
ctx.Redirect(link)
|
ctx.Redirect(link)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleRepoViewSubmodule(ctx *context.Context, submodule *git.SubModule) {
|
func isViewHomeOnlyContent(ctx *context.Context) bool {
|
||||||
// TODO: it needs to use git.NewCommitSubmoduleFile and SubmoduleWebLinkTree to correctly handle relative paths
|
return ctx.FormBool("only_content")
|
||||||
submoduleRepoURL, err := giturl.ParseRepositoryURL(ctx, submodule.URL)
|
}
|
||||||
if err != nil {
|
|
||||||
HandleGitError(ctx, "handleRepoViewSubmodule: ParseRepositoryURL", err)
|
func handleRepoViewSubmodule(ctx *context.Context, commitSubmoduleFile *git.CommitSubmoduleFile) {
|
||||||
|
submoduleWebLink := commitSubmoduleFile.SubmoduleWebLinkTree(ctx)
|
||||||
|
if submoduleWebLink == nil {
|
||||||
|
ctx.Data["NotFoundPrompt"] = ctx.Repo.TreePath
|
||||||
|
ctx.NotFound(nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
submoduleURL := giturl.MakeRepositoryWebLink(submoduleRepoURL)
|
|
||||||
if httplib.IsCurrentGiteaSiteURL(ctx, submoduleURL) {
|
redirectLink := submoduleWebLink.CommitWebLink
|
||||||
ctx.RedirectToCurrentSite(submoduleURL)
|
if isViewHomeOnlyContent(ctx) {
|
||||||
} else {
|
ctx.Resp.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
_, _ = ctx.Resp.Write([]byte(htmlutil.HTMLFormat(`<a href="%s">%s</a>`, redirectLink, redirectLink)))
|
||||||
|
} else if !httplib.IsCurrentGiteaSiteURL(ctx, redirectLink) {
|
||||||
// don't auto-redirect to external URL, to avoid open redirect or phishing
|
// don't auto-redirect to external URL, to avoid open redirect or phishing
|
||||||
ctx.Data["NotFoundPrompt"] = submoduleURL
|
ctx.Data["NotFoundPrompt"] = redirectLink
|
||||||
ctx.NotFound(nil)
|
ctx.NotFound(nil)
|
||||||
|
} else {
|
||||||
|
ctx.Redirect(submoduleWebLink.CommitWebLink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareToRenderDirOrFile(entry *git.TreeEntry) func(ctx *context.Context) {
|
func prepareToRenderDirOrFile(entry *git.TreeEntry) func(ctx *context.Context) {
|
||||||
return func(ctx *context.Context) {
|
return func(ctx *context.Context) {
|
||||||
if entry.IsSubModule() {
|
if entry.IsSubModule() {
|
||||||
submodule, err := ctx.Repo.Commit.GetSubModule(entry.Name())
|
commitSubmoduleFile, err := git.GetCommitInfoSubmoduleFile(ctx.Repo.RepoLink, ctx.Repo.TreePath, ctx.Repo.Commit, entry.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
HandleGitError(ctx, "prepareToRenderDirOrFile: GetSubModule", err)
|
HandleGitError(ctx, "prepareToRenderDirOrFile: GetCommitInfoSubmoduleFile", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handleRepoViewSubmodule(ctx, submodule)
|
handleRepoViewSubmodule(ctx, commitSubmoduleFile)
|
||||||
return
|
} else if entry.IsDir() {
|
||||||
}
|
|
||||||
if entry.IsDir() {
|
|
||||||
prepareToRenderDirectory(ctx)
|
prepareToRenderDirectory(ctx)
|
||||||
} else {
|
} else {
|
||||||
prepareFileView(ctx, entry)
|
prepareFileView(ctx, entry)
|
||||||
@@ -441,7 +447,7 @@ func Home(ctx *context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.FormBool("only_content") {
|
if isViewHomeOnlyContent(ctx) {
|
||||||
ctx.HTML(http.StatusOK, tplRepoViewContent)
|
ctx.HTML(http.StatusOK, tplRepoViewContent)
|
||||||
} else if len(treeNames) != 0 {
|
} else if len(treeNames) != 0 {
|
||||||
ctx.HTML(http.StatusOK, tplRepoView)
|
ctx.HTML(http.StatusOK, tplRepoView)
|
||||||
|
@@ -9,7 +9,6 @@ import (
|
|||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
git_module "code.gitea.io/gitea/modules/git"
|
git_module "code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/services/contexttest"
|
"code.gitea.io/gitea/services/contexttest"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -19,14 +18,20 @@ func TestViewHomeSubmoduleRedirect(t *testing.T) {
|
|||||||
unittest.PrepareTestEnv(t)
|
unittest.PrepareTestEnv(t)
|
||||||
|
|
||||||
ctx, _ := contexttest.MockContext(t, "/user2/repo1/src/branch/master/test-submodule")
|
ctx, _ := contexttest.MockContext(t, "/user2/repo1/src/branch/master/test-submodule")
|
||||||
submodule := &git_module.SubModule{Path: "test-submodule", URL: setting.AppURL + "user2/repo-other.git"}
|
submodule := git_module.NewCommitSubmoduleFile("/user2/repo1", "test-submodule", "../repo-other", "any-ref-id")
|
||||||
handleRepoViewSubmodule(ctx, submodule)
|
handleRepoViewSubmodule(ctx, submodule)
|
||||||
assert.Equal(t, http.StatusSeeOther, ctx.Resp.WrittenStatus())
|
assert.Equal(t, http.StatusSeeOther, ctx.Resp.WrittenStatus())
|
||||||
assert.Equal(t, "/user2/repo-other", ctx.Resp.Header().Get("Location"))
|
assert.Equal(t, "/user2/repo-other/tree/any-ref-id", ctx.Resp.Header().Get("Location"))
|
||||||
|
|
||||||
ctx, _ = contexttest.MockContext(t, "/user2/repo1/src/branch/master/test-submodule")
|
ctx, _ = contexttest.MockContext(t, "/user2/repo1/src/branch/master/test-submodule")
|
||||||
submodule = &git_module.SubModule{Path: "test-submodule", URL: "https://other/user2/repo-other.git"}
|
submodule = git_module.NewCommitSubmoduleFile("/user2/repo1", "test-submodule", "https://other/user2/repo-other.git", "any-ref-id")
|
||||||
handleRepoViewSubmodule(ctx, submodule)
|
handleRepoViewSubmodule(ctx, submodule)
|
||||||
// do not auto-redirect for external URLs, to avoid open redirect or phishing
|
// do not auto-redirect for external URLs, to avoid open redirect or phishing
|
||||||
assert.Equal(t, http.StatusNotFound, ctx.Resp.WrittenStatus())
|
assert.Equal(t, http.StatusNotFound, ctx.Resp.WrittenStatus())
|
||||||
|
|
||||||
|
ctx, respWriter := contexttest.MockContext(t, "/user2/repo1/src/branch/master/test-submodule?only_content=true")
|
||||||
|
submodule = git_module.NewCommitSubmoduleFile("/user2/repo1", "test-submodule", "../repo-other", "any-ref-id")
|
||||||
|
handleRepoViewSubmodule(ctx, submodule)
|
||||||
|
assert.Equal(t, http.StatusOK, ctx.Resp.WrittenStatus())
|
||||||
|
assert.Equal(t, `<a href="/user2/repo-other/tree/any-ref-id">/user2/repo-other/tree/any-ref-id</a>`, respWriter.Body.String())
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user