forked from go-godo/godo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cmd.go
131 lines (113 loc) · 2.41 KB
/
cmd.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
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
package godo
import (
"bytes"
"fmt"
"os"
"os/exec"
"strings"
"github.com/mgutz/ansi"
"gopkg.in/godo.v2/util"
)
// Proccesses are the processes spawned by Start()
var Processes = make(map[string]*os.Process)
const (
// CaptureStdout is a bitmask to capture STDOUT
CaptureStdout = 1
// CaptureStderr is a bitmask to capture STDERR
CaptureStderr = 2
// CaptureBoth captures STDOUT and STDERR
CaptureBoth = CaptureStdout + CaptureStderr
)
type command struct {
// original command string
commandstr string
// parsed executable
executable string
// parsed argv
argv []string
// parsed env
env []string
// working directory
wd string
// bitmask to capture output
capture int
// the output buf
buf bytes.Buffer
}
func (gcmd *command) toExecCmd() (cmd *exec.Cmd, err error) {
cmd = exec.Command(gcmd.executable, gcmd.argv...)
if gcmd.wd != "" {
cmd.Dir = gcmd.wd
}
cmd.Env = effectiveEnv(gcmd.env)
cmd.Stdin = os.Stdin
if gcmd.capture&CaptureStderr > 0 {
cmd.Stderr = newFileWrapper(os.Stderr, &gcmd.buf, ansi.Red)
} else {
cmd.Stderr = os.Stderr
}
if gcmd.capture&CaptureStdout > 0 {
cmd.Stdout = newFileWrapper(os.Stdout, &gcmd.buf, "")
} else {
cmd.Stdout = os.Stdout
}
if verbose {
if Env != "" {
util.Debug("#", "Env: %s\n", Env)
}
util.Debug("#", "%s\n", gcmd.commandstr)
}
return cmd, nil
}
func (gcmd *command) run() (string, error) {
var err error
cmd, err := gcmd.toExecCmd()
if err != nil {
return "", err
}
err = cmd.Run()
if gcmd.capture > 0 {
return gcmd.buf.String(), err
}
return "", err
}
func (gcmd *command) runAsync() error {
cmd, err := gcmd.toExecCmd()
if err != nil {
return err
}
id := gcmd.commandstr
// kills previously spawned process (if exists)
killSpawned(id)
runnerWaitGroup.Add(1)
waitExit = true
go func() {
err = cmd.Start()
if err != nil {
fmt.Println(err.Error())
return
}
Processes[id] = cmd.Process
if verbose {
util.Debug("#", "Processes[%q] added\n", id)
}
cmd.Wait()
runnerWaitGroup.Done()
}()
return nil
}
func killSpawned(command string) {
process := Processes[command]
if process == nil {
return
}
err := process.Kill()
delete(Processes, command)
if err != nil && !strings.Contains(err.Error(), "process already finished") {
util.Error("Start", "Could not kill existing process %+v\n%s\n", process, err.Error())
return
}
if verbose {
util.Debug("#", "Processes[%q] killed\n", command)
}
}