config.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. "os/exec"
  7. "strings"
  8. alpm "github.com/Jguer/go-alpm"
  9. pacmanconf "github.com/Morganamilo/go-pacmanconf"
  10. "github.com/leonelquinteros/gotext"
  11. "github.com/Jguer/yay/v10/pkg/settings"
  12. "github.com/Jguer/yay/v10/pkg/text"
  13. )
  14. // Verbosity settings for search
  15. const (
  16. numberMenu = iota
  17. detailed
  18. minimal
  19. )
  20. var yayVersion = "10.0.0"
  21. var localePath = "/usr/share/locale"
  22. // savedInfo holds the current vcs info
  23. var savedInfo vcsInfo
  24. // YayConf holds the current config values for yay.
  25. var config *settings.Configuration
  26. // AlpmConf holds the current config values for pacman.
  27. var pacmanConf *pacmanconf.Config
  28. // AlpmHandle is the alpm handle used by yay.
  29. var alpmHandle *alpm.Handle
  30. var hideMenus = false
  31. func defaultSettings() *settings.Configuration {
  32. newConfig := &settings.Configuration{
  33. AURURL: "https://aur.archlinux.org",
  34. BuildDir: "$HOME/.cache/yay",
  35. ABSDir: "$HOME/.cache/yay/abs",
  36. CleanAfter: false,
  37. Editor: "",
  38. EditorFlags: "",
  39. Devel: false,
  40. MakepkgBin: "makepkg",
  41. MakepkgConf: "",
  42. NoConfirm: false,
  43. PacmanBin: "pacman",
  44. PGPFetch: true,
  45. PacmanConf: "/etc/pacman.conf",
  46. GpgFlags: "",
  47. MFlags: "",
  48. GitFlags: "",
  49. SortMode: settings.BottomUp,
  50. CompletionInterval: 7,
  51. SortBy: "votes",
  52. SearchBy: "name-desc",
  53. SudoLoop: false,
  54. GitBin: "git",
  55. GpgBin: "gpg",
  56. SudoBin: "sudo",
  57. SudoFlags: "",
  58. TimeUpdate: false,
  59. RequestSplitN: 150,
  60. ReDownload: "no",
  61. ReBuild: "no",
  62. BatchInstall: false,
  63. AnswerClean: "",
  64. AnswerDiff: "",
  65. AnswerEdit: "",
  66. AnswerUpgrade: "",
  67. RemoveMake: "ask",
  68. Provides: true,
  69. UpgradeMenu: true,
  70. CleanMenu: true,
  71. DiffMenu: true,
  72. EditMenu: false,
  73. UseAsk: false,
  74. CombinedUpgrade: false,
  75. }
  76. if os.Getenv("XDG_CACHE_HOME") != "" {
  77. newConfig.BuildDir = "$XDG_CACHE_HOME/yay"
  78. }
  79. return newConfig
  80. }
  81. // Editor returns the preferred system editor.
  82. func editor() (editor string, args []string) {
  83. switch {
  84. case config.Editor != "":
  85. editor, err := exec.LookPath(config.Editor)
  86. if err != nil {
  87. fmt.Fprintln(os.Stderr, err)
  88. } else {
  89. return editor, strings.Fields(config.EditorFlags)
  90. }
  91. fallthrough
  92. case os.Getenv("EDITOR") != "":
  93. if editorArgs := strings.Fields(os.Getenv("EDITOR")); len(editorArgs) != 0 {
  94. editor, err := exec.LookPath(editorArgs[0])
  95. if err != nil {
  96. fmt.Fprintln(os.Stderr, err)
  97. } else {
  98. return editor, editorArgs[1:]
  99. }
  100. }
  101. fallthrough
  102. case os.Getenv("VISUAL") != "":
  103. if editorArgs := strings.Fields(os.Getenv("VISUAL")); len(editorArgs) != 0 {
  104. editor, err := exec.LookPath(editorArgs[0])
  105. if err != nil {
  106. fmt.Fprintln(os.Stderr, err)
  107. } else {
  108. return editor, editorArgs[1:]
  109. }
  110. }
  111. fallthrough
  112. default:
  113. fmt.Fprintln(os.Stderr)
  114. text.Errorln(gotext.Get("%s is not set", bold(cyan("$EDITOR"))))
  115. text.Warnln(gotext.Get("Add %s or %s to your environment variables", bold(cyan("$EDITOR")), bold(cyan("$VISUAL"))))
  116. for {
  117. text.Infoln(gotext.Get("Edit PKGBUILD with?"))
  118. editorInput, err := getInput("")
  119. if err != nil {
  120. fmt.Fprintln(os.Stderr, err)
  121. continue
  122. }
  123. editorArgs := strings.Fields(editorInput)
  124. if len(editorArgs) == 0 {
  125. continue
  126. }
  127. editor, err := exec.LookPath(editorArgs[0])
  128. if err != nil {
  129. fmt.Fprintln(os.Stderr, err)
  130. continue
  131. }
  132. return editor, editorArgs[1:]
  133. }
  134. }
  135. }
  136. // ContinueTask prompts if user wants to continue task.
  137. // If NoConfirm is set the action will continue without user input.
  138. func continueTask(s string, cont bool) bool {
  139. if config.NoConfirm {
  140. return cont
  141. }
  142. var response string
  143. var postFix string
  144. yes := gotext.Get("yes")
  145. no := gotext.Get("no")
  146. y := string([]rune(yes)[0])
  147. n := string([]rune(no)[0])
  148. if cont {
  149. postFix = fmt.Sprintf(" [%s/%s] ", strings.ToUpper(y), n)
  150. } else {
  151. postFix = fmt.Sprintf(" [%s/%s] ", y, strings.ToUpper(n))
  152. }
  153. text.Info(bold(s), bold(postFix))
  154. if _, err := fmt.Scanln(&response); err != nil {
  155. return cont
  156. }
  157. response = strings.ToLower(response)
  158. return response == yes || response == y
  159. }
  160. func getInput(defaultValue string) (string, error) {
  161. text.Info()
  162. if defaultValue != "" || config.NoConfirm {
  163. fmt.Println(defaultValue)
  164. return defaultValue, nil
  165. }
  166. reader := bufio.NewReader(os.Stdin)
  167. buf, overflow, err := reader.ReadLine()
  168. if err != nil {
  169. return "", err
  170. }
  171. if overflow {
  172. return "", fmt.Errorf(gotext.Get("input too long"))
  173. }
  174. return string(buf), nil
  175. }
  176. func toUsage(usages []string) alpm.Usage {
  177. if len(usages) == 0 {
  178. return alpm.UsageAll
  179. }
  180. var ret alpm.Usage
  181. for _, usage := range usages {
  182. switch usage {
  183. case "Sync":
  184. ret |= alpm.UsageSync
  185. case "Search":
  186. ret |= alpm.UsageSearch
  187. case "Install":
  188. ret |= alpm.UsageInstall
  189. case "Upgrade":
  190. ret |= alpm.UsageUpgrade
  191. case "All":
  192. ret |= alpm.UsageAll
  193. }
  194. }
  195. return ret
  196. }
  197. func configureAlpm() error {
  198. // TODO: set SigLevel
  199. // sigLevel := alpm.SigPackage | alpm.SigPackageOptional | alpm.SigDatabase | alpm.SigDatabaseOptional
  200. // localFileSigLevel := alpm.SigUseDefault
  201. // remoteFileSigLevel := alpm.SigUseDefault
  202. for _, repo := range pacmanConf.Repos {
  203. // TODO: set SigLevel
  204. db, err := alpmHandle.RegisterSyncDB(repo.Name, 0)
  205. if err != nil {
  206. return err
  207. }
  208. db.SetServers(repo.Servers)
  209. db.SetUsage(toUsage(repo.Usage))
  210. }
  211. if err := alpmHandle.SetCacheDirs(pacmanConf.CacheDir); err != nil {
  212. return err
  213. }
  214. // add hook directories 1-by-1 to avoid overwriting the system directory
  215. for _, dir := range pacmanConf.HookDir {
  216. if err := alpmHandle.AddHookDir(dir); err != nil {
  217. return err
  218. }
  219. }
  220. if err := alpmHandle.SetGPGDir(pacmanConf.GPGDir); err != nil {
  221. return err
  222. }
  223. if err := alpmHandle.SetLogFile(pacmanConf.LogFile); err != nil {
  224. return err
  225. }
  226. if err := alpmHandle.SetIgnorePkgs(pacmanConf.IgnorePkg); err != nil {
  227. return err
  228. }
  229. if err := alpmHandle.SetIgnoreGroups(pacmanConf.IgnoreGroup); err != nil {
  230. return err
  231. }
  232. if err := alpmHandle.SetArch(pacmanConf.Architecture); err != nil {
  233. return err
  234. }
  235. if err := alpmHandle.SetNoUpgrades(pacmanConf.NoUpgrade); err != nil {
  236. return err
  237. }
  238. if err := alpmHandle.SetNoExtracts(pacmanConf.NoExtract); err != nil {
  239. return err
  240. }
  241. /*if err := alpmHandle.SetDefaultSigLevel(sigLevel); err != nil {
  242. return err
  243. }
  244. if err := alpmHandle.SetLocalFileSigLevel(localFileSigLevel); err != nil {
  245. return err
  246. }
  247. if err := alpmHandle.SetRemoteFileSigLevel(remoteFileSigLevel); err != nil {
  248. return err
  249. }*/
  250. if err := alpmHandle.SetUseSyslog(pacmanConf.UseSyslog); err != nil {
  251. return err
  252. }
  253. return alpmHandle.SetCheckSpace(pacmanConf.CheckSpace)
  254. }