7
7
"os/exec"
8
8
"sync"
9
9
10
+ "github.com/mattn/go-shellwords"
10
11
"golang.org/x/sync/errgroup"
11
12
"golang.org/x/sync/semaphore"
12
13
"golang.org/x/sys/execabs"
@@ -109,18 +110,36 @@ func (proc *concurrentProcess) wait() {
109
110
// newCommandRunner creates new external command runner for given executable. The executable path
110
111
// is resolved in this function.
111
112
func (proc * concurrentProcess ) newCommandRunner (exe string , combineOutput bool ) (* externalCommand , error ) {
112
- p , err := execabs .LookPath (exe )
113
+ var args []string
114
+ p , args , err := findExe (exe )
113
115
if err != nil {
114
116
return nil , err
115
117
}
116
118
cmd := & externalCommand {
117
119
proc : proc ,
118
120
exe : p ,
121
+ args : args ,
119
122
combineOutput : combineOutput ,
120
123
}
121
124
return cmd , nil
122
125
}
123
126
127
+ func findExe (exe string ) (string , []string , error ) {
128
+ p , err := execabs .LookPath (exe )
129
+ if err == nil {
130
+ return p , nil , nil
131
+ }
132
+ // See if the command string contains args. As it is best effort, we do not
133
+ // handle parse errors.
134
+ if exeArgs , _ := shellwords .Parse (exe ); len (exeArgs ) > 0 {
135
+ if p , err := execabs .LookPath (exeArgs [0 ]); err == nil {
136
+ return p , exeArgs [1 :], nil
137
+ }
138
+ }
139
+
140
+ return "" , nil , err
141
+ }
142
+
124
143
// externalCommand is struct to run specific command concurrently with concurrentProcess bounding
125
144
// number of processes at the same time. This type manages fatal errors while running the command
126
145
// by using errgroup.Group. The wait() method must be called at the end for checking if some fatal
@@ -129,13 +148,20 @@ type externalCommand struct {
129
148
proc * concurrentProcess
130
149
eg errgroup.Group
131
150
exe string
151
+ args []string
132
152
combineOutput bool
133
153
}
134
154
135
155
// run runs the command with given arguments and stdin. The callback function is called after the
136
156
// process runs. First argument is stdout and the second argument is an error while running the
137
157
// process.
138
158
func (cmd * externalCommand ) run (args []string , stdin string , callback func ([]byte , error ) error ) {
159
+ if len (cmd .args ) > 0 {
160
+ var allArgs []string
161
+ allArgs = append (allArgs , cmd .args ... )
162
+ allArgs = append (allArgs , args ... )
163
+ args = allArgs
164
+ }
139
165
exec := & cmdExecution {cmd .exe , args , stdin , cmd .combineOutput }
140
166
cmd .proc .run (& cmd .eg , exec , callback )
141
167
}
0 commit comments