@@ -373,8 +373,8 @@ func commitPath(path string, sub int) string {
373
373
// Recursively open all submodule repositories, starting at c.repo, and
374
374
// return a list of them.
375
375
func (c * Cache ) allSubrepos () (paths []string , repos []* git.Repository , err error ) {
376
- var expand func (string , * git.Repository ) error
377
- expand = func (path string , r * git.Repository ) error {
376
+ var recurse func (string , * git.Repository ) error
377
+ recurse = func (path string , r * git.Repository ) error {
378
378
wt , err := r .Worktree ()
379
379
if err != nil {
380
380
return fmt .Errorf ("git worktree(%s): %v" , path , err )
@@ -389,35 +389,51 @@ func (c *Cache) allSubrepos() (paths []string, repos []*git.Repository, err erro
389
389
subpath += "/modules/"
390
390
}
391
391
subpath += sub .Config ().Path
392
+
393
+ ss , err := sub .Status ()
394
+ if err != nil {
395
+ return fmt .Errorf ("git status(%v): %v" , subpath , err )
396
+ }
397
+ empty := plumbing.Hash {}
398
+ if ss .Current == empty {
399
+ // not currently initialized
400
+ c .infof ("git submodule(%s): not initialized; skipping\n " , subpath )
401
+ continue
402
+ }
403
+
392
404
subr , err := sub .Repository ()
393
405
if err != nil {
394
406
return fmt .Errorf ("git repo(%v): %v" , subpath , err )
395
407
}
396
408
paths = append (paths , subpath )
397
409
repos = append (repos , subr )
398
- err = expand (subpath , subr )
410
+ err = recurse (subpath , subr )
399
411
if err != nil {
400
- return nil
412
+ return err
401
413
}
402
414
}
403
415
return nil
404
416
}
405
417
406
- err = expand ("" , c .repo )
418
+ err = recurse ("" , c .repo )
407
419
if err != nil {
408
420
return nil , nil , err
409
421
}
410
422
return paths , repos , nil
411
423
}
412
424
425
+ type NotPresentError struct {}
426
+
427
+ var NotPresent = & NotPresentError {}
428
+
413
429
// Try to find a given commit object in all submodule repositories. If it
414
430
// exists, 'git fetch' it into the main repository so we can refer to it
415
431
// as a parent of our synthetic commits.
416
- func (c * Cache ) tryFetchFromSubmodules (path string , hash plumbing.Hash ) error {
432
+ func (c * Cache ) tryFetchFromSubmodules (path string , hash plumbing.Hash ) ( * NotPresentError , error ) {
417
433
c .infof ("Searching submodules for: %v\n " , path )
418
434
paths , repos , err := c .allSubrepos ()
419
435
if err != nil {
420
- return err
436
+ return nil , err
421
437
}
422
438
for i := range repos {
423
439
subpath := paths [i ]
@@ -434,21 +450,21 @@ func (c *Cache) tryFetchFromSubmodules(path string, hash plumbing.Hash) error {
434
450
err = subr .Storer .SetReference (ref )
435
451
defer subr .Storer .RemoveReference (brrefname )
436
452
if err != nil {
437
- return fmt .Errorf ("submodule %v: create %v: %v" , subpath , ref , err )
453
+ return nil , fmt .Errorf ("submodule %v: create %v: %v" , subpath , ref , err )
438
454
}
439
455
// TODO(apenwarr): go-git should provide this path?
440
456
// Maybe it does, but I can't figure out where.
441
457
remotename := fmt .Sprintf ("%v/.git/modules/%v" , c .repoDir , subpath )
442
458
absremotename , err := filepath .Abs (remotename )
443
459
if err != nil {
444
- return fmt .Errorf ("AbsPath(%v): %v" , remotename , err )
460
+ return nil , fmt .Errorf ("AbsPath(%v): %v" , remotename , err )
445
461
}
446
462
remote , err := c .repo .CreateRemoteAnonymous (& config.RemoteConfig {
447
463
Name : "anonymous" ,
448
464
URLs : []string {absremotename },
449
465
})
450
466
if err != nil {
451
- return fmt .Errorf ("submodule %v: CreateRemote: %v" , absremotename , err )
467
+ return nil , fmt .Errorf ("submodule %v: CreateRemote: %v" , absremotename , err )
452
468
}
453
469
err = remote .Fetch (& git.FetchOptions {
454
470
RemoteName : "anonymous" ,
@@ -457,16 +473,16 @@ func (c *Cache) tryFetchFromSubmodules(path string, hash plumbing.Hash) error {
457
473
},
458
474
})
459
475
if err != nil {
460
- return fmt .Errorf ("submodule %v: fetch: %v" , absremotename , err )
476
+ return nil , fmt .Errorf ("submodule %v: fetch: %v" , absremotename , err )
461
477
}
462
478
// Fetch worked!
463
479
err = subr .Storer .RemoveReference (brrefname )
464
480
if err != nil {
465
- return fmt .Errorf ("submodule %v: remove %v: %v" , subpath , ref , err )
481
+ return nil , fmt .Errorf ("submodule %v: remove %v: %v" , subpath , ref , err )
466
482
}
467
- return nil
483
+ return nil , nil
468
484
}
469
- return fmt .Errorf ("%v: %v not found." , path , hash )
485
+ return NotPresent , fmt .Errorf ("%v: %v not found." , path , hash )
470
486
}
471
487
472
488
// Starting from a given git tree object, recursively add all its subtree
@@ -492,13 +508,13 @@ func (c *Cache) tracTree(path string, tree *object.Tree) (*Trac, error) {
492
508
subpath := fmt .Sprintf ("%s%s@%.10v" , path , e .Name , e .Hash )
493
509
sc , err := c .repo .CommitObject (e .Hash )
494
510
if err != nil {
495
- err = c .tryFetchFromSubmodules (subpath , e .Hash )
511
+ npErr , err := c .tryFetchFromSubmodules (subpath , e .Hash )
512
+ if npErr != nil && c .autoexclude {
513
+ c .infof ("Excluding %v\n " , e .Hash )
514
+ c .exclude (e .Hash )
515
+ continue
516
+ }
496
517
if err != nil {
497
- if c .autoexclude {
498
- c .infof ("Excluding %v\n " , e .Hash )
499
- c .exclude (e .Hash )
500
- continue
501
- }
502
518
return nil , fmt .Errorf ("%v (fetch it manually? or try --exclude)" , err )
503
519
}
504
520
}
0 commit comments