config.go 7.2 KB

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