You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
1.6 KiB
84 lines
1.6 KiB
2 years ago
|
package keybase
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"os/exec"
|
||
|
)
|
||
|
|
||
|
// apiCmd holds the pipes that connect to an executed command
|
||
|
type apiCmd struct {
|
||
|
Stderr io.ReadCloser
|
||
|
Stdin io.WriteCloser
|
||
|
Stdout io.ReadCloser
|
||
|
startFunc func() error
|
||
|
}
|
||
|
|
||
|
type cmd interface {
|
||
|
Start() error
|
||
|
Stdin() io.WriteCloser
|
||
|
Stdout() io.ReadCloser
|
||
|
Stderr() io.ReadCloser
|
||
|
}
|
||
|
|
||
|
type defaultCmd struct {
|
||
|
apiCmd *apiCmd
|
||
|
}
|
||
|
|
||
|
func (c *defaultCmd) Start() error {
|
||
|
return c.apiCmd.startFunc()
|
||
|
}
|
||
|
|
||
|
func (c *defaultCmd) Stdin() io.WriteCloser {
|
||
|
return c.apiCmd.Stdin
|
||
|
}
|
||
|
|
||
|
func (c *defaultCmd) Stdout() io.ReadCloser {
|
||
|
return c.apiCmd.Stdout
|
||
|
}
|
||
|
|
||
|
func (c *defaultCmd) Stderr() io.ReadCloser {
|
||
|
return c.apiCmd.Stderr
|
||
|
}
|
||
|
|
||
|
var _ cmd = &defaultCmd{}
|
||
|
|
||
|
func newApiCmd(ctx context.Context, execCmd string, args ...string) (cmd, error) {
|
||
|
var err error
|
||
|
|
||
|
// create a new apiCmd
|
||
|
cmd := &apiCmd{}
|
||
|
|
||
|
// set up the command
|
||
|
api := exec.CommandContext(ctx, execCmd, args...)
|
||
|
|
||
|
// an empty start func for failures
|
||
|
cmd.startFunc = func() error { return nil }
|
||
|
|
||
|
// hook up the stderr pipe
|
||
|
if cmd.Stderr, err = api.StderrPipe(); err != nil {
|
||
|
return nil, fmt.Errorf("failed to get pipe: %v", err)
|
||
|
}
|
||
|
|
||
|
// hook up the stdout pipe
|
||
|
if cmd.Stdout, err = api.StdoutPipe(); err != nil {
|
||
|
return nil, fmt.Errorf("failed to get pipe: %v", err)
|
||
|
}
|
||
|
|
||
|
// hook up the stdin pipe
|
||
|
if cmd.Stdin, err = api.StdinPipe(); err != nil {
|
||
|
return nil, fmt.Errorf("failed to get pipe: %v", err)
|
||
|
}
|
||
|
|
||
|
// create an anonymous function to start the commands
|
||
|
cmd.startFunc = func() error {
|
||
|
if err := api.Start(); err != nil {
|
||
|
return fmt.Errorf("failed to start command: %v", err)
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return &defaultCmd{cmd}, nil
|
||
|
}
|