Skip to content

Commit 0c79f1f

Browse files
committed
Recursively search all sub-repos, not just the top level.
1 parent 157db58 commit 0c79f1f

File tree

1 file changed

+48
-14
lines changed

1 file changed

+48
-14
lines changed

subtrac.go

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -321,25 +321,58 @@ func commitPath(path string, sub int) string {
321321
return fmt.Sprintf("%s~%d", path[:ix], v+1)
322322
}
323323

324+
// Recursively open all submodule repositories, starting at c.repo, and
325+
// return a list of them.
326+
func (c *Cache) allSubrepos() (paths []string, repos []*git.Repository, err error) {
327+
var expand func(string, *git.Repository) error
328+
expand = func(path string, r *git.Repository) error {
329+
wt, err := r.Worktree()
330+
if err != nil {
331+
return fmt.Errorf("git worktree(%s): %v", path, err)
332+
}
333+
subs, err := wt.Submodules()
334+
if err != nil {
335+
return fmt.Errorf("git submodules(%s): %v", path, subs)
336+
}
337+
for _, sub := range subs {
338+
subpath := path
339+
if subpath != "" {
340+
subpath += "/modules/"
341+
}
342+
subpath += sub.Config().Path
343+
subr, err := sub.Repository()
344+
if err != nil {
345+
return fmt.Errorf("git repo(%v): %v", subpath, err)
346+
}
347+
paths = append(paths, subpath)
348+
repos = append(repos, subr)
349+
err = expand(subpath, subr)
350+
if err != nil {
351+
return nil
352+
}
353+
}
354+
return nil
355+
}
356+
357+
err = expand("", c.repo)
358+
if err != nil {
359+
return nil, nil, err
360+
}
361+
return paths, repos, nil
362+
}
363+
324364
// Try to find a given commit object in all submodule repositories. If it
325365
// exists, 'git fetch' it into the main repository so we can refer to it
326366
// as a parent of our synthetic commits.
327367
func (c *Cache) tryFetchFromSubmodules(path string, hash plumbing.Hash) error {
328368
c.infof("Searching submodules for: %v\n", path)
329-
wt, err := c.repo.Worktree()
369+
paths, repos, err := c.allSubrepos()
330370
if err != nil {
331-
return fmt.Errorf("git worktree: %v", err)
332-
}
333-
subs, err := wt.Submodules()
334-
if err != nil {
335-
return fmt.Errorf("git submodules: %v", subs)
371+
return err
336372
}
337-
for _, sub := range subs {
338-
subpath := sub.Config().Path
339-
subr, err := sub.Repository()
340-
if err != nil {
341-
return fmt.Errorf("submodule %v: %v", subpath, err)
342-
}
373+
for i := range repos {
374+
subpath := paths[i]
375+
subr := repos[i]
343376
_, err = subr.CommitObject(hash)
344377
if err != nil {
345378
c.infof(" ...not in %v\n", subpath)
@@ -354,8 +387,9 @@ func (c *Cache) tryFetchFromSubmodules(path string, hash plumbing.Hash) error {
354387
if err != nil {
355388
return fmt.Errorf("submodule %v: create %v: %v", subpath, ref, err)
356389
}
357-
remotename := fmt.Sprintf("%v/.git/modules/%v",
358-
c.repoDir, sub.Config().Name)
390+
// TODO(apenwarr): go-git should provide this path?
391+
// Maybe it does, but I can't figure out where.
392+
remotename := fmt.Sprintf("%v/.git/modules/%v", c.repoDir, subpath)
359393
absremotename, err := filepath.Abs(remotename)
360394
if err != nil {
361395
return fmt.Errorf("AbsPath(%v): %v", remotename, err)

0 commit comments

Comments
 (0)