unified.go 5.1 KB

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