@@ -20,12 +20,18 @@ type Command struct {
2020 name string
2121 args []string
2222 envs []string
23+ ctx context.Context
2324}
2425
2526// 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.
2630type CommandOptions struct {
27- Args []string
28- Envs []string
31+ Args []string
32+ Envs []string
33+ Timeout time.Duration
34+ Context context.Context
2935}
3036
3137// String returns the string representation of the command.
@@ -38,9 +44,16 @@ func (c *Command) String() string {
3844
3945// NewCommand creates and returns a new Command with given arguments for "git".
4046func 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 {
4153 return & Command {
4254 name : "git" ,
4355 args : args ,
56+ ctx : ctx ,
4457 }
4558}
4659
@@ -56,8 +69,21 @@ func (c *Command) AddEnvs(envs ...string) *Command {
5669 return c
5770}
5871
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+
5978// AddOptions adds options to the command.
6079func (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+
6187 for _ , opt := range opts {
6288 c .AddArgs (opt .Args ... )
6389 c .AddEnvs (opt .Envs ... )
@@ -124,7 +150,9 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
124150 if len (opts ) > 0 {
125151 opt = opts [0 ]
126152 }
127- if opt .Timeout < time .Nanosecond {
153+ if opt .Timeout < 0 {
154+ opt .Timeout = - 1
155+ } else if opt .Timeout == 0 {
128156 opt .Timeout = DefaultTimeout
129157 }
130158
@@ -147,13 +175,21 @@ func (c *Command) RunInDirWithOptions(dir string, opts ...RunInDirOptions) (err
147175 }
148176 }()
149177
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+ }
157193
158194 cmd := exec .CommandContext (ctx , c .name , c .args ... )
159195 if len (c .envs ) > 0 {
0 commit comments