package cache import ( "fmt" "sync" "github.com/pterm/pterm" "gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/remotes" "gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/remotes/load" "gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/remotes/remote" "golang.org/x/exp/slices" ) func (c *Cache) LoadRemotes(gitRemotes ...string) { wg := &sync.WaitGroup{} writer := pterm.DefaultMultiPrinter for _, r := range *c.remotes { // Don't bother if it's dead or the user has provided // one or more remotes via --remote flag(s) if !remote.IsAlive(r) { c.log.Error("Skipping load of remote, not alive", c.log.Args( "remote", r.String())) continue } else if len(gitRemotes) > 0 && !slices.Contains(gitRemotes, r.GetInfo().Host) { c.log.Debug("Skipping remote not in --remote list", c.log.Args( "remote", r.String(), "remotes", gitRemotes)) continue } c.log.Info("Loading projects for remote", c.log.Args( "host", r.GetInfo().Host, "name", r.GetInfo().Name, )) opts := &remote.RemoteQueryOpts{ Ctx: r.GetInfo().Context(), OwnerOnly: c.config.Cache.Load.OwnerOnly, } pi, err := remotes.StreamRemote(r, opts) if err != nil { c.log.Error("Skipping remote", c.log.Args("error", err)) continue } // Prepare progressbar pBar, _ := pterm.DefaultProgressbar. WithShowPercentage(true). WithTotal(pi.NumProjects). WithWriter(writer.NewWriter()). WithMaxWidth(100). Start(r.GetInfo().Name) wg.Add(1) go c.ReceiveRemoteStream(r, wg, pBar, pi) } fmt.Println("") writer.Start() wg.Wait() writer.Stop() fmt.Println("") } func (c *Cache) ReceiveRemoteStream(remote remote.Remote, wg *sync.WaitGroup, pBar *pterm.ProgressbarPrinter, progressInfo *load.ProgressInfo) { defer wg.Done() for { select { case p := <-progressInfo.ProgressChan: pBar.Add(p.Projects) case p := <-progressInfo.ProjectsChan: c.AddProjects(p...) case e := <-progressInfo.ErrorChan: c.log.Error("Fetch projects error", c.log.Args("error", e, "remote", remote.GetInfo().Name)) case <-remote.GetInfo().Context().Done(): c.log.Warn("LoadProjects cancelled", c.log.Args("reason", remote.GetInfo().Context().Err())) return case <-progressInfo.DoneChan: return } } }