@@ -20,12 +20,18 @@ type Command struct {
20
20
name string
21
21
args []string
22
22
envs []string
23
+ ctx context.Context
23
24
}
24
25
25
26
// CommandOptions contains options for running a command.
27
+ // If timeout is zero, DefaultTimeout will be used.
28
+ // If timeout is less than zero, no timeout will be set.
29
+ // If context is nil, context.Background() will be used.
26
30
type CommandOptions struct {
27
- Args []string
28
- Envs []string
31
+ Args []string
32
+ Envs []string
33
+ Timeout time.Duration
34
+ Context context.Context
29
35
}
30
36
31
37
// String returns the string representation of the command.
@@ -38,9 +44,16 @@ func (c *Command) String() string {
38
44
39
45
// NewCommand creates and returns a new Command with given arguments for "git".
40
46
func NewCommand (args ... string ) * Command {
47
+ return NewCommandWithContext (context .Background (), args ... )
48
+ }
49
+
50
+ // NewCommandWithContext creates and returns a new Command with given arguments
51
+ // and context for "git".
52
+ func NewCommandWithContext (ctx context.Context , args ... string ) * Command {
41
53
return & Command {
42
54
name : "git" ,
43
55
args : args ,
56
+ ctx : ctx ,
44
57
}
45
58
}
46
59
@@ -56,8 +69,21 @@ func (c *Command) AddEnvs(envs ...string) *Command {
56
69
return c
57
70
}
58
71
72
+ // WithContext sets the context for the command.
73
+ func (c * Command ) WithContext (ctx context.Context ) * Command {
74
+ c .ctx = ctx
75
+ return c
76
+ }
77
+
59
78
// AddOptions adds options to the command.
60
79
func (c * Command ) AddOptions (opts ... CommandOptions ) * Command {
80
+ if len (opts ) > 0 {
81
+ opt := opts [0 ]
82
+ if opt .Context != nil {
83
+ c .ctx = opt .Context
84
+ }
85
+ }
86
+
61
87
for _ , opt := range opts {
62
88
c .AddArgs (opt .Args ... )
63
89
c .AddEnvs (opt .Envs ... )
@@ -124,7 +150,9 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
124
150
if len (opts ) > 0 {
125
151
opt = opts [0 ]
126
152
}
127
- if opt .Timeout < time .Nanosecond {
153
+ if opt .Timeout < 0 {
154
+ opt .Timeout = - 1
155
+ } else if opt .Timeout == 0 {
128
156
opt .Timeout = DefaultTimeout
129
157
}
130
158
@@ -147,13 +175,21 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
147
175
}
148
176
}()
149
177
150
- ctx , cancel := context .WithTimeout (context .Background (), opt .Timeout )
151
- defer func () {
152
- cancel ()
153
- if err == context .DeadlineExceeded {
154
- err = ErrExecTimeout
155
- }
156
- }()
178
+ ctx := context .Background ()
179
+ if c .ctx != nil {
180
+ ctx = c .ctx
181
+ }
182
+
183
+ if opt .Timeout > 0 {
184
+ var cancel context.CancelFunc
185
+ ctx , cancel = context .WithTimeout (ctx , opt .Timeout )
186
+ defer func () {
187
+ cancel ()
188
+ if err == context .DeadlineExceeded {
189
+ err = ErrExecTimeout
190
+ }
191
+ }()
192
+ }
157
193
158
194
cmd := exec .CommandContext (ctx , c .name , c .args ... )
159
195
if len (c .envs ) > 0 {
0 commit comments