// Package cli handles processing command-line arguments and doing
// the thing that has been requested.
package cli
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"regexp"
"strings"
"git.sr.ht/~hristoast/wem/actions"
"git.sr.ht/~hristoast/wem/cfg"
"git.sr.ht/~hristoast/wem/env"
arg "github.com/alexflint/go-arg"
)
// ProcessArgs is the main entrypoint for the command-line program.
func ProcessArgs() {
c, err := cfg.GetConfig()
if err != nil {
log.Fatal(err.Error())
}
var a args
p := arg.MustParse(&a)
c.ApplyArgs(a.CacheDir, a.GeWineDir, a.WineBuildDir, a.WineEnvDir, a.WineSrcDir)
err = c.EnsureDirs()
if err != nil {
log.Fatal(err.Error())
}
if a.QuietWem {
log.SetOutput(ioutil.Discard)
}
switch {
case a.Build != nil:
wineVer := a.Build.WineVer
err = actions.Build(wineVer, a.Build.Fetch, a.Build.Force, a.Build.Staging,
a.Build.Verbose, a.Build.Win32, a.Build.Jobs, c)
if err != nil {
log.Fatal(err)
}
case a.Cfg != nil:
envName := a.Cfg.EnvName
we, err := env.FromName(envName, !a.Cfg.NoRender)
if err != nil {
re := regexp.MustCompile(`<\.[a-zA-Z]+>`)
//TODO: does this even work?
badField := re.Find([]byte(err.Error()))
if badField != nil {
log.Fatalf("invalid field in \"%s\" config: %s", envName, badField)
} else {
log.Fatalf("The env \"%s\" doesn't exist, try running `wem init %s` instead!", envName, envName)
}
}
//TODO: Is there a better way than straight up reading the file twice?
// A copy to check for changes given via the CLI
we2, err := env.FromName(envName, !a.Cfg.NoRender)
if err != nil {
log.Fatal(err.Error())
}
a.applyArgs(we)
err = actions.Cfg(we, we2, a.Cfg.NoRender, a.Cfg.Save, a.Cfg.NoUnchanged, envName)
if err != nil {
log.Fatal(err.Error())
}
case a.Completion != nil:
if !a.Completion.Bash && !a.Completion.Fish {
log.Fatal("Please specify one or all of: --bash, --fish")
} else {
err = actions.Completion(a.Completion.Bash, a.Completion.Fish, a.Completion.Stdout, c)
if err != nil {
log.Fatal(err.Error())
}
}
case a.Help != nil:
var b bytes.Buffer
p.WriteHelp(&b)
fmt.Println(b.String())
case a.Init != nil:
envName := a.Init.EnvName
we := &env.WineEnv{
Info: &env.Info{Name: envName},
InstallOpts: &env.InstallOpts{},
RunOpts: &env.RunOpts{},
WineOpts: &env.WineOpts{},
SysOpts: &env.SysOpts{},
}
a.applyArgs(we)
name, err := env.Slugify(envName)
if err != nil {
log.Fatal(err.Error())
}
err = actions.Init(c, we, name)
if err != nil {
log.Fatal(err.Error())
}
case a.Install != nil:
run(a, c, a.Install.EnvName, true)
case a.List != nil:
err := actions.List(a.List.Dxvk, a.List.Env, a.List.Installed, a.List.GeWine,
a.List.Wine, a.List.Vkd3d, c.WineBuildDir, c.CacheDir, c.GeWineDir, c.WineEnvDir)
if err != nil {
log.Fatal(err.Error())
}
case a.Man != nil:
err := actions.Manpage(a.Man.Out)
if err != nil {
log.Fatalln(err.Error())
}
case a.GeWine != nil:
err := actions.GeWine(c.GeWineDir, a.GeWine.Version)
if err != nil {
log.Fatal(err)
}
case a.Run != nil:
run(a, c, a.Run.EnvName, false)
case a.Tutorial != nil:
actions.Tutorial()
case a.NoArgs():
// Show the usage text when nothing else valid is given.
var b bytes.Buffer
p.WriteUsage(&b)
fmt.Println(b.String())
fmt.Println("Run `wem help` for the full help text.")
fmt.Println()
}
}
func run(a args, c *cfg.WemConfig, envName string, installOnly bool) {
we, err := env.FromName(envName, true)
if err != nil {
if strings.HasSuffix((err.Error()), "no such file or directory") {
log.Fatalf("The env \"%s\" doesn't exist, try running `wem init %s` instead!", envName, envName)
} else if strings.Contains(err.Error(), " can't evaluate field ") {
log.Printf("ERROR: Unknown variable found in the \"%s\" config:", envName)
log.Fatal(err)
} else {
log.Fatal(err)
}
}
a.applyArgs(we)
err = we.Validate()
if err != nil {
log.Fatalln(err.Error())
}
if installOnly {
err = actions.Run(c, we, a.Install.DryRun, we.QuietRun,
false, true, false, false, "", nil)
} else {
err = actions.Run(c, we, a.Run.DryRun, we.QuietRun,
a.Run.SkipInstall, a.Run.SkipRun, a.Run.Winecfg,
a.Run.Winetricks, a.Run.Exec, a.Run.ExecArgs)
}
if err != nil {
log.Fatalln(err.Error())
}
}