@@ -22,6 +22,12 @@ type Command struct {
2222 envs []string
2323}
2424
25+ // CommandOptions contains options for running a command.
26+ type CommandOptions struct {
27+ Args []string
28+ Envs []string
29+ }
30+
2531// String returns the string representation of the command.
2632func (c * Command ) String () string {
2733 if len (c .args ) == 0 {
@@ -50,6 +56,15 @@ func (c *Command) AddEnvs(envs ...string) *Command {
5056 return c
5157}
5258
59+ // AddOptions adds options to the command.
60+ func (c * Command ) AddOptions (opts ... CommandOptions ) * Command {
61+ for _ , opt := range opts {
62+ c .AddArgs (opt .Args ... )
63+ c .AddEnvs (opt .Envs ... )
64+ }
65+ return c
66+ }
67+
5368// AddCommitter appends given committer to the command.
5469func (c * Command ) AddCommitter (committer * Signature ) * Command {
5570 c .AddEnvs ("GIT_COMMITTER_NAME=" + committer .Name , "GIT_COMMITTER_EMAIL=" + committer .Email )
@@ -87,36 +102,52 @@ func (w *limitDualWriter) Write(p []byte) (int, error) {
87102 return w .w .Write (p )
88103}
89104
90- // RunInDirPipelineWithTimeout executes the command in given directory and
91- // timeout duration. It pipes stdout and stderr to supplied io.Writer.
92- // DefaultTimeout will be used if the timeout duration is less than
105+ // RunInDirOptions contains options for running a command in a directory.
106+ type RunInDirOptions struct {
107+ // Stdin is the input to the command.
108+ Stdin io.Reader
109+ // Stdout is the outputs from the command.
110+ Stdout io.Writer
111+ // Stderr is the error output from the command.
112+ Stderr io.Writer
113+ // Timeout is the duration to wait before timing out.
114+ Timeout time.Duration
115+ }
116+
117+ // RunInDirWithOptions executes the command in given directory and options. It
118+ // pipes stdin from supplied io.Reader, and pipes stdout and stderr to supplied
119+ // io.Writer. DefaultTimeout will be used if the timeout duration is less than
93120// time.Nanosecond (i.e. less than or equal to 0). It returns an ErrExecTimeout
94121// if the execution was timed out.
95- func (c * Command ) RunInDirPipelineWithTimeout (timeout time.Duration , stdout , stderr io.Writer , dir string ) (err error ) {
96- if timeout < time .Nanosecond {
97- timeout = DefaultTimeout
122+ func (c * Command ) RunInDirWithOptions (dir string , opts ... RunInDirOptions ) (err error ) {
123+ var opt RunInDirOptions
124+ if len (opts ) > 0 {
125+ opt = opts [0 ]
126+ }
127+ if opt .Timeout < time .Nanosecond {
128+ opt .Timeout = DefaultTimeout
98129 }
99130
100131 buf := new (bytes.Buffer )
101- w := stdout
132+ w := opt . Stdout
102133 if logOutput != nil {
103134 buf .Grow (512 )
104135 w = & limitDualWriter {
105136 W : buf ,
106137 N : int64 (buf .Cap ()),
107- w : stdout ,
138+ w : opt . Stdout ,
108139 }
109140 }
110141
111142 defer func () {
112143 if len (dir ) == 0 {
113- log ("[timeout: %v] %s\n %s" , timeout , c , buf .Bytes ())
144+ log ("[timeout: %v] %s\n %s" , opt . Timeout , c , buf .Bytes ())
114145 } else {
115- log ("[timeout: %v] %s: %s\n %s" , timeout , dir , c , buf .Bytes ())
146+ log ("[timeout: %v] %s: %s\n %s" , opt . Timeout , dir , c , buf .Bytes ())
116147 }
117148 }()
118149
119- ctx , cancel := context .WithTimeout (context .Background (), timeout )
150+ ctx , cancel := context .WithTimeout (context .Background (), opt . Timeout )
120151 defer func () {
121152 cancel ()
122153 if err == context .DeadlineExceeded {
@@ -129,8 +160,9 @@ func (c *Command) RunInDirPipelineWithTimeout(timeout time.Duration, stdout, std
129160 cmd .Env = append (os .Environ (), c .envs ... )
130161 }
131162 cmd .Dir = dir
163+ cmd .Stdin = opt .Stdin
132164 cmd .Stdout = w
133- cmd .Stderr = stderr
165+ cmd .Stderr = opt . Stderr
134166 if err = cmd .Start (); err != nil {
135167 return err
136168 }
@@ -153,6 +185,21 @@ func (c *Command) RunInDirPipelineWithTimeout(timeout time.Duration, stdout, std
153185 case err = <- result :
154186 return err
155187 }
188+
189+ }
190+
191+ // RunInDirPipelineWithTimeout executes the command in given directory and
192+ // timeout duration. It pipes stdout and stderr to supplied io.Writer.
193+ // DefaultTimeout will be used if the timeout duration is less than
194+ // time.Nanosecond (i.e. less than or equal to 0). It returns an ErrExecTimeout
195+ // if the execution was timed out.
196+ func (c * Command ) RunInDirPipelineWithTimeout (timeout time.Duration , stdout , stderr io.Writer , dir string ) (err error ) {
197+ return c .RunInDirWithOptions (dir , RunInDirOptions {
198+ Stdin : nil ,
199+ Stdout : stdout ,
200+ Stderr : stderr ,
201+ Timeout : timeout ,
202+ })
156203}
157204
158205// RunInDirPipeline executes the command in given directory and default timeout
0 commit comments