Skip to content

Commit a442b65

Browse files
committed
common: add interface for executing external programs
Add 'CommandExecutor' interfaced type for executing arbitrary commands ('git', 'launchctl', etc.). Signed-off-by: Victoria Dye <[email protected]>
1 parent e829e19 commit a442b65

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

internal/common/command.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package common
2+
3+
import (
4+
"fmt"
5+
"os/exec"
6+
)
7+
8+
type CommandExecutor interface {
9+
Run(command string, args ...string) (int, error)
10+
}
11+
12+
type commandExecutor struct{}
13+
14+
func NewCommandExecutor() *commandExecutor {
15+
return &commandExecutor{}
16+
}
17+
18+
func (c *commandExecutor) Run(command string, args ...string) (int, error) {
19+
exe, err := exec.LookPath(command)
20+
if err != nil {
21+
return -1, fmt.Errorf("failed to find '%s' on the path: %w", command, err)
22+
}
23+
24+
cmd := exec.Command(exe, args...)
25+
26+
err = cmd.Start()
27+
if err != nil {
28+
return -1, fmt.Errorf("command failed to start: %w", err)
29+
}
30+
31+
err = cmd.Wait()
32+
_, isExitError := err.(*exec.ExitError)
33+
34+
// If the command succeeded, or ran to completion but returned a nonzero
35+
// exit code, return non-erroneous result
36+
if err == nil || isExitError {
37+
return cmd.ProcessState.ExitCode(), nil
38+
} else {
39+
return -1, err
40+
}
41+
}

0 commit comments

Comments
 (0)