actions.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. package yay
  2. import (
  3. "bufio"
  4. "fmt"
  5. "math"
  6. "os"
  7. "os/exec"
  8. "strconv"
  9. "strings"
  10. "github.com/jguer/go-alpm"
  11. "github.com/jguer/yay/aur"
  12. )
  13. // BuildDir is the root for package building
  14. const BuildDir string = "/tmp/yaytmp/"
  15. // SearchMode is search without numbers.
  16. const SearchMode int = -1
  17. // NumberMenu presents a CLI for selecting packages to install.
  18. func NumberMenu(pkgName string, flags []string) (err error) {
  19. var num int
  20. var numberString string
  21. var args []string
  22. a, err := aur.Search(pkgName, true)
  23. r, err := SearchPackages(pkgName, conf)
  24. if err != nil {
  25. return
  26. }
  27. if len(r.Results) == 0 && a.Resultcount == 0 {
  28. return fmt.Errorf("no Packages match search")
  29. }
  30. r.PrintSearch(0)
  31. a.PrintSearch(len(r.Results))
  32. args = append(args, "pacman", "-S")
  33. fmt.Printf("\x1b[32m%s\x1b[0m\nNumbers:", "Type numbers to install. Separate each number with a space.")
  34. reader := bufio.NewReader(os.Stdin)
  35. numberString, err = reader.ReadString('\n')
  36. if err != nil {
  37. fmt.Println(err)
  38. return
  39. }
  40. var aurInstall []aur.Result
  41. result := strings.Fields(numberString)
  42. for _, numS := range result {
  43. num, err = strconv.Atoi(numS)
  44. if err != nil {
  45. fmt.Println(err)
  46. continue
  47. }
  48. // Install package
  49. if num > len(r.Results)-1 {
  50. aurInstall = append(aurInstall, a.Results[num-len(r.Results)])
  51. } else {
  52. args = append(args, r.Results[num].Name)
  53. }
  54. }
  55. args = append(args, flags...)
  56. if len(args) > 2 {
  57. var cmd *exec.Cmd
  58. cmd = exec.Command("sudo", args...)
  59. cmd.Stdout = os.Stdout
  60. cmd.Stdin = os.Stdin
  61. cmd.Stderr = os.Stderr
  62. err = cmd.Run()
  63. }
  64. for _, aurpkg := range aurInstall {
  65. err = aurpkg.Install(BuildDir, conf, flags)
  66. if err != nil {
  67. // Do not abandon program, we might still be able to install the rest
  68. fmt.Println(err)
  69. }
  70. }
  71. return
  72. }
  73. // Install handles package installs
  74. func Install(pkgs []string, flags []string) error {
  75. h, err := conf.CreateHandle()
  76. defer h.Release()
  77. if err != nil {
  78. return err
  79. }
  80. dbList, err := h.SyncDbs()
  81. if err != nil {
  82. return err
  83. }
  84. var foreign []string
  85. var args []string
  86. repocnt := 0
  87. args = append(args, "pacman")
  88. args = append(args, "-S")
  89. for _, pkg := range pkgs {
  90. found := false
  91. for _, db := range dbList.Slice() {
  92. _, err = db.PkgByName(pkg)
  93. if err == nil {
  94. found = true
  95. args = append(args, pkg)
  96. repocnt++
  97. break
  98. }
  99. }
  100. if !found {
  101. foreign = append(foreign, pkg)
  102. }
  103. }
  104. args = append(args, flags...)
  105. if repocnt != 0 {
  106. var cmd *exec.Cmd
  107. cmd = exec.Command("sudo", args...)
  108. cmd.Stdout = os.Stdout
  109. cmd.Stdin = os.Stdin
  110. cmd.Stderr = os.Stderr
  111. err = cmd.Run()
  112. }
  113. for _, aurpkg := range foreign {
  114. err = aur.Install(aurpkg, BuildDir, conf, flags)
  115. }
  116. return nil
  117. }
  118. // Upgrade handles updating the cache and installing updates.
  119. func Upgrade(flags []string) error {
  120. errp := UpdatePackages(flags)
  121. erra := aur.UpdatePackages(BuildDir, conf, flags)
  122. if errp != nil {
  123. return errp
  124. }
  125. return erra
  126. }
  127. // Search presents a query to the local repos and to the AUR.
  128. func Search(pkg string) (err error) {
  129. a, err := aur.Search(pkg, true)
  130. if err != nil {
  131. return err
  132. }
  133. SearchRepos(pkg, conf, SearchMode)
  134. a.PrintSearch(SearchMode)
  135. return nil
  136. }
  137. // LocalStatistics returns installed packages statistics.
  138. func LocalStatistics() error {
  139. var tS int64 // TotalSize
  140. var nPkg int
  141. var ePkg int
  142. var pkgs [10]alpm.Package
  143. h, err := conf.CreateHandle()
  144. defer h.Release()
  145. if err != nil {
  146. return err
  147. }
  148. localDb, err := h.LocalDb()
  149. if err != nil {
  150. return err
  151. }
  152. var k int
  153. for e, pkg := range localDb.PkgCache().Slice() {
  154. tS += pkg.ISize()
  155. k = -1
  156. nPkg++
  157. if pkg.Reason() == 0 {
  158. ePkg++
  159. }
  160. if e < 10 {
  161. pkgs[e] = pkg
  162. continue
  163. }
  164. for i, pkw := range pkgs {
  165. if k == -1 {
  166. if pkw.ISize() < pkg.ISize() {
  167. k = i
  168. }
  169. } else {
  170. if pkw.ISize() < pkgs[k].ISize() && pkw.ISize() < pkg.ISize() {
  171. k = i
  172. }
  173. }
  174. }
  175. if k != -1 {
  176. pkgs[k] = pkg
  177. }
  178. }
  179. fmt.Println("\x1B[1;34m===========================================\x1B[0m")
  180. fmt.Printf("\x1B[1;32mTotal installed packages: \x1B[0;33m%d\x1B[0m\n", nPkg)
  181. fmt.Printf("\x1B[1;32mExplicitly installed packages: \x1B[0;33m%d\x1B[0m\n", ePkg)
  182. fmt.Printf("\x1B[1;32mTotal Size occupied by packages: \x1B[0;33m%s\x1B[0m\n", size(tS))
  183. fmt.Println("\x1B[1;34m===========================================\x1B[0m")
  184. fmt.Println("\x1B[1;32mTen biggest packages\x1B[0m")
  185. for _, pkg := range pkgs {
  186. fmt.Printf("%s: \x1B[0;33m%s\x1B[0m\n", pkg.Name(), size(pkg.ISize()))
  187. }
  188. fmt.Println("\x1B[1;34m===========================================\x1B[0m")
  189. return nil
  190. }
  191. // Function by pyk https://github.com/pyk/byten
  192. func index(s int64) float64 {
  193. x := math.Log(float64(s)) / math.Log(1024)
  194. return math.Floor(x)
  195. }
  196. // Function by pyk https://github.com/pyk/byten
  197. func countSize(s int64, i float64) float64 {
  198. return float64(s) / math.Pow(1024, math.Floor(i))
  199. }
  200. // Size return a formated string from file size
  201. // Function by pyk https://github.com/pyk/byten
  202. func size(s int64) string {
  203. symbols := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"}
  204. i := index(s)
  205. if s < 10 {
  206. return fmt.Sprintf("%dB", s)
  207. }
  208. size := countSize(s, i)
  209. format := "%.0f"
  210. if size < 10 {
  211. format = "%.1f"
  212. }
  213. return fmt.Sprintf(format+"%s", size, symbols[int(i)])
  214. }