diff --git a/cmdext/builder.go b/cmdext/builder.go new file mode 100644 index 0000000..c97d15f --- /dev/null +++ b/cmdext/builder.go @@ -0,0 +1,56 @@ +package cmdext + +import ( + "fmt" + "time" +) + +type CommandRunner struct { + program string + args []string + timeout *time.Duration + env []string +} + +func Runner(program string) *CommandRunner { + return &CommandRunner{ + program: program, + args: make([]string, 0), + timeout: nil, + env: make([]string, 0), + } +} + +func (r *CommandRunner) Arg(arg string) *CommandRunner { + r.args = append(r.args, arg) + return r +} + +func (r *CommandRunner) Args(arg []string) *CommandRunner { + r.args = append(r.args, arg...) + return r +} + +func (r *CommandRunner) Timeout(timeout time.Duration) *CommandRunner { + r.timeout = &timeout + return r +} + +func (r *CommandRunner) Env(key, value string) *CommandRunner { + r.env = append(r.env, fmt.Sprintf("%s=%s", key, value)) + return r +} + +func (r *CommandRunner) RawEnv(env string) *CommandRunner { + r.env = append(r.env, env) + return r +} + +func (r *CommandRunner) Envs(env []string) *CommandRunner { + r.env = append(r.env, env...) + return r +} + +func (r *CommandRunner) Run() (CommandResult, error) { + return run(*r) +} diff --git a/cmdext/cmdrunner.go b/cmdext/cmdrunner.go index c00ff6d..49d749e 100644 --- a/cmdext/cmdrunner.go +++ b/cmdext/cmdrunner.go @@ -14,9 +14,9 @@ type CommandResult struct { CommandTimedOut bool } -func RunCommand(program string, args []string, timeout *time.Duration) (CommandResult, error) { - - cmd := exec.Command(program, args...) +func run(opt CommandRunner) (CommandResult, error) { + cmd := exec.Command(opt.program, opt.args...) + cmd.Env = append(cmd.Env, opt.env) stdoutPipe, err := cmd.StdoutPipe() if err != nil { @@ -75,68 +75,42 @@ func RunCommand(program string, args []string, timeout *time.Duration) (CommandR } }() - if timeout != nil { + var timeoutChan <-chan time.Time = make(chan time.Time, 1) + if opt.timeout != nil { + timeoutChan = time.After(*opt.timeout) + } - select { + select { - case <-time.After(*timeout): - _ = cmd.Process.Kill() + case <-timeoutChan: + _ = cmd.Process.Kill() + return CommandResult{ + StdOut: stdout, + StdErr: stderr, + StdCombined: stdcombined, + ExitCode: -1, + CommandTimedOut: true, + }, nil + + case err := <-errch: + if exiterr, ok := err.(*exec.ExitError); ok { return CommandResult{ StdOut: stdout, StdErr: stderr, StdCombined: stdcombined, - ExitCode: -1, - CommandTimedOut: true, + ExitCode: exiterr.ExitCode(), + CommandTimedOut: false, + }, nil + } else if err != nil { + return CommandResult{}, err + } else { + return CommandResult{ + StdOut: stdout, + StdErr: stderr, + StdCombined: stdcombined, + ExitCode: 0, + CommandTimedOut: false, }, nil - - case err := <-errch: - if exiterr, ok := err.(*exec.ExitError); ok { - return CommandResult{ - StdOut: stdout, - StdErr: stderr, - StdCombined: stdcombined, - ExitCode: exiterr.ExitCode(), - CommandTimedOut: false, - }, nil - } else if err != nil { - return CommandResult{}, err - } else { - return CommandResult{ - StdOut: stdout, - StdErr: stderr, - StdCombined: stdcombined, - ExitCode: 0, - CommandTimedOut: false, - }, nil - } - - } - - } else { - - select { - - case err := <-errch: - if exiterr, ok := err.(*exec.ExitError); ok { - return CommandResult{ - StdOut: stdout, - StdErr: stderr, - StdCombined: stdcombined, - ExitCode: exiterr.ExitCode(), - CommandTimedOut: false, - }, nil - } else if err != nil { - return CommandResult{}, err - } else { - return CommandResult{ - StdOut: stdout, - StdErr: stderr, - StdCombined: stdcombined, - ExitCode: 0, - CommandTimedOut: false, - }, nil - } - } } } diff --git a/cmdext/helper.go b/cmdext/helper.go new file mode 100644 index 0000000..e21496d --- /dev/null +++ b/cmdext/helper.go @@ -0,0 +1,12 @@ +package cmdext + +import "time" + +func RunCommand(program string, args []string, timeout *time.Duration) (CommandResult, error) { + b := Runner(program) + b = b.Args(args) + if timeout != nil { + b = b.Timeout(*timeout) + } + return b.Run() +}