config.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. package config
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io"
  6. "net/http"
  7. "os"
  8. "os/exec"
  9. "strings"
  10. alpm "github.com/jguer/go-alpm"
  11. )
  12. // Verbosity settings for search
  13. const (
  14. NumberMenu = iota
  15. Detailed
  16. Minimal
  17. )
  18. // Describes Sorting method for numberdisplay
  19. const (
  20. BottomUp = iota
  21. TopDown
  22. )
  23. // Configuration stores yay's config.
  24. type Configuration struct {
  25. BuildDir string `json:"buildDir"`
  26. Editor string `json:"editor"`
  27. MakepkgBin string `json:"makepkgbin"`
  28. Shell string `json:"-"`
  29. NoConfirm bool `json:"noconfirm"`
  30. Devel bool `json:"devel"`
  31. PacmanBin string `json:"pacmanbin"`
  32. PacmanConf string `json:"pacmanconf"`
  33. SearchMode int `json:"-"`
  34. SortMode int `json:"sortmode"`
  35. TarBin string `json:"tarbin"`
  36. TimeUpdate bool `json:"timeupdate"`
  37. }
  38. // YayConf holds the current config values for yay.
  39. var YayConf Configuration
  40. // AlpmConf holds the current config values for pacman.
  41. var AlpmConf alpm.PacmanConfig
  42. // AlpmHandle is the alpm handle used by yay.
  43. var AlpmHandle *alpm.Handle
  44. func init() {
  45. var err error
  46. configfile := os.Getenv("HOME") + "/.config/yay/config.json"
  47. if _, err = os.Stat(configfile); os.IsNotExist(err) {
  48. _ = os.MkdirAll(os.Getenv("HOME")+"/.config/yay", 0755)
  49. defaultSettings(&YayConf)
  50. } else {
  51. file, err := os.Open(configfile)
  52. if err != nil {
  53. fmt.Println("Error reading config:", err)
  54. } else {
  55. decoder := json.NewDecoder(file)
  56. err = decoder.Decode(&YayConf)
  57. if err != nil {
  58. fmt.Println("Loading default Settings\nError reading config:", err)
  59. defaultSettings(&YayConf)
  60. }
  61. }
  62. }
  63. AlpmConf, err = readAlpmConfig(YayConf.PacmanConf)
  64. if err != nil {
  65. fmt.Println("Unable to read Pacman conf", err)
  66. os.Exit(1)
  67. }
  68. AlpmHandle, err = AlpmConf.CreateHandle()
  69. if err != nil {
  70. fmt.Println("Unable to CreateHandle", err)
  71. os.Exit(1)
  72. }
  73. }
  74. func readAlpmConfig(pacmanconf string) (conf alpm.PacmanConfig, err error) {
  75. file, err := os.Open(pacmanconf)
  76. if err != nil {
  77. return
  78. }
  79. conf, err = alpm.ParseConfig(file)
  80. if err != nil {
  81. return
  82. }
  83. return
  84. }
  85. // SaveConfig writes yay config to file.
  86. func SaveConfig() error {
  87. YayConf.NoConfirm = false
  88. configfile := os.Getenv("HOME") + "/.config/yay/config.json"
  89. marshalledinfo, _ := json.Marshal(YayConf)
  90. in, err := os.OpenFile(configfile, os.O_RDWR|os.O_CREATE, 0755)
  91. if err != nil {
  92. return err
  93. }
  94. defer in.Close()
  95. _, err = in.Write(marshalledinfo)
  96. if err != nil {
  97. return err
  98. }
  99. err = in.Sync()
  100. return err
  101. }
  102. func defaultSettings(config *Configuration) {
  103. config.BuildDir = "/tmp/yaytmp/"
  104. config.Editor = ""
  105. config.Devel = false
  106. config.MakepkgBin = "/usr/bin/makepkg"
  107. config.NoConfirm = false
  108. config.PacmanBin = "/usr/bin/pacman"
  109. config.PacmanConf = "/etc/pacman.conf"
  110. config.SortMode = BottomUp
  111. config.TarBin = "/usr/bin/bsdtar"
  112. config.TimeUpdate = false
  113. }
  114. // Editor returns the preferred system editor.
  115. func Editor() string {
  116. switch {
  117. case YayConf.Editor != "":
  118. editor, err := exec.LookPath(YayConf.Editor)
  119. if err != nil {
  120. fmt.Println(err)
  121. } else {
  122. return editor
  123. }
  124. fallthrough
  125. case os.Getenv("EDITOR") != "":
  126. editor, err := exec.LookPath(os.Getenv("EDITOR"))
  127. if err != nil {
  128. fmt.Println(err)
  129. } else {
  130. return editor
  131. }
  132. fallthrough
  133. case os.Getenv("VISUAL") != "":
  134. editor, err := exec.LookPath(os.Getenv("VISUAL"))
  135. if err != nil {
  136. fmt.Println(err)
  137. } else {
  138. return editor
  139. }
  140. fallthrough
  141. default:
  142. fmt.Printf("\x1b[1;31;40mWarning: \x1B[1;33;40m$EDITOR\x1b[0;37;40m is not set.\x1b[0m\nPlease add $EDITOR or to your environment variables.\n")
  143. editorLoop:
  144. fmt.Printf("\x1b[32m%s\x1b[0m ", "Edit PKGBUILD with:")
  145. var editorInput string
  146. _, err := fmt.Scanln(&editorInput)
  147. if err != nil {
  148. fmt.Println(err)
  149. goto editorLoop
  150. }
  151. editor, err := exec.LookPath(editorInput)
  152. if err != nil {
  153. fmt.Println(err)
  154. goto editorLoop
  155. }
  156. return editor
  157. }
  158. }
  159. // ContinueTask prompts if user wants to continue task.
  160. //If NoConfirm is set the action will continue without user input.
  161. func ContinueTask(s string, def string) (cont bool) {
  162. if YayConf.NoConfirm {
  163. return true
  164. }
  165. var postFix string
  166. if def == "nN" {
  167. postFix = "[Y/n] "
  168. } else {
  169. postFix = "[y/N] "
  170. }
  171. var response string
  172. fmt.Printf("\x1b[1;32m==> %s\x1b[1;37m %s\x1b[0m", s, postFix)
  173. n, err := fmt.Scanln(&response)
  174. if err != nil || n == 0 {
  175. return true
  176. }
  177. if response == string(def[0]) || response == string(def[1]) {
  178. return false
  179. }
  180. return true
  181. }
  182. func downloadFile(path string, url string) (err error) {
  183. // Create the file
  184. out, err := os.Create(path)
  185. if err != nil {
  186. return err
  187. }
  188. defer out.Close()
  189. // Get the data
  190. resp, err := http.Get(url)
  191. if err != nil {
  192. return err
  193. }
  194. defer resp.Body.Close()
  195. // Writer the body to file
  196. _, err = io.Copy(out, resp.Body)
  197. return err
  198. }
  199. // DownloadAndUnpack downloads url tgz and extracts to path.
  200. func DownloadAndUnpack(url string, path string, trim bool) (err error) {
  201. err = os.MkdirAll(path, 0755)
  202. if err != nil {
  203. return
  204. }
  205. tokens := strings.Split(url, "/")
  206. fileName := tokens[len(tokens)-1]
  207. tarLocation := path + fileName
  208. defer os.Remove(tarLocation)
  209. err = downloadFile(tarLocation, url)
  210. if err != nil {
  211. return
  212. }
  213. if trim {
  214. err = exec.Command("/bin/sh", "-c",
  215. YayConf.TarBin+" --strip-components 2 --include='*/"+fileName[:len(fileName)-7]+"/trunk/' -xf "+tarLocation+" -C "+path).Run()
  216. os.Rename(path+"trunk", path+fileName[:len(fileName)-7]) // kurwa
  217. } else {
  218. err = exec.Command(YayConf.TarBin, "-xf", tarLocation, "-C", path).Run()
  219. }
  220. if err != nil {
  221. return
  222. }
  223. return
  224. }
  225. // PassToPacman outsorces execution to pacman binary without modifications.
  226. func PassToPacman(op string, pkgs []string, flags []string) error {
  227. var cmd *exec.Cmd
  228. var args []string
  229. args = append(args, op)
  230. if len(pkgs) != 0 {
  231. args = append(args, pkgs...)
  232. }
  233. if len(flags) != 0 {
  234. args = append(args, flags...)
  235. }
  236. if strings.Contains(op, "-Q") || op == "Si" {
  237. cmd = exec.Command(YayConf.PacmanBin, args...)
  238. } else {
  239. args = append([]string{YayConf.PacmanBin}, args...)
  240. cmd = exec.Command("sudo", args...)
  241. }
  242. cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
  243. err := cmd.Run()
  244. return err
  245. }