123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- package main
- import (
- "context"
- "fmt"
- "runtime"
- "sync"
- mapset "github.com/deckarep/golang-set/v2"
- "github.com/leonelquinteros/gotext"
- "github.com/Jguer/yay/v12/pkg/multierror"
- "github.com/Jguer/yay/v12/pkg/settings/exe"
- "github.com/Jguer/yay/v12/pkg/text"
- )
- type ErrDownloadSource struct {
- inner error
- pkgName string
- errOut string
- }
- func (e ErrDownloadSource) Error() string {
- return fmt.Sprintln(gotext.Get("error downloading sources: %s", text.Cyan(e.pkgName)),
- "\n\t context:", e.inner.Error(), "\n\t", e.errOut)
- }
- func (e *ErrDownloadSource) Unwrap() error {
- return e.inner
- }
- func downloadPKGBUILDSource(ctx context.Context,
- cmdBuilder exe.ICmdBuilder, pkgBuildDir string, installIncompatible bool,
- ) error {
- args := []string{"--verifysource", "-Ccf"}
- if installIncompatible {
- args = append(args, "--ignorearch")
- }
- err := cmdBuilder.Show(
- cmdBuilder.BuildMakepkgCmd(ctx, pkgBuildDir, args...))
- if err != nil {
- return ErrDownloadSource{inner: err, pkgName: pkgBuildDir}
- }
- return nil
- }
- func downloadPKGBUILDSourceWorker(ctx context.Context, wg *sync.WaitGroup,
- dirChannel <-chan string, valOut chan<- string, errOut chan<- error,
- cmdBuilder exe.ICmdBuilder, incompatible bool,
- ) {
- for pkgBuildDir := range dirChannel {
- err := downloadPKGBUILDSource(ctx, cmdBuilder, pkgBuildDir, incompatible)
- if err != nil {
- errOut <- ErrDownloadSource{inner: err, pkgName: pkgBuildDir, errOut: ""}
- } else {
- valOut <- pkgBuildDir
- }
- }
- wg.Done()
- }
- func downloadPKGBUILDSourceFanout(ctx context.Context, cmdBuilder exe.ICmdBuilder, pkgBuildDirs map[string]string,
- incompatible bool, maxConcurrentDownloads int,
- ) error {
- if len(pkgBuildDirs) == 0 {
- return nil // no work to do
- }
- if len(pkgBuildDirs) == 1 {
- for _, pkgBuildDir := range pkgBuildDirs {
- return downloadPKGBUILDSource(ctx, cmdBuilder, pkgBuildDir, incompatible)
- }
- }
- var (
- numOfWorkers = runtime.NumCPU()
- wg = &sync.WaitGroup{}
- c = make(chan string)
- fanInChanValues = make(chan string)
- fanInChanErrors = make(chan error)
- )
- if maxConcurrentDownloads != 0 {
- numOfWorkers = maxConcurrentDownloads
- }
- dedupSet := mapset.NewThreadUnsafeSet[string]()
- go func() {
- for _, pkgbuildDir := range pkgBuildDirs {
- if !dedupSet.Contains(pkgbuildDir) {
- c <- pkgbuildDir
- dedupSet.Add(pkgbuildDir)
- }
- }
- close(c)
- }()
- // Launch Workers
- wg.Add(numOfWorkers)
- for s := 0; s < numOfWorkers; s++ {
- go downloadPKGBUILDSourceWorker(ctx, wg, c,
- fanInChanValues, fanInChanErrors, cmdBuilder, incompatible)
- }
- go func() {
- wg.Wait()
- close(fanInChanValues)
- close(fanInChanErrors)
- }()
- returnErr := multierror.MultiError{}
- receiver:
- for {
- select {
- case _, ok := <-fanInChanValues:
- if !ok {
- break receiver
- }
- case err, ok := <-fanInChanErrors:
- if !ok {
- break receiver
- }
- returnErr.Add(err)
- }
- }
- return returnErr.Return()
- }
|