yay/pkg/settings/runtime.go

154 lines
3.3 KiB
Go
Raw Normal View History

2020-07-05 00:45:23 +00:00
package settings
import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/Morganamilo/go-pacmanconf"
"github.com/leonelquinteros/gotext"
"github.com/pkg/errors"
"github.com/Jguer/yay/v10/pkg/text"
)
2020-07-05 00:45:23 +00:00
type TargetMode int
// configFileName holds the name of the config file.
const configFileName string = "config.json"
// vcsFileName holds the name of the vcs file.
const vcsFileName string = "vcs.json"
const completionFileName string = "completion.cache"
2020-07-05 00:45:23 +00:00
const (
ModeAny TargetMode = iota
ModeAUR
ModeRepo
)
type Runner interface {
Capture(cmd *exec.Cmd, timeout int64) (stdout string, stderr string, err error)
Show(cmd *exec.Cmd) error
}
type OSRunner struct {
}
func (r *OSRunner) Show(cmd *exec.Cmd) error {
cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
err := cmd.Run()
if err != nil {
return fmt.Errorf("")
}
return nil
}
func (r *OSRunner) Capture(cmd *exec.Cmd, timeout int64) (stdout, stderr string, err error) {
var outbuf, errbuf bytes.Buffer
var timer *time.Timer
timedOut := false
cmd.Stdout = &outbuf
cmd.Stderr = &errbuf
err = cmd.Start()
if err != nil {
return "", "", err
}
if timeout != 0 {
timer = time.AfterFunc(time.Duration(timeout)*time.Second, func() {
err = cmd.Process.Kill()
if err != nil {
text.Errorln(err)
}
timedOut = true
})
}
err = cmd.Wait()
if timeout != 0 {
timer.Stop()
}
if err != nil {
return "", "", err
}
stdout = strings.TrimSpace(outbuf.String())
stderr = strings.TrimSpace(errbuf.String())
if timedOut {
err = fmt.Errorf("command timed out")
}
return stdout, stderr, err
}
2020-07-05 00:45:23 +00:00
type Runtime struct {
Mode TargetMode
SaveConfig bool
CompletionPath string
ConfigPath string
VCSPath string
PacmanConf *pacmanconf.Config
CmdRunner Runner
}
func MakeRuntime() (*Runtime, error) {
cacheHome := ""
configHome := ""
runtime := &Runtime{
Mode: ModeAny,
SaveConfig: false,
CompletionPath: "",
CmdRunner: &OSRunner{},
}
if configHome = os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
configHome = filepath.Join(configHome, "yay")
} else if configHome = os.Getenv("HOME"); configHome != "" {
configHome = filepath.Join(configHome, ".config", "yay")
} else {
return nil, errors.New(gotext.Get("%s and %s unset", "XDG_CONFIG_HOME", "HOME"))
}
if err := initDir(configHome); err != nil {
return nil, err
}
if cacheHome = os.Getenv("XDG_CACHE_HOME"); cacheHome != "" {
cacheHome = filepath.Join(cacheHome, "yay")
} else if cacheHome = os.Getenv("HOME"); cacheHome != "" {
cacheHome = filepath.Join(cacheHome, ".cache", "yay")
} else {
return nil, errors.New(gotext.Get("%s and %s unset", "XDG_CACHE_HOME", "HOME"))
}
if err := initDir(cacheHome); err != nil {
return runtime, err
}
runtime.ConfigPath = filepath.Join(configHome, configFileName)
runtime.VCSPath = filepath.Join(cacheHome, vcsFileName)
runtime.CompletionPath = filepath.Join(cacheHome, completionFileName)
return runtime, nil
}
func initDir(dir string) error {
if _, err := os.Stat(dir); os.IsNotExist(err) {
if err = os.MkdirAll(dir, 0o755); err != nil {
return errors.New(gotext.Get("failed to create config directory '%s': %s", dir, err))
}
} else if err != nil {
return err
}
return nil
2020-07-05 00:45:23 +00:00
}