@@ -17,10 +17,11 @@ import (
17
17
18
18
// Command contains the name, arguments and environment variables of a command.
19
19
type Command struct {
20
- name string
21
- args []string
22
- envs []string
23
- ctx context.Context
20
+ name string
21
+ args []string
22
+ envs []string
23
+ timeout time.Duration
24
+ ctx context.Context
24
25
}
25
26
26
27
// CommandOptions contains options for running a command.
@@ -69,17 +70,29 @@ func (c *Command) AddEnvs(envs ...string) *Command {
69
70
return c
70
71
}
71
72
72
- // WithContext sets the context for the command .
73
- func (c * Command ) WithContext (ctx context.Context ) * Command {
73
+ // WithContext returns a new Command with the given context .
74
+ func (c Command ) WithContext (ctx context.Context ) * Command {
74
75
c .ctx = ctx
75
- return c
76
+ return & c
77
+ }
78
+
79
+ // WithTimeout returns a new Command with given timeout.
80
+ func (c Command ) WithTimeout (timeout time.Duration ) * Command {
81
+ c .timeout = timeout
82
+ return & c
83
+ }
84
+
85
+ // SetTimeout sets the timeout for the command.
86
+ func (c * Command ) SetTimeout (timeout time.Duration ) {
87
+ c .timeout = timeout
76
88
}
77
89
78
90
// AddOptions adds options to the command.
79
91
// Note: only the last option will take effect if there are duplicated options.
80
92
func (c * Command ) AddOptions (opts ... CommandOptions ) * Command {
81
93
for _ , opt := range opts {
82
- c = c .WithContext (opt .Context )
94
+ c .timeout = opt .Timeout
95
+ c .ctx = opt .Context
83
96
c .AddArgs (opt .Args ... )
84
97
c .AddEnvs (opt .Envs ... )
85
98
}
@@ -93,7 +106,7 @@ func (c *Command) AddCommitter(committer *Signature) *Command {
93
106
}
94
107
95
108
// DefaultTimeout is the default timeout duration for all commands.
96
- const DefaultTimeout = time .Minute
109
+ const DefaultTimeout = time .Second
97
110
98
111
// A limitDualWriter writes to W but limits the amount of data written to just N
99
112
// bytes. On the other hand, it passes everything to w.
@@ -132,6 +145,8 @@ type RunInDirOptions struct {
132
145
// Stderr is the error output from the command.
133
146
Stderr io.Writer
134
147
// Timeout is the duration to wait before timing out.
148
+ //
149
+ // Deprecated: Use CommandOptions.Timeout or *Command.WithTimeout instead.
135
150
Timeout time.Duration
136
151
}
137
152
@@ -145,10 +160,15 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
145
160
if len (opts ) > 0 {
146
161
opt = opts [0 ]
147
162
}
148
- if opt .Timeout < 0 {
149
- opt .Timeout = - 1
150
- } else if opt .Timeout == 0 {
151
- opt .Timeout = DefaultTimeout
163
+
164
+ timeout := c .timeout
165
+ // TODO: remove this in newer version
166
+ if opt .Timeout > 0 {
167
+ timeout = opt .Timeout
168
+ }
169
+
170
+ if timeout == 0 {
171
+ timeout = DefaultTimeout
152
172
}
153
173
154
174
buf := new (bytes.Buffer )
@@ -164,9 +184,9 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
164
184
165
185
defer func () {
166
186
if len (dir ) == 0 {
167
- log ("[timeout: %v] %s\n %s" , opt . Timeout , c , buf .Bytes ())
187
+ log ("[timeout: %v] %s\n %s" , timeout , c , buf .Bytes ())
168
188
} else {
169
- log ("[timeout: %v] %s: %s\n %s" , opt . Timeout , dir , c , buf .Bytes ())
189
+ log ("[timeout: %v] %s: %s\n %s" , timeout , dir , c , buf .Bytes ())
170
190
}
171
191
}()
172
192
@@ -175,9 +195,9 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
175
195
ctx = c .ctx
176
196
}
177
197
178
- if opt . Timeout > 0 {
198
+ if timeout > 0 {
179
199
var cancel context.CancelFunc
180
- ctx , cancel = context .WithTimeout (ctx , opt . Timeout )
200
+ ctx , cancel = context .WithTimeout (ctx , timeout )
181
201
defer func () {
182
202
cancel ()
183
203
if err == context .DeadlineExceeded {
@@ -219,55 +239,72 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
219
239
220
240
}
221
241
242
+ // RunInDirPipeline executes the command in given directory and default timeout
243
+ // duration. It pipes stdout and stderr to supplied io.Writer.
244
+ func (c * Command ) RunInDirPipeline (stdout , stderr io.Writer , dir string ) error {
245
+ return c .RunInDirWithOptions (dir , RunInDirOptions {
246
+ Stdin : nil ,
247
+ Stdout : stdout ,
248
+ Stderr : stderr ,
249
+ })
250
+ }
251
+
222
252
// RunInDirPipelineWithTimeout executes the command in given directory and
223
253
// timeout duration. It pipes stdout and stderr to supplied io.Writer.
224
254
// DefaultTimeout will be used if the timeout duration is less than
225
255
// time.Nanosecond (i.e. less than or equal to 0). It returns an ErrExecTimeout
226
256
// if the execution was timed out.
257
+ //
258
+ // Deprecated: Use RunInDirPipeline and CommandOptions instead.
259
+ // TODO: remove this in the next major version
227
260
func (c * Command ) RunInDirPipelineWithTimeout (timeout time.Duration , stdout , stderr io.Writer , dir string ) (err error ) {
228
- return c .RunInDirWithOptions (dir , RunInDirOptions {
229
- Stdin : nil ,
230
- Stdout : stdout ,
231
- Stderr : stderr ,
232
- Timeout : timeout ,
233
- })
234
- }
235
-
236
- // RunInDirPipeline executes the command in given directory and default timeout
237
- // duration. It pipes stdout and stderr to supplied io.Writer.
238
- func (c * Command ) RunInDirPipeline (stdout , stderr io.Writer , dir string ) error {
239
- return c .RunInDirPipelineWithTimeout (DefaultTimeout , stdout , stderr , dir )
261
+ if timeout != 0 {
262
+ c = c .WithTimeout (timeout )
263
+ }
264
+ return c .RunInDirPipeline (stdout , stderr , dir )
240
265
}
241
266
242
267
// RunInDirWithTimeout executes the command in given directory and timeout
243
268
// duration. It returns stdout in []byte and error (combined with stderr).
269
+ //
270
+ // Deprecated: Use RunInDir and CommandOptions instead.
271
+ // TODO: remove this in the next major version
244
272
func (c * Command ) RunInDirWithTimeout (timeout time.Duration , dir string ) ([]byte , error ) {
245
- stdout := new (bytes.Buffer )
246
- stderr := new (bytes.Buffer )
247
- if err := c .RunInDirPipelineWithTimeout (timeout , stdout , stderr , dir ); err != nil {
248
- return nil , concatenateError (err , stderr .String ())
273
+ if timeout != 0 {
274
+ c = c .WithTimeout (timeout )
249
275
}
250
- return stdout . Bytes (), nil
276
+ return c . RunInDir ( dir )
251
277
}
252
278
253
279
// RunInDir executes the command in given directory and default timeout
254
280
// duration. It returns stdout and error (combined with stderr).
255
281
func (c * Command ) RunInDir (dir string ) ([]byte , error ) {
256
- return c .RunInDirWithTimeout (DefaultTimeout , dir )
282
+ stdout := new (bytes.Buffer )
283
+ stderr := new (bytes.Buffer )
284
+ if err := c .RunInDirPipeline (stdout , stderr , dir ); err != nil {
285
+ return nil , concatenateError (err , stderr .String ())
286
+ }
287
+ return stdout .Bytes (), nil
257
288
}
258
289
259
290
// RunWithTimeout executes the command in working directory and given timeout
260
291
// duration. It returns stdout in string and error (combined with stderr).
292
+ //
293
+ // Deprecated: Use RunInDir and CommandOptions instead.
294
+ // TODO: remove this in the next major version
261
295
func (c * Command ) RunWithTimeout (timeout time.Duration ) ([]byte , error ) {
262
- stdout , err := c .RunInDirWithTimeout (timeout , "" )
263
- if err != nil {
264
- return nil , err
296
+ if timeout != 0 {
297
+ c = c .WithTimeout (timeout )
265
298
}
266
- return stdout , nil
299
+ return c . Run ()
267
300
}
268
301
269
302
// Run executes the command in working directory and default timeout duration.
270
303
// It returns stdout in string and error (combined with stderr).
271
304
func (c * Command ) Run () ([]byte , error ) {
272
- return c .RunWithTimeout (DefaultTimeout )
305
+ stdout , err := c .RunInDir ("" )
306
+ if err != nil {
307
+ return nil , err
308
+ }
309
+ return stdout , nil
273
310
}
0 commit comments