unified.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. package download
  2. import (
  3. "net/http"
  4. "os"
  5. "path/filepath"
  6. "sync"
  7. "github.com/leonelquinteros/gotext"
  8. "github.com/Jguer/go-alpm/v2"
  9. "github.com/Jguer/yay/v10/pkg/db"
  10. "github.com/Jguer/yay/v10/pkg/multierror"
  11. "github.com/Jguer/yay/v10/pkg/settings"
  12. "github.com/Jguer/yay/v10/pkg/settings/exe"
  13. "github.com/Jguer/yay/v10/pkg/text"
  14. )
  15. func downloadGitRepo(cmdRunner exe.Runner,
  16. cmdBuilder exe.GitCmdBuilder, pkgURL, pkgName, dest string, force bool, gitArgs ...string) error {
  17. gitArgs = append(gitArgs, pkgURL, pkgName)
  18. cloneArgs := make([]string, 0, len(gitArgs)+4)
  19. cloneArgs = append(cloneArgs, "clone", "--no-progress")
  20. cloneArgs = append(cloneArgs, gitArgs...)
  21. finalDir := filepath.Join(dest, pkgName)
  22. if _, err := os.Stat(filepath.Join(finalDir, ".git")); os.IsNotExist(err) {
  23. if _, errD := os.Stat(finalDir); force && errD == nil {
  24. if errR := os.RemoveAll(finalDir); errR != nil {
  25. return ErrGetPKGBUILDRepo{inner: errR, pkgName: pkgName}
  26. }
  27. }
  28. cmd := cmdBuilder.BuildGitCmd(dest, cloneArgs...)
  29. _, stderr, errCapture := cmdRunner.Capture(cmd, 0)
  30. if errCapture != nil {
  31. return ErrGetPKGBUILDRepo{inner: errCapture, pkgName: pkgName, errOut: stderr}
  32. }
  33. } else if err != nil {
  34. return ErrGetPKGBUILDRepo{
  35. inner: err,
  36. pkgName: pkgName,
  37. errOut: gotext.Get("error reading %s", filepath.Join(dest, pkgName, ".git")),
  38. }
  39. } else {
  40. cmd := cmdBuilder.BuildGitCmd(filepath.Join(dest, pkgName), "pull", "--ff-only")
  41. _, stderr, errCmd := cmdRunner.Capture(cmd, 0)
  42. if errCmd != nil {
  43. return ErrGetPKGBUILDRepo{inner: errCmd, pkgName: pkgName, errOut: stderr}
  44. }
  45. }
  46. return nil
  47. }
  48. func getURLName(pkg db.IPackage) string {
  49. name := pkg.Base()
  50. if name == "" {
  51. name = pkg.Name()
  52. }
  53. return name
  54. }
  55. func GetPkgbuilds(dbExecutor db.Executor, httpClient *http.Client, targets []string, mode settings.TargetMode) (map[string][]byte, error) {
  56. pkgbuilds := make(map[string][]byte, len(targets))
  57. var (
  58. mux sync.Mutex
  59. errs multierror.MultiError
  60. wg sync.WaitGroup
  61. )
  62. sem := make(chan uint8, MaxConcurrentFetch)
  63. for _, target := range targets {
  64. aur := true
  65. dbName, name := text.SplitDBFromName(target)
  66. if dbName != "aur" && (mode == settings.ModeAny || mode == settings.ModeRepo) {
  67. if pkg := dbExecutor.SyncPackage(name); pkg != nil {
  68. aur = false
  69. name = getURLName(pkg)
  70. dbName = pkg.DB().Name()
  71. }
  72. }
  73. if aur && mode == settings.ModeRepo {
  74. // Mode does not allow AUR packages
  75. continue
  76. }
  77. sem <- 1
  78. wg.Add(1)
  79. go func(target, dbName, pkgName string, aur bool) {
  80. var (
  81. err error
  82. pkgbuild []byte
  83. )
  84. if aur {
  85. pkgbuild, err = GetAURPkgbuild(httpClient, pkgName)
  86. } else {
  87. pkgbuild, err = GetABSPkgbuild(httpClient, dbName, pkgName)
  88. }
  89. if err == nil {
  90. mux.Lock()
  91. pkgbuilds[target] = pkgbuild
  92. mux.Unlock()
  93. } else {
  94. errs.Add(err)
  95. }
  96. <-sem
  97. wg.Done()
  98. }(target, dbName, name, aur)
  99. }
  100. wg.Wait()
  101. return pkgbuilds, errs.Return()
  102. }
  103. func PKGBUILDRepos(dbExecutor db.Executor,
  104. cmdRunner exe.Runner,
  105. cmdBuilder exe.GitCmdBuilder,
  106. targets []string, mode settings.TargetMode, aurURL, dest string, force bool) (map[string]bool, error) {
  107. cloned := make(map[string]bool, len(targets))
  108. var (
  109. mux sync.Mutex
  110. errs multierror.MultiError
  111. wg sync.WaitGroup
  112. )
  113. sem := make(chan uint8, MaxConcurrentFetch)
  114. for _, target := range targets {
  115. aur := true
  116. dbName, name := text.SplitDBFromName(target)
  117. if dbName != "aur" && (mode == settings.ModeAny || mode == settings.ModeRepo) {
  118. var pkg alpm.IPackage
  119. if dbName != "" {
  120. pkg = dbExecutor.SatisfierFromDB(name, dbName)
  121. if pkg == nil {
  122. // if the user precised a db but the package is not in the db
  123. // then it is missing
  124. continue
  125. }
  126. } else {
  127. pkg = dbExecutor.SyncPackage(name)
  128. }
  129. if pkg != nil {
  130. aur = false
  131. name = getURLName(pkg)
  132. dbName = pkg.DB().Name()
  133. }
  134. }
  135. if aur && mode == settings.ModeRepo {
  136. // Mode does not allow AUR packages
  137. continue
  138. }
  139. sem <- 1
  140. wg.Add(1)
  141. go func(target, dbName, pkgName string, aur bool) {
  142. var (
  143. err error
  144. )
  145. if aur {
  146. err = AURPkgbuildRepo(cmdRunner, cmdBuilder, aurURL, pkgName, dest, force)
  147. } else {
  148. err = ABSPkgbuildRepo(cmdRunner, cmdBuilder, dbName, pkgName, dest, force)
  149. }
  150. success := err == nil
  151. if success {
  152. mux.Lock()
  153. cloned[target] = success
  154. mux.Unlock()
  155. }
  156. if !success {
  157. errs.Add(err)
  158. }
  159. if aur {
  160. text.OperationInfoln(
  161. gotext.Get("(%d/%d) Downloaded PKGBUILD: %s",
  162. len(cloned), len(targets), text.Cyan(pkgName)))
  163. } else {
  164. text.OperationInfoln(
  165. gotext.Get("(%d/%d) Downloaded PKGBUILD from ABS: %s",
  166. len(cloned), len(targets), text.Cyan(pkgName)))
  167. }
  168. <-sem
  169. wg.Done()
  170. }(target, dbName, name, aur)
  171. }
  172. wg.Wait()
  173. return cloned, errs.Return()
  174. }