2017-03-12 17:18:59 -03:00
|
|
|
package execext
|
|
|
|
|
|
|
|
|
|
import (
|
2017-04-12 20:32:56 -03:00
|
|
|
"context"
|
2017-04-22 15:46:29 -03:00
|
|
|
"errors"
|
|
|
|
|
"io"
|
|
|
|
|
"strings"
|
2017-09-02 11:32:24 -03:00
|
|
|
"sync"
|
2017-04-22 15:46:29 -03:00
|
|
|
|
2017-09-02 11:19:00 -03:00
|
|
|
"mvdan.cc/sh/interp"
|
|
|
|
|
"mvdan.cc/sh/syntax"
|
2017-03-12 17:18:59 -03:00
|
|
|
)
|
|
|
|
|
|
2017-09-02 11:32:24 -03:00
|
|
|
var (
|
|
|
|
|
parserPool = sync.Pool{
|
|
|
|
|
New: func() interface{} {
|
|
|
|
|
return syntax.NewParser()
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
runnerPool = sync.Pool{
|
|
|
|
|
New: func() interface{} {
|
|
|
|
|
return &interp.Runner{}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2017-04-24 10:25:38 -03:00
|
|
|
// RunCommandOptions is the options for the RunCommand func
|
2017-04-22 15:46:29 -03:00
|
|
|
type RunCommandOptions struct {
|
|
|
|
|
Context context.Context
|
|
|
|
|
Command string
|
|
|
|
|
Dir string
|
|
|
|
|
Env []string
|
|
|
|
|
Stdin io.Reader
|
|
|
|
|
Stdout io.Writer
|
|
|
|
|
Stderr io.Writer
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-12 17:18:59 -03:00
|
|
|
var (
|
2017-04-22 15:46:29 -03:00
|
|
|
// ErrNilOptions is returned when a nil options is given
|
|
|
|
|
ErrNilOptions = errors.New("execext: nil options given")
|
2017-03-12 17:18:59 -03:00
|
|
|
)
|
|
|
|
|
|
2017-04-22 15:46:29 -03:00
|
|
|
// RunCommand runs a shell command
|
|
|
|
|
func RunCommand(opts *RunCommandOptions) error {
|
|
|
|
|
if opts == nil {
|
|
|
|
|
return ErrNilOptions
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-02 11:32:24 -03:00
|
|
|
parser := parserPool.Get().(*syntax.Parser)
|
|
|
|
|
defer parserPool.Put(parser)
|
|
|
|
|
|
|
|
|
|
p, err := parser.Parse(strings.NewReader(opts.Command), "")
|
2017-04-22 15:46:29 -03:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2017-03-12 17:18:59 -03:00
|
|
|
|
2017-09-02 11:32:24 -03:00
|
|
|
r := runnerPool.Get().(*interp.Runner)
|
|
|
|
|
defer runnerPool.Put(r)
|
|
|
|
|
|
|
|
|
|
r.Context = opts.Context
|
|
|
|
|
r.Dir = opts.Dir
|
|
|
|
|
r.Env = opts.Env
|
|
|
|
|
r.Stdin = opts.Stdin
|
|
|
|
|
r.Stdout = opts.Stdout
|
|
|
|
|
r.Stderr = opts.Stderr
|
|
|
|
|
|
2017-08-05 14:20:44 -03:00
|
|
|
if err = r.Reset(); err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
return r.Run(p)
|
2017-03-12 17:18:59 -03:00
|
|
|
}
|