Skip to content

Commit 354ff79

Browse files
committed
Add submodule indexing without repo cache
When not using repo cache, index git submodules recursively into subrepos using the go-git API
1 parent f5f7877 commit 354ff79

File tree

2 files changed

+113
-5
lines changed

2 files changed

+113
-5
lines changed

gitindex/index.go

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -831,10 +831,13 @@ func prepareDeltaBuild(options Options, repository *git.Repository) (repos map[f
831831

832832
func prepareNormalBuild(options Options, repository *git.Repository) (repos map[fileKey]BlobLocation, branchVersions map[string]map[string]plumbing.Hash, err error) {
833833
var repoCache *RepoCache
834-
if options.Submodules {
834+
if options.Submodules && options.RepoCacheDir != "" {
835835
repoCache = NewRepoCache(options.RepoCacheDir)
836836
}
837+
return prepareNormalBuildRecurse(options, repository, repoCache, false)
838+
}
837839

840+
func prepareNormalBuildRecurse(options Options, repository *git.Repository, repoCache *RepoCache, isSubrepo bool) (repos map[fileKey]BlobLocation, branchVersions map[string]map[string]plumbing.Hash, err error) {
838841
// Branch => Repo => SHA1
839842
branchVersions = map[string]map[string]plumbing.Hash{}
840843

@@ -843,7 +846,22 @@ func prepareNormalBuild(options Options, repository *git.Repository) (repos map[
843846
return nil, nil, fmt.Errorf("expandBranches: %w", err)
844847
}
845848

846-
rw := NewRepoWalker(repository, options.BuildOptions.RepositoryDescription.URL, repoCache)
849+
repoURL := options.BuildOptions.RepositoryDescription.URL
850+
851+
if isSubrepo {
852+
cfg, err := repository.Config()
853+
if err != nil {
854+
return nil, nil, fmt.Errorf("unable to get repository config: %w", err)
855+
}
856+
857+
u, err := normalizeSubmoduleRemoteURL(cfg)
858+
if err != nil {
859+
return nil, nil, fmt.Errorf("failed to identify subrepository URL: %w", err)
860+
}
861+
repoURL = u.String()
862+
}
863+
864+
rw := NewRepoWalker(repository, repoURL, repoCache)
847865
for _, b := range branches {
848866
commit, err := getCommit(repository, options.BranchPrefix, b)
849867
if err != nil {
@@ -872,6 +890,47 @@ func prepareNormalBuild(options Options, repository *git.Repository) (repos map[
872890
branchVersions[b] = subVersions
873891
}
874892

893+
// Index submodules using go-git if we didn't do so using the repo cache
894+
if options.Submodules && options.RepoCacheDir == "" {
895+
worktree, err := repository.Worktree()
896+
if err != nil {
897+
return nil, nil, fmt.Errorf("failed to get repository worktree: %w", err)
898+
}
899+
900+
submodules, err := worktree.Submodules()
901+
if err != nil {
902+
return nil, nil, fmt.Errorf("failed to get submodules: %w", err)
903+
}
904+
905+
for _, submodule := range submodules {
906+
subRepository, err := submodule.Repository()
907+
if err != nil {
908+
log.Printf("failed to open submodule repository: %s, %s", submodule.Config().Name, err)
909+
continue
910+
}
911+
912+
sw, subVersions, err := prepareNormalBuildRecurse(options, subRepository, repoCache, true)
913+
if err != nil {
914+
log.Printf("failed to index submodule repository: %s, %s", submodule.Config().Name, err)
915+
continue
916+
}
917+
918+
log.Printf("adding subrepository files from: %s", submodule.Config().Name)
919+
920+
for k, repo := range sw {
921+
rw.Files[fileKey{
922+
SubRepoPath: filepath.Join(submodule.Config().Path, k.SubRepoPath),
923+
Path: k.Path,
924+
ID: k.ID,
925+
}] = repo
926+
}
927+
928+
for k, v := range subVersions {
929+
branchVersions[filepath.Join(submodule.Config().Path, k)] = v
930+
}
931+
}
932+
}
933+
875934
return rw.Files, branchVersions, nil
876935
}
877936

gitindex/tree.go

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"strings"
2525

2626
"github.com/go-git/go-git/v5"
27+
"github.com/go-git/go-git/v5/config"
2728
"github.com/go-git/go-git/v5/plumbing"
2829
"github.com/go-git/go-git/v5/plumbing/filemode"
2930
"github.com/go-git/go-git/v5/plumbing/object"
@@ -93,6 +94,39 @@ func (rw *RepoWalker) parseModuleMap(t *object.Tree) error {
9394
return nil
9495
}
9596

97+
// This attempts to get a repo URL similar to the main repository template processing as in setTemplatesFromConfig()
98+
func normalizeSubmoduleRemoteURL(cfg *config.Config) (*url.URL, error) {
99+
sec := cfg.Raw.Section("zoekt")
100+
remoteURL := sec.Options.Get("web-url")
101+
if remoteURL == "" {
102+
// fall back to "origin" remote
103+
remoteURL = configLookupRemoteURL(cfg, "origin")
104+
if remoteURL == "" {
105+
return nil, fmt.Errorf("no remote URL found in git config")
106+
}
107+
}
108+
109+
if sm := sshRelativeURLRegexp.FindStringSubmatch(remoteURL); sm != nil {
110+
user := sm[1]
111+
host := sm[2]
112+
path := sm[3]
113+
114+
remoteURL = fmt.Sprintf("ssh+git://%s@%s/%s", user, host, path)
115+
}
116+
117+
u, err := url.Parse(remoteURL)
118+
if err != nil {
119+
return nil, fmt.Errorf("unable to parse remote URL %q: %w", remoteURL, err)
120+
}
121+
122+
if u.Scheme == "ssh+git" {
123+
u.Scheme = "https"
124+
u.User = nil
125+
}
126+
127+
return u, nil
128+
}
129+
96130
// CollectFiles fetches the blob SHA1s for the tree. If repoCache is
97131
// non-nil, recurse into submodules. In addition, it returns a mapping
98132
// that indicates in which repo each SHA1 can be found.
@@ -159,6 +193,14 @@ func (rw *RepoWalker) handleSubmodule(p string, id *plumbing.Hash, branch string
159193

160194
subRepoVersions[p] = *id
161195

196+
cfg, err := subRepo.Config()
197+
if err == nil {
198+
subRemoteURL, err := normalizeSubmoduleRemoteURL(cfg)
199+
if err == nil {
200+
subURL = subRemoteURL
201+
}
202+
}
203+
162204
sw := NewRepoWalker(subRepo, subURL.String(), rw.repoCache)
163205
subVersions, err := sw.CollectFiles(tree, branch, ig)
164206
if err != nil {
@@ -178,9 +220,16 @@ func (rw *RepoWalker) handleSubmodule(p string, id *plumbing.Hash, branch string
178220
}
179221

180222
func (rw *RepoWalker) handleEntry(p string, e *object.TreeEntry, branch string, subRepoVersions map[string]plumbing.Hash, ig *ignore.Matcher) error {
181-
if e.Mode == filemode.Submodule && rw.repoCache != nil {
182-
if err := rw.tryHandleSubmodule(p, &e.Hash, branch, subRepoVersions, ig); err != nil {
183-
return fmt.Errorf("submodule %s: %v", p, err)
223+
if e.Mode == filemode.Submodule {
224+
if rw.repoCache != nil {
225+
// Index the submodule using repo cache
226+
if err := rw.tryHandleSubmodule(p, &e.Hash, branch, subRepoVersions, ig); err != nil {
227+
return fmt.Errorf("submodule %s: %v", p, err)
228+
}
229+
} else {
230+
// Record the commit ID for the submodule path
231+
// This will be the submodule's commit hash, not the parent's
232+
subRepoVersions[p] = e.Hash
184233
}
185234
}
186235

0 commit comments

Comments
 (0)