@@ -364,6 +364,85 @@ func (g gitSyncer) initRepo(repoDir, org, repo string) error {
364364 return nil
365365}
366366
367+ // syncRepo initializes a local git repo, fetches branch heads from both source
368+ // and destination via ls-remote, and mirrors each branch that needs syncing.
369+ func (g gitSyncer ) syncRepo (org , repo , targetOrg , dstRepo string , branches []location ) []error {
370+ var errs []error
371+ repoLogger := g .logger
372+
373+ gitDir , err := g .makeGitDir (org , repo )
374+ if err != nil {
375+ for _ , source := range branches {
376+ errs = append (errs , fmt .Errorf ("%s: %w" , source .String (), err ))
377+ }
378+ return errs
379+ }
380+
381+ if err := g .initRepo (gitDir , org , repo ); err != nil {
382+ for _ , source := range branches {
383+ errs = append (errs , fmt .Errorf ("%s: %w" , source .String (), err ))
384+ }
385+ return errs
386+ }
387+
388+ // ls-remote destination once per repo
389+ destUrlRaw := fmt .Sprintf ("%s/%s/%s" , g .prefix , targetOrg , dstRepo )
390+ destUrl , err := url .Parse (destUrlRaw )
391+ if err != nil {
392+ repoLogger .WithField ("remote-url" , destUrlRaw ).WithError (err ).Error ("Failed to construct URL for the destination remote" )
393+ for _ , source := range branches {
394+ errs = append (errs , fmt .Errorf ("%s: failed to construct URL for the destination remote" , source .String ()))
395+ }
396+ return errs
397+ }
398+ if g .token != "" {
399+ destUrl .User = url .User (g .token )
400+ }
401+
402+ dstHeads , err := getRemoteBranchHeads (repoLogger , g .git , gitDir , destUrl .String ())
403+ if err != nil {
404+ message := "destination repository does not exist or we cannot access it"
405+ if g .failOnNonexistentDst {
406+ repoLogger .Errorf ("%s" , message )
407+ for _ , source := range branches {
408+ errs = append (errs , fmt .Errorf ("%s: %s" , source .String (), message ))
409+ }
410+ } else {
411+ repoLogger .Warn (message )
412+ }
413+ return errs
414+ }
415+
416+ // ls-remote source once per repo
417+ srcRemote := fmt .Sprintf ("%s-%s" , org , repo )
418+ srcHeads , err := getRemoteBranchHeads (repoLogger , withRetryOnNonzero (g .git , 5 ), gitDir , srcRemote )
419+ if err != nil {
420+ repoLogger .WithError (err ).Error ("Failed to determine branch HEADs in source" )
421+ for _ , source := range branches {
422+ errs = append (errs , fmt .Errorf ("%s: failed to determine branch HEADs in source" , source .String ()))
423+ }
424+ return errs
425+ }
426+
427+ for _ , source := range branches {
428+ g .logger = config .LoggerForInfo (config.Info {
429+ Metadata : api.Metadata {
430+ Org : source .org ,
431+ Repo : source .repo ,
432+ Branch : source .branch ,
433+ },
434+ })
435+
436+ destination := location {org : targetOrg , repo : dstRepo , branch : source .branch }
437+
438+ if err := g .mirror (gitDir , source , destination , srcHeads , dstHeads , destUrl ); err != nil {
439+ errs = append (errs , fmt .Errorf ("%s->%s: %w" , source .String (), destination .String (), err ))
440+ }
441+ }
442+
443+ return errs
444+ }
445+
367446// mirror syncs a single branch from source to destination, using pre-fetched
368447// branch head information. The `repoDir` must have been previously initialized
369448// with git init and remote setup. The `srcHeads` and `dstHeads` must have been
@@ -651,83 +730,14 @@ func main() {
651730 }
652731
653732 for key , branches := range grouped {
654- repoLogger := logrus .WithFields (logrus.Fields {"org" : key .org , "repo" : key .repo })
655- syncer .logger = repoLogger
733+ syncer .logger = logrus .WithFields (logrus.Fields {"org" : key .org , "repo" : key .repo })
656734
657735 dstRepo := key .repo
658736 if ! flattenedOrgs .Has (key .org ) {
659737 dstRepo = fmt .Sprintf ("%s-%s" , key .org , key .repo )
660738 }
661739
662- gitDir , err := syncer .makeGitDir (key .org , key .repo )
663- if err != nil {
664- for _ , source := range branches {
665- errs = append (errs , fmt .Errorf ("%s: %w" , source .String (), err ))
666- }
667- continue
668- }
669-
670- if err := syncer .initRepo (gitDir , key .org , key .repo ); err != nil {
671- for _ , source := range branches {
672- errs = append (errs , fmt .Errorf ("%s: %w" , source .String (), err ))
673- }
674- continue
675- }
676-
677- // ls-remote destination once per repo
678- destUrlRaw := fmt .Sprintf ("%s/%s/%s" , syncer .prefix , o .targetOrg , dstRepo )
679- destUrl , err := url .Parse (destUrlRaw )
680- if err != nil {
681- repoLogger .WithField ("remote-url" , destUrlRaw ).WithError (err ).Error ("Failed to construct URL for the destination remote" )
682- for _ , source := range branches {
683- errs = append (errs , fmt .Errorf ("%s: failed to construct URL for the destination remote" , source .String ()))
684- }
685- continue
686- }
687- if syncer .token != "" {
688- destUrl .User = url .User (syncer .token )
689- }
690-
691- dstHeads , err := getRemoteBranchHeads (repoLogger , syncer .git , gitDir , destUrl .String ())
692- if err != nil {
693- message := "destination repository does not exist or we cannot access it"
694- if syncer .failOnNonexistentDst {
695- repoLogger .Errorf ("%s" , message )
696- for _ , source := range branches {
697- errs = append (errs , fmt .Errorf ("%s: %s" , source .String (), message ))
698- }
699- } else {
700- repoLogger .Warn (message )
701- }
702- continue
703- }
704-
705- // ls-remote source once per repo
706- srcRemote := fmt .Sprintf ("%s-%s" , key .org , key .repo )
707- srcHeads , err := getRemoteBranchHeads (repoLogger , withRetryOnNonzero (syncer .git , 5 ), gitDir , srcRemote )
708- if err != nil {
709- repoLogger .WithError (err ).Error ("Failed to determine branch HEADs in source" )
710- for _ , source := range branches {
711- errs = append (errs , fmt .Errorf ("%s: failed to determine branch HEADs in source" , source .String ()))
712- }
713- continue
714- }
715-
716- for _ , source := range branches {
717- syncer .logger = config .LoggerForInfo (config.Info {
718- Metadata : api.Metadata {
719- Org : source .org ,
720- Repo : source .repo ,
721- Branch : source .branch ,
722- },
723- })
724-
725- destination := location {org : o .targetOrg , repo : dstRepo , branch : source .branch }
726-
727- if err := syncer .mirror (gitDir , source , destination , srcHeads , dstHeads , destUrl ); err != nil {
728- errs = append (errs , fmt .Errorf ("%s->%s: %w" , source .String (), destination .String (), err ))
729- }
730- }
740+ errs = append (errs , syncer .syncRepo (key .org , key .repo , o .targetOrg , dstRepo , branches )... )
731741 }
732742
733743 if len (errs ) > 0 {
0 commit comments