Skip to content

Commit 14e6573

Browse files
Add command options and pass stdin to command (#74)
Co-authored-by: Joe Chen <[email protected]>
1 parent d462647 commit 14e6573

11 files changed

+271
-83
lines changed

command.go

+59-12
Original file line numberDiff line numberDiff line change
@@ -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.
2632
func (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.
5469
func (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

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/gogs/git-module
22

3-
go 1.12
3+
go 1.13
44

55
require (
66
github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75

0 commit comments

Comments
 (0)