@@ -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