Skip to content

Commit f7e0f64

Browse files
committed
pass context in as a argument rather than using the withContext pattern
1 parent c6e1540 commit f7e0f64

File tree

2 files changed

+20
-25
lines changed

2 files changed

+20
-25
lines changed

command.go

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ type Command struct {
2020
StderrWriter io.Writer
2121
StdoutWriter io.Writer
2222
WorkingDir string
23-
ctx context.Context
2423
executed bool
2524
exitCode int
2625
// stderr and stdout retrieve the output after the command was executed
@@ -59,7 +58,6 @@ func NewCommand(cmd string, options ...func(*Command)) *Command {
5958
Timeout: 30 * time.Minute,
6059
executed: false,
6160
Env: []string{},
62-
ctx: context.Background(),
6361
}
6462

6563
c.StdoutWriter = io.MultiWriter(&c.stdout, &c.combined)
@@ -145,17 +143,6 @@ func WithEnvironmentVariables(env EnvVars) func(c *Command) {
145143
}
146144
}
147145

148-
// WithContext adds context.Context to the command. Context timeout/deadline
149-
// is favored over Timeout
150-
func WithContext(ctx context.Context) func(c *Command) {
151-
if ctx == nil {
152-
panic("nil context")
153-
}
154-
return func(c *Command) {
155-
c.ctx = ctx
156-
}
157-
}
158-
159146
// AddEnv adds an environment variable to the command
160147
// If a variable gets passed like ${VAR_NAME} the env variable will be read out by the current shell
161148
func (c *Command) AddEnv(key string, value string) {
@@ -198,9 +185,8 @@ func (c *Command) isExecuted(property string) {
198185
}
199186
}
200187

201-
// Execute executes the command and writes the results into it's own instance
202-
// The results can be received with the Stdout(), Stderr() and ExitCode() methods
203-
func (c *Command) Execute() error {
188+
// ExecuteContext runs Execute but with Context
189+
func (c *Command) ExecuteContext(ctx context.Context) error {
204190
cmd := createBaseCommand(c)
205191
cmd.Env = c.Env
206192
cmd.Dir = c.Dir
@@ -210,11 +196,11 @@ func (c *Command) Execute() error {
210196

211197
// Create timer only if timeout was set > 0 and context does
212198
// not have a deadline
213-
_, hasDeadline := c.ctx.Deadline()
199+
_, hasDeadline := ctx.Deadline()
214200
if c.Timeout != 0 && !hasDeadline {
215-
ctx, cancel := context.WithTimeout(c.ctx, c.Timeout)
201+
subCtx, cancel := context.WithTimeout(ctx, c.Timeout)
216202
defer cancel()
217-
c.ctx = ctx
203+
ctx = subCtx
218204
}
219205

220206
err := cmd.Start()
@@ -228,14 +214,14 @@ func (c *Command) Execute() error {
228214
}()
229215

230216
select {
231-
case <-c.ctx.Done():
217+
case <-ctx.Done():
232218
if err := cmd.Process.Kill(); err != nil {
233219
return fmt.Errorf("Timeout occurred and can not kill process with pid %v", cmd.Process.Pid)
234220
}
235221
if c.Timeout != 0 && !hasDeadline {
236222
return fmt.Errorf("Command timed out after %v", c.Timeout)
237223
}
238-
return c.ctx.Err()
224+
return ctx.Err()
239225
case err := <-done:
240226
if err != nil {
241227
c.getExitCode(err)
@@ -245,6 +231,12 @@ func (c *Command) Execute() error {
245231
return nil
246232
}
247233

234+
// Execute executes the command and writes the results into it's own instance
235+
// The results can be received with the Stdout(), Stderr() and ExitCode() methods
236+
func (c *Command) Execute() error {
237+
return c.ExecuteContext(context.Background())
238+
}
239+
248240
func (c *Command) getExitCode(err error) {
249241
if exitErr, ok := err.(*exec.ExitError); ok {
250242
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {

command_test.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,15 @@ func TestCommand_SetOptions(t *testing.T) {
133133
}
134134

135135
func TestCommand_WithContext(t *testing.T) {
136+
// Ensure context is favored over WithTimeout
137+
cmd := NewCommand("sleep 3;", WithTimeout(1*time.Second))
138+
err := cmd.Execute()
139+
assert.NotNil(t, err)
140+
assert.Equal(t, "Command timed out after 1s", err.Error())
141+
136142
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
137143
defer cancel()
138-
// WithContext is favored over Timeout
139-
cmd := NewCommand("sleep 3;", WithContext(ctx), WithTimeout(1*time.Second))
140-
141-
err := cmd.Execute()
144+
err = cmd.ExecuteContext(ctx)
142145
assert.NotNil(t, err)
143146
assert.Equal(t, "context deadline exceeded", err.Error())
144147
}

0 commit comments

Comments
 (0)