252 lines
5.6 KiB
Go
252 lines
5.6 KiB
Go
package shell
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"go.wit.com/log"
|
|
)
|
|
|
|
var msecDelay int = 20 // check every 20 milliseconds
|
|
|
|
// TODO: look at https://github.com/go-cmd/cmd/issues/20
|
|
// use go-cmd instead here?
|
|
// exiterr.Sys().(syscall.WaitStatus)
|
|
|
|
// run command and return it's output
|
|
/*
|
|
func RunCapture(cmdline string) string {
|
|
test := New()
|
|
test.Exec(cmdline)
|
|
return Chomp(test.Buffer)
|
|
}
|
|
|
|
func RunWait(args []string) *OldShell {
|
|
test := New()
|
|
cmdline := strings.Join(args, " ")
|
|
test.Exec(cmdline)
|
|
return test
|
|
}
|
|
*/
|
|
|
|
// var newfile *shell.File
|
|
func RunString(args string) bool {
|
|
// return false
|
|
parts := strings.Split(args, " ")
|
|
return Run(parts)
|
|
}
|
|
|
|
func Run(args []string) bool {
|
|
dir, err := os.Getwd()
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
r := RunPath(dir, args)
|
|
if r.Ok {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
var ErrorArgvEmpty error = errors.New("command was empty")
|
|
|
|
type RunResult struct {
|
|
Ok bool
|
|
Argv []string
|
|
Path string
|
|
Output []byte
|
|
Err error
|
|
Outerr error
|
|
}
|
|
|
|
// run, but set the working path
|
|
func RunPath(path string, args []string) *RunResult {
|
|
r := new(RunResult)
|
|
r.Path = path
|
|
r.Argv = args
|
|
if len(args) == 0 {
|
|
r.Ok = true
|
|
r.Err = ErrorArgvEmpty
|
|
return r
|
|
}
|
|
if args[0] == "" {
|
|
r.Ok = false
|
|
r.Err = ErrorArgvEmpty
|
|
return r
|
|
}
|
|
thing := args[0]
|
|
parts := args[1:]
|
|
cmd := exec.Command(thing, parts...)
|
|
cmd.Dir = path
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
|
|
log.Info("path =", path, "cmd =", strings.Join(args, " "))
|
|
if err := cmd.Run(); err != nil {
|
|
// Handle error if the command execution fails
|
|
// log.Info("RunPath() failed")
|
|
// log.Info("cmd.Enviorn =", cmd.Environ())
|
|
out, outerr := cmd.Output()
|
|
// log.Info("cmd.output =", out)
|
|
// log.Info("cmd.output err=", outerr)
|
|
// log.Info("path =", path)
|
|
// log.Info("args =", args)
|
|
// log.Info("err =", err.Error())
|
|
r.Ok = false
|
|
r.Err = err
|
|
r.Output = out
|
|
r.Outerr = outerr
|
|
return r
|
|
}
|
|
out, outerr := cmd.Output()
|
|
r.Output = out
|
|
r.Outerr = outerr
|
|
r.Ok = true
|
|
return r
|
|
}
|
|
|
|
// send the path and the command
|
|
func RunCmd(workingpath string, parts []string) (error, bool, string) {
|
|
if len(parts) == 0 {
|
|
log.Warn("command line was empty")
|
|
return errors.New("empty"), false, ""
|
|
}
|
|
if parts[0] == "" {
|
|
log.Warn("command line was empty")
|
|
return errors.New("empty"), false, ""
|
|
}
|
|
thing := parts[0]
|
|
parts = parts[1:]
|
|
log.Log(INFO, "working path =", workingpath, "thing =", thing, "cmdline =", parts)
|
|
|
|
// Create the command
|
|
cmd := exec.Command(thing, parts...)
|
|
|
|
// Set the working directory
|
|
cmd.Dir = workingpath
|
|
|
|
// Execute the command
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
if thing == "git" {
|
|
log.Log(INFO, "git ERROR. maybe okay", workingpath, "thing =", thing, "cmdline =", parts)
|
|
log.Log(INFO, "git ERROR. maybe okay err =", err)
|
|
if err.Error() == "exit status 1" {
|
|
log.Log(INFO, "git ERROR. normal exit status 1")
|
|
if parts[0] == "diff-index" {
|
|
log.Log(INFO, "git normal diff-index when repo dirty")
|
|
return nil, false, "git diff-index exit status 1"
|
|
}
|
|
}
|
|
}
|
|
|
|
log.Warn("ERROR working path =", workingpath, "thing =", thing, "cmdline =", parts)
|
|
log.Warn("ERROR working path =", workingpath, "thing =", thing, "cmdline =", parts)
|
|
log.Warn("ERROR working path =", workingpath, "thing =", thing, "cmdline =", parts)
|
|
log.Error(err)
|
|
log.Warn("output was", string(output))
|
|
log.Warn("cmd exited with error", err)
|
|
// panic("fucknuts")
|
|
|
|
// The command failed (non-zero exit status)
|
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
|
// Assert that it is an exec.ExitError and get the exit code
|
|
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
|
log.Warn("Exit Status: %d\n", status.ExitStatus())
|
|
}
|
|
} else {
|
|
log.Warn("cmd.Run() failed with %s\n", err)
|
|
}
|
|
return err, false, string(output)
|
|
}
|
|
|
|
tmp := string(output)
|
|
tmp = strings.TrimSpace(tmp)
|
|
|
|
// Print the output
|
|
return nil, true, tmp
|
|
}
|
|
|
|
// send the path and the command
|
|
func RunCmdRun(workingpath string, parts []string) error {
|
|
if len(parts) == 0 {
|
|
log.Warn("command line was empty")
|
|
return errors.New("empty")
|
|
}
|
|
if parts[0] == "" {
|
|
log.Warn("command line was empty")
|
|
return errors.New("empty")
|
|
}
|
|
thing := parts[0]
|
|
parts = parts[1:]
|
|
log.Log(INFO, "working path =", workingpath, "thing =", thing, "cmdline =", parts)
|
|
|
|
// Create the command
|
|
cmd := exec.Command(thing, parts...)
|
|
|
|
// Set the working directory
|
|
cmd.Dir = workingpath
|
|
|
|
// Execute the command
|
|
err := cmd.Run()
|
|
if err != nil {
|
|
log.Warn("ERROR working path =", workingpath, "thing =", thing, "cmdline =", parts)
|
|
log.Error(err)
|
|
log.Warn("cmd exited with error", err)
|
|
// panic("fucknuts")
|
|
|
|
// The command failed (non-zero exit status)
|
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
|
// Assert that it is an exec.ExitError and get the exit code
|
|
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
|
|
log.Warn("Exit Status: %d\n", status.ExitStatus())
|
|
}
|
|
} else {
|
|
log.Warn("cmd.Run() failed with %s\n", err)
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *RunResult) Stdout() string {
|
|
return string(r.Output)
|
|
}
|
|
|
|
// run, but set the working path
|
|
func Output(path string, args []string) *RunResult {
|
|
r := new(RunResult)
|
|
r.Path = path
|
|
r.Argv = args
|
|
if len(args) == 0 {
|
|
r.Ok = true
|
|
r.Err = ErrorArgvEmpty
|
|
return r
|
|
}
|
|
if args[0] == "" {
|
|
r.Ok = false
|
|
r.Err = ErrorArgvEmpty
|
|
return r
|
|
}
|
|
thing := args[0]
|
|
parts := args[1:]
|
|
cmd := exec.Command(thing, parts...)
|
|
cmd.Dir = path
|
|
output, err := cmd.CombinedOutput()
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
r.Ok = false
|
|
r.Err = err
|
|
r.Output = output
|
|
return r
|
|
}
|
|
r.Output = output
|
|
r.Err = err
|
|
r.Ok = true
|
|
return r
|
|
}
|