aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2025-07-18 17:42:44 +0800
committerGitHub <noreply@github.com>2025-07-18 09:42:44 +0000
commit8f91bfe9d82e6da43c12a60b5a54f910e076a560 (patch)
treeb2043b6d1d95f26cd0b0a7fb9f9f4a9a8bf8cf5a
parent13b9659952f72cbbca05a35fd90375cb80c0841f (diff)
downloadgitea-8f91bfe9d82e6da43c12a60b5a54f910e076a560.tar.gz
gitea-8f91bfe9d82e6da43c12a60b5a54f910e076a560.zip
Fix submodule parsing when the gitmodules is missing (#35109)
Follow up #35096, fix #35095, fix #35115 and add more tests The old code used some fragile behaviors which depend on the "nil" receiver. This PR should be a complete fix for more edge cases.
-rw-r--r--modules/git/commit_info.go6
-rw-r--r--modules/git/commit_info_test.go9
-rw-r--r--modules/git/commit_submodule_file.go13
-rw-r--r--modules/git/commit_submodule_file_test.go2
-rw-r--r--routers/web/repo/view_home.go3
-rw-r--r--services/repository/files/tree.go4
6 files changed, 28 insertions, 9 deletions
diff --git a/modules/git/commit_info.go b/modules/git/commit_info.go
index 9079e36677..b44e9fa51d 100644
--- a/modules/git/commit_info.go
+++ b/modules/git/commit_info.go
@@ -15,8 +15,12 @@ type CommitInfo struct {
func getCommitInfoSubmoduleFile(repoLink string, entry *TreeEntry, commit *Commit, treePathDir string) (*CommitSubmoduleFile, error) {
fullPath := path.Join(treePathDir, entry.Name())
submodule, err := commit.GetSubModule(fullPath)
- if submodule == nil || err != nil {
+ 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, submodule.URL, entry.ID.String()), nil
}
diff --git a/modules/git/commit_info_test.go b/modules/git/commit_info_test.go
index f8060bc33d..5f2eb5e129 100644
--- a/modules/git/commit_info_test.go
+++ b/modules/git/commit_info_test.go
@@ -129,7 +129,14 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
require.NoError(t, err)
cisf, err := getCommitInfoSubmoduleFile("/any/repo-link", tree, commit, "")
require.NoError(t, err)
- assert.Nil(t, cisf)
+ assert.Equal(t, &CommitSubmoduleFile{
+ repoLink: "/any/repo-link",
+ fullPath: "file1.txt",
+ refURL: "",
+ refID: "e2129701f1a4d54dc44f03c93bca0a2aec7c5449",
+ }, cisf)
+ // since there is no refURL, it means that the submodule info doesn't exist, so it won't have a web link
+ assert.Nil(t, cisf.SubmoduleWebLinkTree(t.Context()))
})
}
diff --git a/modules/git/commit_submodule_file.go b/modules/git/commit_submodule_file.go
index 34f582c21f..a3f63710de 100644
--- a/modules/git/commit_submodule_file.go
+++ b/modules/git/commit_submodule_file.go
@@ -29,12 +29,16 @@ func NewCommitSubmoduleFile(repoLink, fullPath, refURL, refID string) *CommitSub
return &CommitSubmoduleFile{repoLink: repoLink, fullPath: fullPath, refURL: refURL, refID: refID}
}
+// RefID returns the commit ID of the submodule, it returns empty string for nil receiver
func (sf *CommitSubmoduleFile) RefID() string {
+ if sf == nil {
+ return ""
+ }
return sf.refID
}
func (sf *CommitSubmoduleFile) getWebLinkInTargetRepo(ctx context.Context, moreLinkPath string) *SubmoduleWebLink {
- if sf == nil {
+ if sf == nil || sf.refURL == "" {
return nil
}
if strings.HasPrefix(sf.refURL, "../") {
@@ -53,14 +57,13 @@ func (sf *CommitSubmoduleFile) getWebLinkInTargetRepo(ctx context.Context, moreL
}
// SubmoduleWebLinkTree tries to make the submodule's tree link in its own repo, it also works on "nil" receiver
+// It returns nil if the submodule does not have a valid URL or is nil
func (sf *CommitSubmoduleFile) SubmoduleWebLinkTree(ctx context.Context, optCommitID ...string) *SubmoduleWebLink {
- if sf == nil {
- return nil
- }
- return sf.getWebLinkInTargetRepo(ctx, "/tree/"+util.OptionalArg(optCommitID, sf.refID))
+ return sf.getWebLinkInTargetRepo(ctx, "/tree/"+util.OptionalArg(optCommitID, sf.RefID()))
}
// SubmoduleWebLinkCompare tries to make the submodule's compare link in its own repo, it also works on "nil" receiver
+// It returns nil if the submodule does not have a valid URL or is nil
func (sf *CommitSubmoduleFile) SubmoduleWebLinkCompare(ctx context.Context, commitID1, commitID2 string) *SubmoduleWebLink {
return sf.getWebLinkInTargetRepo(ctx, "/compare/"+commitID1+"..."+commitID2)
}
diff --git a/modules/git/commit_submodule_file_test.go b/modules/git/commit_submodule_file_test.go
index fc2ff39bda..203939fb1b 100644
--- a/modules/git/commit_submodule_file_test.go
+++ b/modules/git/commit_submodule_file_test.go
@@ -12,6 +12,8 @@ import (
func TestCommitSubmoduleLink(t *testing.T) {
assert.Nil(t, (*CommitSubmoduleFile)(nil).SubmoduleWebLinkTree(t.Context()))
assert.Nil(t, (*CommitSubmoduleFile)(nil).SubmoduleWebLinkCompare(t.Context(), "", ""))
+ assert.Nil(t, (&CommitSubmoduleFile{}).SubmoduleWebLinkTree(t.Context()))
+ assert.Nil(t, (&CommitSubmoduleFile{}).SubmoduleWebLinkCompare(t.Context(), "", ""))
t.Run("GitHubRepo", func(t *testing.T) {
sf := NewCommitSubmoduleFile("/any/repo-link", "full-path", "git@github.com:user/repo.git", "aaaa")
diff --git a/routers/web/repo/view_home.go b/routers/web/repo/view_home.go
index 5482780c98..fd6e746381 100644
--- a/routers/web/repo/view_home.go
+++ b/routers/web/repo/view_home.go
@@ -259,9 +259,10 @@ func handleRepoEmptyOrBroken(ctx *context.Context) {
}
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, "prepareToRenderDirOrFile: ParseRepositoryURL", err)
+ HandleGitError(ctx, "handleRepoViewSubmodule: ParseRepositoryURL", err)
return
}
submoduleURL := giturl.MakeRepositoryWebLink(submoduleRepoURL)
diff --git a/services/repository/files/tree.go b/services/repository/files/tree.go
index 27b4cbf56d..419dbedd74 100644
--- a/services/repository/files/tree.go
+++ b/services/repository/files/tree.go
@@ -174,7 +174,9 @@ func newTreeViewNodeFromEntry(ctx context.Context, repoLink string, renderedIcon
} else if subModule != nil {
submoduleFile := git.NewCommitSubmoduleFile(repoLink, node.FullPath, subModule.URL, entry.ID.String())
webLink := submoduleFile.SubmoduleWebLinkTree(ctx)
- node.SubmoduleURL = webLink.CommitWebLink
+ if webLink != nil {
+ node.SubmoduleURL = webLink.CommitWebLink
+ }
}
}