runtime.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package settings
  2. import (
  3. "bytes"
  4. "fmt"
  5. "os"
  6. "os/exec"
  7. "path/filepath"
  8. "strings"
  9. "time"
  10. "github.com/Morganamilo/go-pacmanconf"
  11. "github.com/leonelquinteros/gotext"
  12. "github.com/pkg/errors"
  13. "github.com/Jguer/yay/v10/pkg/text"
  14. )
  15. type TargetMode int
  16. // configFileName holds the name of the config file.
  17. const configFileName string = "config.json"
  18. // vcsFileName holds the name of the vcs file.
  19. const vcsFileName string = "vcs.json"
  20. const completionFileName string = "completion.cache"
  21. const (
  22. ModeAny TargetMode = iota
  23. ModeAUR
  24. ModeRepo
  25. )
  26. type Runner interface {
  27. Capture(cmd *exec.Cmd, timeout int64) (stdout string, stderr string, err error)
  28. Show(cmd *exec.Cmd) error
  29. }
  30. type OSRunner struct {
  31. }
  32. func (r *OSRunner) Show(cmd *exec.Cmd) error {
  33. cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
  34. err := cmd.Run()
  35. if err != nil {
  36. return fmt.Errorf("")
  37. }
  38. return nil
  39. }
  40. func (r *OSRunner) Capture(cmd *exec.Cmd, timeout int64) (stdout, stderr string, err error) {
  41. var outbuf, errbuf bytes.Buffer
  42. var timer *time.Timer
  43. timedOut := false
  44. cmd.Stdout = &outbuf
  45. cmd.Stderr = &errbuf
  46. err = cmd.Start()
  47. if err != nil {
  48. return "", "", err
  49. }
  50. if timeout != 0 {
  51. timer = time.AfterFunc(time.Duration(timeout)*time.Second, func() {
  52. err = cmd.Process.Kill()
  53. if err != nil {
  54. text.Errorln(err)
  55. }
  56. timedOut = true
  57. })
  58. }
  59. err = cmd.Wait()
  60. if timeout != 0 {
  61. timer.Stop()
  62. }
  63. if err != nil {
  64. return "", "", err
  65. }
  66. stdout = strings.TrimSpace(outbuf.String())
  67. stderr = strings.TrimSpace(errbuf.String())
  68. if timedOut {
  69. err = fmt.Errorf("command timed out")
  70. }
  71. return stdout, stderr, err
  72. }
  73. type Runtime struct {
  74. Mode TargetMode
  75. SaveConfig bool
  76. CompletionPath string
  77. ConfigPath string
  78. VCSPath string
  79. PacmanConf *pacmanconf.Config
  80. CmdRunner Runner
  81. }
  82. func MakeRuntime() (*Runtime, error) {
  83. cacheHome := ""
  84. configHome := ""
  85. runtime := &Runtime{
  86. Mode: ModeAny,
  87. SaveConfig: false,
  88. CompletionPath: "",
  89. CmdRunner: &OSRunner{},
  90. }
  91. if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
  92. configHome = filepath.Join(configHome, "yay")
  93. } else if configHome = os.Getenv("HOME"); configHome != "" {
  94. configHome = filepath.Join(configHome, ".config", "yay")
  95. } else {
  96. return nil, errors.New(gotext.Get("%s and %s unset", "XDG_CONFIG_HOME", "HOME"))
  97. }
  98. if err := initDir(configHome); err != nil {
  99. return nil, err
  100. }
  101. if cacheHome = os.Getenv("XDG_CACHE_HOME"); cacheHome != "" {
  102. cacheHome = filepath.Join(cacheHome, "yay")
  103. } else if cacheHome = os.Getenv("HOME"); cacheHome != "" {
  104. cacheHome = filepath.Join(cacheHome, ".cache", "yay")
  105. } else {
  106. return nil, errors.New(gotext.Get("%s and %s unset", "XDG_CACHE_HOME", "HOME"))
  107. }
  108. if err := initDir(cacheHome); err != nil {
  109. return runtime, err
  110. }
  111. runtime.ConfigPath = filepath.Join(configHome, configFileName)
  112. runtime.VCSPath = filepath.Join(cacheHome, vcsFileName)
  113. runtime.CompletionPath = filepath.Join(cacheHome, completionFileName)
  114. return runtime, nil
  115. }
  116. func initDir(dir string) error {
  117. if _, err := os.Stat(dir); os.IsNotExist(err) {
  118. if err = os.MkdirAll(dir, 0o755); err != nil {
  119. return errors.New(gotext.Get("failed to create config directory '%s': %s", dir, err))
  120. }
  121. } else if err != nil {
  122. return err
  123. }
  124. return nil
  125. }