u.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // Package upgrade package is responsible for returning lists of outdated packages.
  2. package upgrade
  3. import (
  4. "fmt"
  5. alpm "github.com/jguer/go-alpm"
  6. "github.com/jguer/yay/config"
  7. rpc "github.com/mikkeloscar/aur"
  8. pkgb "github.com/mikkeloscar/gopkgbuild"
  9. )
  10. // Upgrade type describes a system upgrade.
  11. type Upgrade struct {
  12. Name string
  13. Repository string
  14. LocalVersion string
  15. RemoteVersion string
  16. }
  17. // FilterPackages filters packages based on source and type.
  18. func FilterPackages() (local []alpm.Package, remote []alpm.Package,
  19. localNames []string, remoteNames []string, err error) {
  20. localDb, err := config.AlpmHandle.LocalDb()
  21. if err != nil {
  22. return
  23. }
  24. dbList, err := config.AlpmHandle.SyncDbs()
  25. if err != nil {
  26. return
  27. }
  28. f := func(k alpm.Package) error {
  29. found := false
  30. // For each DB search for our secret package.
  31. _ = dbList.ForEach(func(d alpm.Db) error {
  32. if found {
  33. return nil
  34. }
  35. _, err := d.PkgByName(k.Name())
  36. if err == nil {
  37. found = true
  38. local = append(local, k)
  39. localNames = append(localNames, k.Name())
  40. }
  41. return nil
  42. })
  43. if !found {
  44. remote = append(remote, k)
  45. remoteNames = append(remoteNames, k.Name())
  46. }
  47. return nil
  48. }
  49. err = localDb.PkgCache().ForEach(f)
  50. return
  51. }
  52. func Print(start int, u []Upgrade) {
  53. for _, i := range u {
  54. old, err := pkgb.NewCompleteVersion(i.LocalVersion)
  55. if err != nil {
  56. fmt.Println(i.Name, err)
  57. }
  58. new, err := pkgb.NewCompleteVersion(i.RemoteVersion)
  59. if err != nil {
  60. fmt.Println(i.Name, err)
  61. }
  62. f := func(name string) (color int) {
  63. var hash = 5381
  64. for i := 0; i < len(name); i++ {
  65. hash = int(name[i]) + ((hash << 5) + (hash))
  66. }
  67. return (hash)%6 + 31
  68. }
  69. // fmt.Printf("\x1b[33m%-2d\x1b[0m ", len(u)+start-k-1)
  70. fmt.Printf("\x1b[1;%dm%s\x1b[0m/\x1b[1;39m%-20s\t\t\x1b[0m", f(i.Repository), i.Repository, i.Name)
  71. if old.Version != new.Version {
  72. fmt.Printf("\x1b[31m%10s\x1b[0m-%d -> \x1b[1;32m%s\x1b[0m-%d\x1b[0m",
  73. old.Version, old.Pkgrel,
  74. new.Version, new.Pkgrel)
  75. } else {
  76. fmt.Printf("\x1b[0m%10s-\x1b[31m%d\x1b[0m -> %s-\x1b[32m%d\x1b[0m",
  77. old.Version, old.Pkgrel,
  78. new.Version, new.Pkgrel)
  79. }
  80. print("\n")
  81. }
  82. }
  83. // List returns lists of packages to upgrade from each source.
  84. func List() (aurUp []Upgrade, repoUp []Upgrade, err error) {
  85. err = config.PassToPacman("-Sy", nil, nil)
  86. if err != nil {
  87. return
  88. }
  89. local, remote, _, remoteNames, err := FilterPackages()
  90. if err != nil {
  91. return
  92. }
  93. repoC := make(chan []Upgrade)
  94. aurC := make(chan []Upgrade)
  95. errC := make(chan error)
  96. go func() {
  97. repoUpList, err := repo(local)
  98. errC <- err
  99. repoC <- repoUpList
  100. }()
  101. go func() {
  102. aurUpList, err := aur(remote, remoteNames)
  103. errC <- err
  104. aurC <- aurUpList
  105. }()
  106. var i = 0
  107. loop:
  108. for {
  109. select {
  110. case repoUp = <-repoC:
  111. i++
  112. case aurUp = <-aurC:
  113. i++
  114. case err := <-errC:
  115. if err != nil {
  116. fmt.Println(err)
  117. }
  118. default:
  119. if i == 2 {
  120. close(repoC)
  121. close(aurC)
  122. close(errC)
  123. break loop
  124. }
  125. }
  126. }
  127. return
  128. }
  129. // aur gathers foreign packages and checks if they have new versions.
  130. // Output: Upgrade type package list.
  131. func aur(remote []alpm.Package, remoteNames []string) (toUpgrade []Upgrade, err error) {
  132. var j int
  133. var routines int
  134. var routineDone int
  135. packageC := make(chan Upgrade)
  136. done := make(chan bool)
  137. for i := len(remote); i != 0; i = j {
  138. //Split requests so AUR RPC doesn't get mad at us.
  139. j = i - config.YayConf.RequestSplitN
  140. if j < 0 {
  141. j = 0
  142. }
  143. routines++
  144. go func(local []alpm.Package, remote []string) {
  145. qtemp, err := rpc.Info(remoteNames)
  146. if err != nil {
  147. fmt.Println(err)
  148. done <- true
  149. return
  150. }
  151. // For each item in query: Search equivalent in foreign.
  152. // We assume they're ordered and are returned ordered
  153. // and will only be missing if they don't exist in AUR.
  154. max := len(qtemp) - 1
  155. var missing, x int
  156. for i := range local {
  157. x = i - missing
  158. if x > max {
  159. break
  160. } else if qtemp[x].Name == local[i].Name() {
  161. if (config.YayConf.TimeUpdate && (int64(qtemp[x].LastModified) > local[i].BuildDate().Unix())) ||
  162. (alpm.VerCmp(local[i].Version(), qtemp[x].Version) < 0) {
  163. packageC <- Upgrade{qtemp[x].Name, "aur", local[i].Version(), qtemp[x].Version}
  164. }
  165. continue
  166. } else {
  167. missing++
  168. }
  169. }
  170. done <- true
  171. }(remote[j:i], remoteNames[j:i])
  172. }
  173. for {
  174. select {
  175. case pkg := <-packageC:
  176. fmt.Println("Package Received")
  177. toUpgrade = append(toUpgrade, pkg)
  178. case <-done:
  179. routineDone++
  180. if routineDone == routines {
  181. err = nil
  182. return
  183. }
  184. }
  185. }
  186. }
  187. // repo gathers local packages and checks if they have new versions.
  188. // Output: Upgrade type package list.
  189. func repo(local []alpm.Package) ([]Upgrade, error) {
  190. dbList, err := config.AlpmHandle.SyncDbs()
  191. if err != nil {
  192. return nil, err
  193. }
  194. slice := []Upgrade{}
  195. for _, pkg := range local {
  196. newPkg := pkg.NewVersion(dbList)
  197. if newPkg != nil {
  198. slice = append(slice, Upgrade{pkg.Name(), newPkg.DB().Name(), pkg.Version(), newPkg.Version()})
  199. }
  200. }
  201. return slice, nil
  202. }