yay.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. "strconv"
  7. "strings"
  8. "github.com/jguer/yay/aur"
  9. "github.com/jguer/yay/config"
  10. pac "github.com/jguer/yay/pacman"
  11. )
  12. func usage() {
  13. fmt.Println(`usage: yay <operation> [...]
  14. operations:
  15. yay {-h --help}
  16. yay {-V --version}
  17. yay {-D --database} <options> <package(s)>
  18. yay {-F --files} [options] [package(s)]
  19. yay {-Q --query} [options] [package(s)]
  20. yay {-R --remove} [options] <package(s)>
  21. yay {-S --sync} [options] [package(s)]
  22. yay {-T --deptest} [options] [package(s)]
  23. yay {-U --upgrade} [options] <file(s)>
  24. New operations:
  25. yay -Qstats displays system information
  26. yay -Cd remove unneeded dependencies
  27. yay -G [package(s)] get pkgbuild from ABS or AUR
  28. New options:
  29. --topdown shows repository's packages first and then aur's
  30. --bottomup shows aur's packages first and then repository's
  31. --noconfirm skip user input on package install
  32. `)
  33. }
  34. var version = "2.116"
  35. func parser() (op string, options []string, packages []string, changedConfig bool, err error) {
  36. if len(os.Args) < 2 {
  37. err = fmt.Errorf("no operation specified")
  38. return
  39. }
  40. changedConfig = false
  41. op = "yogurt"
  42. for _, arg := range os.Args[1:] {
  43. if arg[0] == '-' && arg[1] != '-' {
  44. switch arg {
  45. default:
  46. op = arg
  47. }
  48. continue
  49. }
  50. if arg[0] == '-' && arg[1] == '-' {
  51. switch arg {
  52. case "--bottomup":
  53. config.YayConf.SortMode = config.BottomUp
  54. changedConfig = true
  55. case "--topdown":
  56. config.YayConf.SortMode = config.TopDown
  57. changedConfig = true
  58. case "--complete":
  59. config.YayConf.Shell = "sh"
  60. complete()
  61. os.Exit(0)
  62. case "--fcomplete":
  63. config.YayConf.Shell = "fish"
  64. complete()
  65. os.Exit(0)
  66. case "--help":
  67. usage()
  68. os.Exit(0)
  69. case "--noconfirm":
  70. config.YayConf.NoConfirm = true
  71. fallthrough
  72. default:
  73. options = append(options, arg)
  74. }
  75. continue
  76. }
  77. packages = append(packages, arg)
  78. }
  79. return
  80. }
  81. func main() {
  82. op, options, pkgs, changedConfig, err := parser()
  83. if err != nil {
  84. fmt.Println(err)
  85. os.Exit(1)
  86. }
  87. switch op {
  88. case "-Cd":
  89. err = cleanDependencies(pkgs)
  90. case "-G":
  91. for _, pkg := range pkgs {
  92. err = getPkgbuild(pkg)
  93. if err != nil {
  94. fmt.Println(pkg+":", err)
  95. }
  96. }
  97. case "-Qstats":
  98. err = localStatistics(version)
  99. case "-Ss", "-Ssq", "-Sqs":
  100. if op == "-Ss" {
  101. config.YayConf.SearchMode = config.Detailed
  102. } else {
  103. config.YayConf.SearchMode = config.Minimal
  104. }
  105. if pkgs != nil {
  106. err = syncSearch(pkgs)
  107. }
  108. case "-S":
  109. err = install(pkgs, options)
  110. case "-Syu", "-Suy":
  111. err = upgrade(options)
  112. case "-Si":
  113. err = syncInfo(pkgs, options)
  114. case "yogurt":
  115. config.YayConf.SearchMode = config.NumberMenu
  116. if pkgs != nil {
  117. err = numberMenu(pkgs, options)
  118. }
  119. default:
  120. err = config.PassToPacman(op, pkgs, options)
  121. }
  122. if changedConfig {
  123. config.SaveConfig()
  124. }
  125. config.AlpmHandle.Release()
  126. if err != nil {
  127. fmt.Println(err)
  128. os.Exit(1)
  129. }
  130. }
  131. // NumberMenu presents a CLI for selecting packages to install.
  132. func numberMenu(pkgS []string, flags []string) (err error) {
  133. var num int
  134. aq, err := aur.NarrowSearch(pkgS, true)
  135. if err != nil {
  136. fmt.Println("Error during AUR search:", err)
  137. }
  138. numaq := len(aq)
  139. pq, numpq, err := pac.Search(pkgS)
  140. if err != nil {
  141. return
  142. }
  143. if numpq == 0 && numaq == 0 {
  144. return fmt.Errorf("no packages match search")
  145. }
  146. if config.YayConf.SortMode == config.BottomUp {
  147. printAURSearch(aq, numpq)
  148. pq.PrintSearch()
  149. } else {
  150. pq.PrintSearch()
  151. printAURSearch(aq, numpq)
  152. }
  153. fmt.Printf("\x1b[32m%s\x1b[0m\nNumbers:", "Type numbers to install. Separate each number with a space.")
  154. reader := bufio.NewReader(os.Stdin)
  155. numberBuf, overflow, err := reader.ReadLine()
  156. if err != nil || overflow {
  157. fmt.Println(err)
  158. return
  159. }
  160. numberString := string(numberBuf)
  161. var aurInstall []string
  162. var repoInstall []string
  163. result := strings.Fields(numberString)
  164. for _, numS := range result {
  165. num, err = strconv.Atoi(numS)
  166. if err != nil {
  167. continue
  168. }
  169. // Install package
  170. if num > numaq+numpq-1 || num < 0 {
  171. continue
  172. } else if num > numpq-1 {
  173. if config.YayConf.SortMode == config.BottomUp {
  174. aurInstall = append(aurInstall, aq[numaq+numpq-num-1].Name)
  175. } else {
  176. aurInstall = append(aurInstall, aq[num-numpq].Name)
  177. }
  178. } else {
  179. if config.YayConf.SortMode == config.BottomUp {
  180. repoInstall = append(repoInstall, pq[numpq-num-1].Name)
  181. } else {
  182. repoInstall = append(repoInstall, pq[num].Name)
  183. }
  184. }
  185. }
  186. if len(repoInstall) != 0 {
  187. config.PassToPacman("-S", repoInstall, flags)
  188. }
  189. if len(aurInstall) != 0 {
  190. aur.Install(aurInstall, flags)
  191. }
  192. return nil
  193. }