-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaction.go
95 lines (80 loc) · 1.69 KB
/
action.go
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
package main
import (
"fmt"
"io"
"os"
"os/exec"
"github.com/google/shlex"
)
type Action struct {
statement string
chdir string
stdin io.Reader
stdout io.Writer
logger Logger
expandEnv bool
}
func NewAction(statement string) *Action {
return &Action{
statement: statement,
stdin: os.Stdin,
stdout: os.Stdout,
expandEnv: true,
}
}
func (a *Action) WithStdin(stdin io.Reader) *Action {
if stdin != nil {
a.stdin = stdin
}
return a
}
func (a *Action) WithStdout(stdout io.Writer) *Action {
a.stdout = stdout
return a
}
func (a *Action) WithEnvExpansion(expandEnv bool) *Action {
a.expandEnv = expandEnv
return a
}
func (a *Action) WithWorkingDirectory(chdir string) *Action {
a.chdir = chdir
return a
}
func (a *Action) Execute() error {
// first, setup the environment
if a.expandEnv {
a.statement = os.ExpandEnv(a.statement)
}
cmd, err := createCommand(a.statement)
if err != nil {
return err
}
// setup the process' working directory
cmd.Dir = a.chdir
// setup the process' IO streams
cmd.Stderr = os.Stderr
cmd.Stdin = a.stdin
cmd.Stdout = a.stdout
// spawn the command
if err := cmd.Start(); err != nil {
return fmt.Errorf("failed to start action: %v", err)
}
// wait for the command to finish
if err := cmd.Wait(); err != nil {
return fmt.Errorf("action failed: %v", err)
}
return nil
}
func createCommand(statement string) (*exec.Cmd, error) {
var name string
var args []string
fields, err := shlex.Split(statement)
if err != nil {
return nil, fmt.Errorf("failed to parse action: %s\nerror: %v", statement, err)
}
if len(fields) > 0 {
name = fields[0]
args = fields[1:]
}
return exec.Command(name, args...), nil
}