summaryrefslogtreecommitdiff
path: root/run.go
blob: e016a8e9d5a5b748f74f6d1ce0924ccf85fc7af1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
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
}