@@ -17,10 +17,11 @@ import (
1717
1818// Command contains the name, arguments and environment variables of a command.
1919type 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
2425}
2526
2627// CommandOptions contains options for running a command.
@@ -69,17 +70,29 @@ func (c *Command) AddEnvs(envs ...string) *Command {
6970 return c
7071}
7172
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 {
7475 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
7688}
7789
7890// AddOptions adds options to the command.
7991// Note: only the last option will take effect if there are duplicated options.
8092func (c * Command ) AddOptions (opts ... CommandOptions ) * Command {
8193 for _ , opt := range opts {
82- c = c .WithContext (opt .Context )
94+ c .timeout = opt .Timeout
95+ c .ctx = opt .Context
8396 c .AddArgs (opt .Args ... )
8497 c .AddEnvs (opt .Envs ... )
8598 }
@@ -132,6 +145,8 @@ type RunInDirOptions struct {
132145 // Stderr is the error output from the command.
133146 Stderr io.Writer
134147 // Timeout is the duration to wait before timing out.
148+ //
149+ // Deprecated: Use CommandOptions.Timeout or *Command.WithTimeout instead.
135150 Timeout time.Duration
136151}
137152
@@ -145,10 +160,15 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
145160 if len (opts ) > 0 {
146161 opt = opts [0 ]
147162 }
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
152172 }
153173
154174 buf := new (bytes.Buffer )
@@ -164,9 +184,9 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
164184
165185 defer func () {
166186 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 ())
168188 } 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 ())
170190 }
171191 }()
172192
@@ -175,9 +195,9 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
175195 ctx = c .ctx
176196 }
177197
178- if opt . Timeout > 0 {
198+ if timeout > 0 {
179199 var cancel context.CancelFunc
180- ctx , cancel = context .WithTimeout (ctx , opt . Timeout )
200+ ctx , cancel = context .WithTimeout (ctx , timeout )
181201 defer func () {
182202 cancel ()
183203 if err == context .DeadlineExceeded {
@@ -219,55 +239,72 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
219239
220240}
221241
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+
222252// RunInDirPipelineWithTimeout executes the command in given directory and
223253// timeout duration. It pipes stdout and stderr to supplied io.Writer.
224254// DefaultTimeout will be used if the timeout duration is less than
225255// time.Nanosecond (i.e. less than or equal to 0). It returns an ErrExecTimeout
226256// if the execution was timed out.
257+ //
258+ // Deprecated: Use RunInDirPipeline and CommandOptions instead.
259+ // TODO: remove this in the next major version
227260func (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 )
240265}
241266
242267// RunInDirWithTimeout executes the command in given directory and timeout
243268// 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
244272func (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 )
249275 }
250- return stdout . Bytes (), nil
276+ return c . RunInDir ( dir )
251277}
252278
253279// RunInDir executes the command in given directory and default timeout
254280// duration. It returns stdout and error (combined with stderr).
255281func (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
257288}
258289
259290// RunWithTimeout executes the command in working directory and given timeout
260291// 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
261295func (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 )
265298 }
266- return stdout , nil
299+ return c . Run ()
267300}
268301
269302// Run executes the command in working directory and default timeout duration.
270303// It returns stdout in string and error (combined with stderr).
271304func (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
273310}
0 commit comments