posh/pkg/shell/shell.go
Kevin Franklin Kim e2ad376b6c initial commit
2023-01-03 15:37:15 +01:00

135 lines
2.7 KiB
Go

package shell
import (
"context"
"fmt"
"io"
"os"
"os/exec"
"strings"
"github.com/foomo/posh/pkg/log"
)
// Shell struct
type Shell struct {
l log.Logger
cmd *exec.Cmd
quiet bool
args []string
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
}
// ------------------------------------------------------------------------------------------------
// ~ Constructor
// ------------------------------------------------------------------------------------------------
func New(ctx context.Context, l log.Logger, inputs ...interface{}) *Shell {
var args []string
for _, input := range inputs {
if value, ok := input.(string); ok {
args = append(args, value)
} else if value, ok := input.([]string); ok {
args = append(args, value...)
} else {
args = append(args, fmt.Sprintf("%v", args))
}
}
cmd := exec.CommandContext(ctx, "/bin/sh", "-c")
cmd.Env = os.Environ()
return &Shell{
l: l,
cmd: cmd,
args: args,
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
}
}
// ------------------------------------------------------------------------------------------------
// ~ Public methods
// ------------------------------------------------------------------------------------------------
func (s *Shell) Args(args ...string) *Shell {
s.args = append(s.args, args...)
return s
}
func (s *Shell) Env(env []string) *Shell {
s.cmd.Env = append(s.cmd.Env, env...)
return s
}
func (s *Shell) Dir(dir string) *Shell {
s.cmd.Dir = dir
return s
}
func (s *Shell) Quiet() *Shell {
s.quiet = true
return s
}
func (s *Shell) Run() error {
args := s.args
s.cmd.Args = append(s.cmd.Args, strings.Join(args, " "))
s.cmd.Stdin = s.Stdin
if !s.quiet {
s.cmd.Stdout = s.Stdout
s.cmd.Stderr = s.Stderr
}
s.debug()
return s.cmd.Run()
}
func (s *Shell) Output() ([]byte, error) {
args := s.args
s.cmd.Args = append(s.cmd.Args, strings.Join(args, " "))
if !s.quiet {
s.cmd.Stdin = s.Stdin
s.cmd.Stderr = s.Stderr
}
s.debug()
return s.cmd.Output()
}
// Wait ...
func (s *Shell) Wait() error {
args := s.args
s.cmd.Args = append(s.cmd.Args, strings.Join(args, " "))
s.cmd.Stdin = s.Stdin
if !s.quiet {
s.cmd.Stdout = s.Stdout
s.cmd.Stderr = s.Stderr
}
s.debug()
// start the process and wait till it's finished
if err := s.cmd.Start(); err != nil {
return err
} else if err := s.cmd.Wait(); err != nil {
return err
}
return nil
}
// ------------------------------------------------------------------------------------------------
// ~ Private methods
// ------------------------------------------------------------------------------------------------
func (s *Shell) debug() {
s.l.Debugf(`"Executing:
$ %s
Directory: %s
%s
`,
s.cmd.String(),
s.cmd.Dir,
strings.Join(s.cmd.Environ(), "\n"),
)
}