@@ -321,25 +321,58 @@ func commitPath(path string, sub int) string {
321
321
return fmt .Sprintf ("%s~%d" , path [:ix ], v + 1 )
322
322
}
323
323
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
+
324
364
// Try to find a given commit object in all submodule repositories. If it
325
365
// exists, 'git fetch' it into the main repository so we can refer to it
326
366
// as a parent of our synthetic commits.
327
367
func (c * Cache ) tryFetchFromSubmodules (path string , hash plumbing.Hash ) error {
328
368
c .infof ("Searching submodules for: %v\n " , path )
329
- wt , err := c .repo . Worktree ()
369
+ paths , repos , err := c .allSubrepos ()
330
370
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
336
372
}
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 ]
343
376
_ , err = subr .CommitObject (hash )
344
377
if err != nil {
345
378
c .infof (" ...not in %v\n " , subpath )
@@ -354,8 +387,9 @@ func (c *Cache) tryFetchFromSubmodules(path string, hash plumbing.Hash) error {
354
387
if err != nil {
355
388
return fmt .Errorf ("submodule %v: create %v: %v" , subpath , ref , err )
356
389
}
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 )
359
393
absremotename , err := filepath .Abs (remotename )
360
394
if err != nil {
361
395
return fmt .Errorf ("AbsPath(%v): %v" , remotename , err )
0 commit comments