diff --git a/modules/git/commit_info.go b/modules/git/commit_info.go
index b44e9fa51d..4f76a28f31 100644
--- a/modules/git/commit_info.go
+++ b/modules/git/commit_info.go
@@ -3,8 +3,6 @@
package git
-import "path"
-
// CommitInfo describes the first commit with the provided entry
type CommitInfo struct {
Entry *TreeEntry
@@ -12,15 +10,14 @@ type CommitInfo struct {
SubmoduleFile *CommitSubmoduleFile
}
-func getCommitInfoSubmoduleFile(repoLink string, entry *TreeEntry, commit *Commit, treePathDir string) (*CommitSubmoduleFile, error) {
- fullPath := path.Join(treePathDir, entry.Name())
+func GetCommitInfoSubmoduleFile(repoLink, fullPath string, commit *Commit, refCommitID ObjectID) (*CommitSubmoduleFile, error) {
submodule, err := commit.GetSubModule(fullPath)
if err != nil {
return nil, err
}
if submodule == nil {
// 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
}
diff --git a/modules/git/commit_info_gogit.go b/modules/git/commit_info_gogit.go
index 7e03e634a0..73227347bc 100644
--- a/modules/git/commit_info_gogit.go
+++ b/modules/git/commit_info_gogit.go
@@ -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 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 {
return nil, nil, err
}
diff --git a/modules/git/commit_info_nogogit.go b/modules/git/commit_info_nogogit.go
index 161edb7e96..ed775332a9 100644
--- a/modules/git/commit_info_nogogit.go
+++ b/modules/git/commit_info_nogogit.go
@@ -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 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 {
return nil, nil, err
}
diff --git a/modules/git/commit_info_test.go b/modules/git/commit_info_test.go
index 5f2eb5e129..078b6815d2 100644
--- a/modules/git/commit_info_test.go
+++ b/modules/git/commit_info_test.go
@@ -125,9 +125,9 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
t.Run("NonExistingSubmoduleAsNil", func(t *testing.T) {
commit, err := bareRepo1.GetCommit("HEAD")
require.NoError(t, err)
- tree, err := commit.GetTreeEntryByPath("file1.txt")
+ treeEntry, err := commit.GetTreeEntryByPath("file1.txt")
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)
assert.Equal(t, &CommitSubmoduleFile{
repoLink: "/any/repo-link",
diff --git a/routers/web/repo/view_home.go b/routers/web/repo/view_home.go
index fd6e746381..f475e93f60 100644
--- a/routers/web/repo/view_home.go
+++ b/routers/web/repo/view_home.go
@@ -19,8 +19,8 @@ import (
unit_model "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"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/htmlutil"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/log"
repo_module "code.gitea.io/gitea/modules/repository"
@@ -258,35 +258,41 @@ func handleRepoEmptyOrBroken(ctx *context.Context) {
ctx.Redirect(link)
}
-func handleRepoViewSubmodule(ctx *context.Context, submodule *git.SubModule) {
- // TODO: it needs to use git.NewCommitSubmoduleFile and SubmoduleWebLinkTree to correctly handle relative paths
- submoduleRepoURL, err := giturl.ParseRepositoryURL(ctx, submodule.URL)
- if err != nil {
- HandleGitError(ctx, "handleRepoViewSubmodule: ParseRepositoryURL", err)
+func isViewHomeOnlyContent(ctx *context.Context) bool {
+ return ctx.FormBool("only_content")
+}
+
+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
}
- submoduleURL := giturl.MakeRepositoryWebLink(submoduleRepoURL)
- if httplib.IsCurrentGiteaSiteURL(ctx, submoduleURL) {
- ctx.RedirectToCurrentSite(submoduleURL)
- } else {
+
+ redirectLink := submoduleWebLink.CommitWebLink
+ if isViewHomeOnlyContent(ctx) {
+ ctx.Resp.Header().Set("Content-Type", "text/html; charset=utf-8")
+ _, _ = ctx.Resp.Write([]byte(htmlutil.HTMLFormat(`%s`, redirectLink, redirectLink)))
+ } else if !httplib.IsCurrentGiteaSiteURL(ctx, redirectLink) {
// don't auto-redirect to external URL, to avoid open redirect or phishing
- ctx.Data["NotFoundPrompt"] = submoduleURL
+ ctx.Data["NotFoundPrompt"] = redirectLink
ctx.NotFound(nil)
+ } else {
+ ctx.Redirect(submoduleWebLink.CommitWebLink)
}
}
func prepareToRenderDirOrFile(entry *git.TreeEntry) func(ctx *context.Context) {
return func(ctx *context.Context) {
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 {
- HandleGitError(ctx, "prepareToRenderDirOrFile: GetSubModule", err)
+ HandleGitError(ctx, "prepareToRenderDirOrFile: GetCommitInfoSubmoduleFile", err)
return
}
- handleRepoViewSubmodule(ctx, submodule)
- return
- }
- if entry.IsDir() {
+ handleRepoViewSubmodule(ctx, commitSubmoduleFile)
+ } else if entry.IsDir() {
prepareToRenderDirectory(ctx)
} else {
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)
} else if len(treeNames) != 0 {
ctx.HTML(http.StatusOK, tplRepoView)
diff --git a/routers/web/repo/view_home_test.go b/routers/web/repo/view_home_test.go
index 6264dba71c..dd74ae560b 100644
--- a/routers/web/repo/view_home_test.go
+++ b/routers/web/repo/view_home_test.go
@@ -9,7 +9,6 @@ import (
"code.gitea.io/gitea/models/unittest"
git_module "code.gitea.io/gitea/modules/git"
- "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/services/contexttest"
"github.com/stretchr/testify/assert"
@@ -19,14 +18,20 @@ func TestViewHomeSubmoduleRedirect(t *testing.T) {
unittest.PrepareTestEnv(t)
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)
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")
- 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)
// do not auto-redirect for external URLs, to avoid open redirect or phishing
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, `/user2/repo-other/tree/any-ref-id`, respWriter.Body.String())
}