diff --git a/pkg/exec/call.go b/pkg/exec/call.go
deleted file mode 100644
index 8b23657..0000000
--- a/pkg/exec/call.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package exec
-
-import (
- "strings"
-
- "gopkg.in/hedzr/errors.v3"
-)
-
-// Call executes the command line via system (OS).
-//
-// DO NOT QUOTE: in 'cmd', A command line shouldn't has quoted parts.
-// These are bad:
-//
-// cmd := "ls '/usr/bin'"
-// cmd := `tar "c:/My Documents/"`
-//
-// Uses CallSlice if your args includes space (like 'c:/My Documents/')
-func Call(cmd string, fn func(retCode int, stdoutText string)) (err error) {
- a := strings.Split(cmd, " ")
- err = internalCallImpl(a, fn, true)
- return
-}
-
-// CallQuiet executes the command line via system (OS) without error printing.
-//
-// DO NOT QUOTE: in 'cmd', A command line shouldn't has quoted parts.
-// These are bad:
-//
-// cmd := "ls '/usr/bin'"
-// cmd := `tar "c:/My Documents/"`
-//
-// Uses CallSliceQuiet if your args includes space (like 'c:/My Documents/')
-func CallQuiet(cmd string, fn func(retCode int, stdoutText string)) (err error) {
- a := strings.Split(cmd, " ")
- err = internalCallImpl(a, fn, false)
- return
-}
-
-// CallSlice executes the command line via system (OS).
-func CallSlice(cmd []string, fn func(retCode int, stdoutText string)) (err error) {
- err = internalCallImpl(cmd, fn, true)
- return
-}
-
-// CallSliceQuiet executes the command line via system (OS) without error printing.
-func CallSliceQuiet(cmd []string, fn func(retCode int, stdoutText string)) (err error) {
- err = internalCallImpl(cmd, fn, false)
- return
-}
-
-// internalCallImpl executes the command line via system (OS) without error printing.
-func internalCallImpl(cmd []string, fn func(retCode int, stdoutText string), autoErrReport bool) (err error) {
- var (
- str string
- rc int
- )
-
- _, str, err = RunWithOutput(cmd[0], cmd[1:]...)
- if err != nil {
- if autoErrReport {
- err = errors.New("Error on launching '%v': %v", cmd, err)
- }
- return
- }
- fn(rc, str)
- return
-}
diff --git a/pkg/exec/run.go b/pkg/exec/run.go
deleted file mode 100644
index 74e6f6c..0000000
--- a/pkg/exec/run.go
+++ /dev/null
@@ -1,450 +0,0 @@
-package exec
-
-import (
- "bytes"
- "context"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "os/exec"
- "strings"
- "sync"
-
- "gopkg.in/hedzr/errors.v3"
-)
-
-// New return a calling object to allow you to make the fluent call.
-//
-// Just like:
-//
-// exec.New().WithCommand("bash", "-c", "echo hello world!").Run()
-// err = exec.New().WithCommand("bash", "-c", "echo hello world!").RunAndCheckError()
-//
-// Processing the invoke result:
-//
-// exec.New().
-// WithCommand("bash", "-c", "echo hello world!").
-// WithStdoutCaught().
-// WithOnOK(func(retCode int, stdoutText string) { }).
-// WithStderrCaught().
-// WithOnError(func(err error, retCode int, stdoutText, stderrText string) { }).
-// Run()
-//
-// Use context:
-//
-// exec.New().
-// WithCommandString("bash -c 'echo hello world!'", '\'').
-// WithContext(context.TODO()).
-// Run()
-// // or double quote pieces
-// exec.New().
-// WithCommandString("bash -c \"echo hello world!\"").
-// Run()
-//
-// Auto Left-Padding if WithOnError / WithOnOK /
-// WithStderrCaught / WithStdoutCaught specified
-// (It's no effects when you caught stdout/stderr with
-// the handlers above. In this case, do it with
-// LeftPad manually).
-//
-// args := []string{"-al", "/usr/local/bin"}
-// err := exec.New().
-// WithPadding(8).
-// WithCommandArgs("ls", args...).
-// RunAndCheckError()
-func New(opts ...Opt) *calling {
- c := &calling{}
-
- c.env = append(c.env, os.Environ()...)
-
- for _, opt := range opts {
- opt(c)
- }
- return c
-}
-
-func (c *calling) Run() { _ = c.run() }
-func (c *calling) RunAndCheckError() error { return c.run() }
-
-func (c *calling) WithCommandArgs(cmd string, args ...string) *calling {
- c.Cmd = exec.Command(cmd, args...)
- return c
-}
-
-// WithCommandString allows split command-line by quote
-// characters (default is double-quote).
-func (c *calling) WithCommandString(cmd string, quoteChars ...rune) *calling {
- a := SplitCommandString(cmd, quoteChars...)
- c.Cmd = exec.Command(a[0], a[1:]...)
- return c
-}
-
-func (c *calling) WithCommand(cmd ...interface{}) *calling {
- var args []string
- for _, a := range cmd[1:] {
- if as, ok := a.([]string); ok {
- args = append(args, as...)
- } else if as, ok := a.(string); ok {
- args = append(args, as)
- } else {
- args = append(args, toStringSimple(a))
- }
- }
- c.Cmd = exec.Command(toStringSimple(cmd[0]), args...)
- return c
-}
-
-func (c *calling) WithEnv(key, value string) *calling {
- if key != "" {
- chk := key + "="
- for i, kv := range c.env {
- if strings.HasPrefix(kv, chk) {
- c.env[i] = chk + value
- return c
- }
- }
-
- c.env = append(c.env, chk+value)
- }
- return c
-}
-
-func (c *calling) WithWorkDir(dir string) *calling {
- c.Cmd.Dir = dir
- return c
-}
-
-func (c *calling) WithExtraFiles(files ...*os.File) *calling {
- c.Cmd.ExtraFiles = files
- return c
-}
-
-func (c *calling) WithContext(ctx context.Context) *calling {
- c.Cmd = exec.CommandContext(ctx, c.Cmd.Path, c.Cmd.Args[1:]...)
- return c
-}
-
-func (c *calling) WithStdoutCaught(writer ...io.Writer) *calling {
- for _, w := range writer {
- c.stdoutWriter = w
- }
- c.prepareStdoutPipe()
- return c
-}
-
-func (c *calling) WithOnOK(onOK func(retCode int, stdoutText string)) *calling {
- c.onOK = onOK
- return c
-}
-
-func (c *calling) WithStderrCaught(writer ...io.Writer) *calling {
- for _, w := range writer {
- c.stderrWriter = w
- }
- c.prepareStderrPipe()
- return c
-}
-
-func (c *calling) WithOnError(onError func(err error, retCode int, stdoutText, stderrText string)) *calling {
- c.onError = onError
- return c
-}
-
-// WithPadding apply left paddings to stdout/err if no
-// WithOnError / WithOnOK / WithStderrCaught / WithStdoutCaught
-// specified.
-func (c *calling) WithPadding(leftPadding int) *calling {
- c.leftPadding = leftPadding
- return c
-}
-
-func (c *calling) WithVerboseCommandLine(verbose bool) *calling {
- c.verbose = verbose
- return c
-}
-
-// WithQuietOnError do NOT print error internally
-func (c *calling) WithQuietOnError(quiet bool) *calling {
- c.quiet = quiet
- return c
-}
-
-type calling struct {
- *exec.Cmd
-
- err error
- wg sync.WaitGroup
- stdoutPiper io.ReadCloser
- stderrPiper io.ReadCloser
- stdoutWriter io.Writer
- stderrWriter io.Writer
- env []string
- leftPadding int
- verbose bool // print command-line in std-output dumping
-
- retCode int
- output bytes.Buffer
- slurp bytes.Buffer
-
- quiet bool
-
- onOK func(retCode int, stdoutText string)
- onError func(err error, retCode int, stdoutText, stderrText string)
-}
-
-func (c *calling) run() (err error) {
-
- err = c.runNow()
-
- var ok, er bool
- if err == nil {
- if c.onOK != nil {
- c.onOK(c.retCode, c.output.String())
- ok = true
- }
- }
-
- if c.onError != nil && err != nil {
- c.onError(err, c.retCode, c.output.String(), c.slurp.String())
- // er = true
- return
- }
-
- if !c.quiet {
- if c.output.Len() > 0 && !ok {
- if c.leftPadding > 0 {
- fmt.Print(strings.Repeat(" ", c.leftPadding))
- }
- if c.verbose {
- fmt.Printf("OUTPUT // %v:\n", c.Cmd.Args)
- } else {
- fmt.Print("OUTPUT:\n")
- }
- _, _ = fmt.Fprintf(os.Stdout, "%v\n", leftPad(c.output.String(), c.leftPadding))
- }
- if c.slurp.Len() > 0 && !er && c.retCode != 0 {
- if c.leftPadding > 0 {
- _, _ = fmt.Fprintf(os.Stderr, "%v", strings.Repeat(" ", c.leftPadding))
- }
- if c.verbose {
- fmt.Printf("SLURP // %v:\n", c.Cmd.Args)
- } else {
- fmt.Print("SLURP:\n")
- }
- _, _ = fmt.Fprintf(os.Stderr, "%v\n", leftPad(c.slurp.String(), c.leftPadding))
- }
- if err != nil {
- err = errors.New("system call failed (command-line: %q): %v", c.Args, err)
- }
- }
- return
-}
-
-func (c *calling) runNow() error {
- if c.Cmd == nil {
- return errors.New("WithCommand() hasn't called yet.")
- }
-
- c.Cmd.Env = append(c.Cmd.Env, c.env...)
-
- // log.Debugf("ENV:\n%v", c.Cmd.Env)
-
- if (c.onOK != nil || c.leftPadding > 0) && c.stdoutPiper == nil {
- c.prepareStdoutPipe()
- }
-
- if c.stdoutPiper != nil {
- defer c.stdoutPiper.Close()
- c.wg.Add(1)
- go func() {
- defer c.wg.Done()
- if c.stdoutWriter != nil {
- if c.stdoutWriter == os.Stdout && c.leftPadding > 0 {
- _, _ = io.Copy(&c.output, c.stdoutPiper)
- b := []byte(leftPad(c.output.String(), c.leftPadding))
- _, _ = c.stdoutWriter.Write(b)
- c.output.Reset()
- } else {
- _, _ = io.Copy(c.stdoutWriter, c.stderrPiper)
- }
- } else {
- _, _ = io.Copy(&c.output, c.stdoutPiper)
- }
- }()
- } else {
- c.Cmd.Stdout = os.Stdout
- }
-
- if (c.onError != nil || c.leftPadding > 0) && c.stderrPiper == nil {
- c.prepareStderrPipe()
- }
-
- if c.stderrPiper != nil {
- defer c.stderrPiper.Close()
- c.wg.Add(1)
- go func() {
- defer c.wg.Done()
- if c.stderrWriter != nil {
- if c.stderrWriter == os.Stderr && c.leftPadding > 0 {
- _, _ = io.Copy(&c.slurp, c.stderrPiper)
- b := []byte(leftPad(c.slurp.String(), c.leftPadding))
- _, _ = c.stderrWriter.Write(b)
- c.slurp.Reset()
- } else {
- _, _ = io.Copy(c.stderrWriter, c.stderrPiper)
- }
- } else {
- _, _ = io.Copy(&c.slurp, c.stderrPiper)
- }
- }()
- } else {
- c.Cmd.Stderr = os.Stderr
- }
-
- if c.err = c.Cmd.Start(); c.err != nil {
- // Problem while copying stdin, stdout, or stderr
- c.err = fmt.Errorf("failed: %v, cmd: %q", c.err, c.Path)
- return c.err
- }
-
- // Zero exit status
- // Darwin: launchctl can fail with a zero exit status,
- // so check for emtpy stderr
- if c.Path == "launchctl" {
- slurpText, _ := ioutil.ReadAll(c.stderrPiper)
- if len(slurpText) > 0 && !bytes.HasSuffix(slurpText, []byte("Operation now in progress\n")) {
- c.err = fmt.Errorf("failed with stderr: %s, cmd: %q", slurpText, c.Path)
- return c.err
- }
- }
-
- // slurp, _ := ioutil.ReadAll(stderr)
-
- c.wg.Wait()
-
- if c.err = c.Cmd.Wait(); c.err != nil {
- exitStatus, ok := IsExitError(c.err)
- if ok {
- // CmdS didn't exit with a zero exit status.
- c.retCode = exitStatus
- c.err = errors.New("%q failed with stderr:\n%v\n ", c.Path, c.slurp.String()).WithErrors(c.err)
- return c.err
- }
-
- // An error occurred and there is no exit status.
- // return 0, output, fmt.Errorf("%q failed: %v |\n stderr: %s", command, err.Error(), slurp)
- c.err = errors.New("%q failed with stderr:\n%v\n ", c.Path, c.slurp.String()).WithErrors(c.err)
- return c.err
- }
-
- return nil
-}
-
-func (c *calling) prepareStdoutPipe() {
- c.stdoutPiper, c.err = c.Cmd.StdoutPipe()
- if c.err != nil {
- // Failed to connect pipe
- c.err = fmt.Errorf("failed to connect stdout pipe: %v, cmd: %q", c.err, c.Path)
- }
-}
-
-func (c *calling) prepareStderrPipe() {
- c.stderrPiper, c.err = c.Cmd.StderrPipe()
- if c.err != nil {
- // Failed to connect pipe
- c.err = fmt.Errorf("failed to connect stderr pipe: %v, cmd: %q", c.err, c.Path)
- }
-}
-
-func (c *calling) OutputText() string { return c.output.String() }
-func (c *calling) SlurpText() string { return c.slurp.String() }
-func (c *calling) RetCode() int { return c.retCode }
-func (c *calling) Error() error { return c.err }
-
-type Opt func(*calling)
-
-func WithCommandArgs(cmd string, args ...string) Opt {
- return func(c *calling) {
- c.WithCommandArgs(cmd, args...)
- }
-}
-
-func WithCommandString(cmd string) Opt {
- return func(c *calling) {
- c.WithCommandString(cmd)
- }
-}
-
-func WithCommand(cmd ...interface{}) Opt {
- return func(c *calling) {
- c.WithCommand(cmd...)
- }
-}
-
-func WithEnv(key, value string) Opt {
- return func(c *calling) {
- c.WithEnv(key, value)
- }
-}
-
-func WithWorkDir(dir string) Opt {
- return func(c *calling) {
- c.WithWorkDir(dir)
- }
-}
-
-func WithExtraFiles(files ...*os.File) Opt {
- return func(c *calling) {
- c.WithExtraFiles(files...)
- }
-}
-
-func WithContext(ctx context.Context) Opt {
- return func(c *calling) {
- c.WithContext(ctx)
- }
-}
-
-func WithStdoutCaught(writer ...io.Writer) Opt {
- return func(c *calling) {
- c.WithStdoutCaught(writer...)
- }
-}
-
-func WithOnOK(onOK func(retCode int, stdoutText string)) Opt {
- return func(c *calling) {
- c.WithOnOK(onOK)
- }
-}
-
-func WithStderrCaught(writer ...io.Writer) Opt {
- return func(c *calling) {
- c.WithStderrCaught(writer...)
- }
-}
-
-func WithOnError(onError func(err error, retCode int, stdoutText, stderrText string)) Opt {
- return func(c *calling) {
- c.WithOnError(onError)
- }
-}
-
-func WithPadding(leftPadding int) Opt {
- return func(c *calling) {
- c.WithPadding(leftPadding)
- }
-}
-
-func WithVerboseCommandLine(verbose bool) Opt {
- return func(c *calling) {
- c.WithVerboseCommandLine(verbose)
- }
-}
-
-// WithQuietOnError do NOT print error internally
-func WithQuietOnError(quiet bool) Opt {
- return func(c *calling) {
- c.WithQuietOnError(quiet)
- }
-}
diff --git a/pkg/exec/scripts_run.go b/pkg/exec/scripts_run.go
deleted file mode 100644
index db243a9..0000000
--- a/pkg/exec/scripts_run.go
+++ /dev/null
@@ -1,155 +0,0 @@
-package exec
-
-import (
- "os"
- "runtime"
- "strings"
-)
-
-// InvokeShellScripts invokes a shell script fragments with internal
-// invoker (typically it's hedzr/log.exec.Run).
-//
-// InvokeShellScripts finds and prepares the proper shell (bash, or
-// powershell, etc.), and call it by invoker.
-//
-// The invoker can be customized by yours, use WithScriptInvoker.
-func InvokeShellScripts(scripts string, opts ...ISSOpt) (err error) {
- return invokeShellScripts(scripts, opts...)
-}
-
-type issCtx struct {
- knownShell string
- invoker func(command string, args ...string) (err error)
- isFile bool
- delayedOpts []func(c *issCtx) // not yet
- expander func(source string) string
- // cmd *CmdS
- // args []string
-}
-
-type ISSOpt func(c *issCtx)
-
-// WithScriptShell provides a predefined shell executable (short if it's
-// in $PATH, or full-path by you risks).
-//
-// The knownShell looks like shebang.
-// Such as: '/bin/bash', or '/usr/bin/env bash', ...
-func WithScriptShell(knownShell string) ISSOpt {
- return func(c *issCtx) {
- c.knownShell = knownShell
- }
-}
-
-// // WithCmdrEnviron provides the current command hit with its args.
-// // Its generally come from cmdr.CmdS.Action of a cmdr CmdS.
-// func WithCmdrEnviron(cmd *CmdS, args []string) ISSOpt {
-// return func(c *issCtx) {
-// c.cmd, c.args = cmd, args
-// }
-// }
-
-// WithScriptInvoker provides a custom runner to run the shell and scripts.
-//
-// The default is exec.Run in hedzr/log package.
-//
-// For example:
-//
-// err = InvokeShellScripts("ls -l /",
-// WithScriptShell("/bin/bash"),
-// WithScriptIsFile(false),
-// WithScriptInvoker(func(command string, args ...string) (err error) {
-// err = exec.New().
-// WithCommandArgs(command, args...).
-// WithOnOK(func(retCode int, stdoutText string) {
-// t.Logf("%v", LeftPad(stdoutText, 4))
-// }).
-// RunAndCheckError()
-// return
-// }),
-// )
-// if err != nil {
-// t.Errorf("%v", err)
-// }
-func WithScriptInvoker(invoker func(command string, args ...string) (err error)) ISSOpt {
- return func(c *issCtx) {
- c.invoker = invoker
- }
-}
-
-// WithScriptExpander providers a string expander for the given script.
-//
-// You may specify a special one (such as os.ExpandEnv) rather than
-// internal default (a dummy functor to return the source directly).
-func WithScriptExpander(expander func(source string) string) ISSOpt {
- return func(c *issCtx) {
- c.expander = expander
- }
-}
-
-// WithScriptIsFile provides a bool flag for flagging the given
-// scripts is a shell scripts fragments or a file.
-func WithScriptIsFile(isFile bool) ISSOpt {
- return func(c *issCtx) {
- c.isFile = isFile
- }
-}
-
-func invokeShellScripts(scripts string, opts ...ISSOpt) (err error) {
-
- var c issCtx
-
- for _, opt := range opts {
- opt(&c)
- }
-
- var a []string
-
- if c.knownShell == "" {
- if runtime.GOOS == "windows" {
- c.knownShell = "powershell.exe"
- } else {
- c.knownShell = "/bin/bash"
- }
- } else if strings.Contains(c.knownShell, "/env ") {
- cc := strings.Split(c.knownShell, " ")
- c.knownShell, a = cc[0], append(a, cc[1:]...)
- }
-
- var scriptFragments string
- // if c.cmd != nil {
- // scriptFragments = internalGetWorker().expandTmplWithExecutiveEnv(scripts, c.cmd, c.args)
- // } else {
- // scriptFragments = scripts
- // }
- if c.expander == nil {
- c.expander = os.ExpandEnv
- }
- scriptFragments = c.expander(scripts)
-
- for _, opt := range c.delayedOpts {
- opt(&c)
- }
-
- if strings.Contains(c.knownShell, "powershell") {
- a = append(a, "-NoProfile", "-NonInteractive")
- if c.isFile {
- a = append(a, "-File", scriptFragments)
- } else {
- a = append(a, "-CmdS", scriptFragments)
- }
- } else {
- if c.isFile {
- a = append(a, scriptFragments)
- } else {
- a = append(a, "-c", scriptFragments)
- }
- }
-
- if c.invoker == nil {
- c.invoker = Run
- }
-
- err = c.invoker(c.knownShell, a...)
-
- return
-}
diff --git a/pkg/exec/scripts_run_test.go b/pkg/exec/scripts_run_test.go
deleted file mode 100644
index 810cce2..0000000
--- a/pkg/exec/scripts_run_test.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package exec
-
-import (
- "os"
- "runtime"
- "testing"
-)
-
-func TestScriptsRun(t *testing.T) {
- if runtime.GOOS == "linux" || runtime.GOOS == "darwin" {
-
- var err error
-
- err = InvokeShellScripts("ls -l /",
- WithScriptShell("/bin/bash"),
- WithScriptIsFile(false),
- WithScriptInvoker(Run),
- WithScriptExpander(os.ExpandEnv),
- )
- if err != nil {
- t.Errorf("%v", err)
- }
-
- err = InvokeShellScripts("ls -l /",
- WithScriptShell("/bin/bash"),
- WithScriptIsFile(false),
- WithScriptInvoker(func(command string, args ...string) (err error) {
- err = New().
- WithCommandArgs(command, args...).
- WithOnOK(func(retCode int, stdoutText string) {
- t.Logf("%v", LeftPad(stdoutText, 4))
- }).
- RunAndCheckError()
- return
- }),
- )
- if err != nil {
- t.Errorf("%v", err)
- }
-
- }
-}
diff --git a/pkg/exec/sudo.go b/pkg/exec/sudo.go
deleted file mode 100644
index 9d4a94c..0000000
--- a/pkg/exec/sudo.go
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright © 2020 Hedzr Yeh.
-
-package exec
-
-import (
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "os/exec"
- "sync"
- "syscall"
-
- "gopkg.in/hedzr/errors.v3"
-
- "github.com/hedzr/is"
-)
-
-// Run runs an OS command
-func Run(command string, arguments ...string) (err error) {
- _, _, err = RunCommand(command, false, arguments...)
- return
-}
-
-// Sudo runs an OS command with sudo prefix
-func Sudo(command string, arguments ...string) (retCode int, stdoutText string, err error) {
- if is.Root() {
- retCode, stdoutText, err = RunCommand(command, true, arguments...)
- return
- }
-
- var sudocmd string
- sudocmd, err = exec.LookPath("sudo")
- if err != nil {
- return -1, "'sudo' not found", Run(command, arguments...)
- }
-
- retCode, stdoutText, err = RunCommand(sudocmd, true, append([]string{command}, arguments...)...)
- return
-}
-
-// RunWithOutput runs an OS command and collect the result outputting
-func RunWithOutput(command string, arguments ...string) (retCode int, stdoutText string, err error) {
- return RunCommand(command, true, arguments...)
-}
-
-// RunCommand runs an OS command and return outputs
-func RunCommand(command string, readStdout bool, arguments ...string) (retCode int, stdoutText string, err error) {
- var errText string
- retCode, stdoutText, errText, err = RunCommandFull(command, readStdout, arguments...)
- if errText != "" {
- stdoutText += errText
- }
- return
-}
-
-// RunCommandFull runs an OS command and return the all outputs
-func RunCommandFull(command string, readStdout bool, arguments ...string) (retCode int, stdoutText, stderrText string, err error) {
- cmd := exec.Command(command, arguments...)
-
- var stdout io.ReadCloser
- var stderr io.ReadCloser
- var output, slurp bytes.Buffer
- var wg sync.WaitGroup
-
- if readStdout {
- // Connect pipe to read Stdout
- stdout, err = cmd.StdoutPipe()
- if err != nil {
- // Failed to connect pipe
- return 0, "", "", fmt.Errorf("%q failed to connect stdout pipe: %v", command, err)
- }
-
- defer stdout.Close()
- wg.Add(1)
- go func() {
- defer wg.Done()
- _, _ = io.Copy(&output, stdout)
- }()
-
- } else {
- cmd.Stdout = os.Stdout
- // cmd.Stderr = os.Stderr
- }
-
- // Connect pipe to read Stderr
- stderr, err = cmd.StderrPipe()
- if err != nil {
- // Failed to connect pipe
- return 0, "", "", fmt.Errorf("%q failed to connect stderr pipe: %v", command, err)
- }
-
- defer stderr.Close()
-
- wg.Add(1)
- go func() {
- defer wg.Done()
- _, _ = io.Copy(&slurp, stderr)
- }()
-
- // Do not use cmd.Run()
- if err = cmd.Start(); err != nil {
- // Problem while copying stdin, stdout, or stderr
- return 0, "", "", fmt.Errorf("%q failed: %v", command, err)
- }
-
- // Zero exit status
- // Darwin: launchctl can fail with a zero exit status,
- // so check for emtpy stderr
- if command == "launchctl" {
- slurpText, _ := ioutil.ReadAll(stderr)
- if len(slurpText) > 0 && !bytes.HasSuffix(slurpText, []byte("Operation now in progress\n")) {
- return 0, "", "", fmt.Errorf("%q failed with stderr: %s", command, slurpText)
- }
- }
-
- // slurp, _ := ioutil.ReadAll(stderr)
-
- wg.Wait()
-
- if err = cmd.Wait(); err != nil {
- exitStatus, ok := IsExitError(err)
- if ok {
- // CmdS didn't exit with a zero exit status.
- return exitStatus, output.String(), slurp.String(), errors.New("%q failed with stderr:\n%v\n ", command, slurp.String()).WithErrors(err)
- }
-
- // An error occurred and there is no exit status.
- // return 0, output, fmt.Errorf("%q failed: %v |\n stderr: %s", command, err.Error(), slurp)
- return 0, output.String(), slurp.String(), errors.New("%q failed with stderr:\n%v\n ", command, slurp.String()).WithErrors(err)
- }
-
- // if readStdout {
- // var out []byte
- // out, err = ioutil.ReadAll(stdout)
- // if err != nil {
- // return 0, "", fmt.Errorf("%q failed while attempting to read stdout: %v", command, err)
- // } else if len(out) > 0 {
- // output = string(out)
- // }
- // }
-
- return 0, output.String(), slurp.String(), nil
-}
-
-// IsEAccess detects whether err is a EACCESS errno or not
-func IsEAccess(err error) bool {
- if e, ok := err.(*os.PathError); ok && e.Err == syscall.EACCES {
- return true
- }
- return false
-}
diff --git a/pkg/exec/sudo_nacl.go b/pkg/exec/sudo_nacl.go
deleted file mode 100644
index 1e5d30c..0000000
--- a/pkg/exec/sudo_nacl.go
+++ /dev/null
@@ -1,19 +0,0 @@
-//go:build nacl
-// +build nacl
-
-// Copyright © 2020 Hedzr Yeh.
-
-package exec
-
-import (
- "os/exec"
-)
-
-// IsExitError checks the error object
-func IsExitError(err error) (int, bool) {
- if ee, ok := err.(*exec.ExitError); ok {
- return ee.ExitCode(), true
- }
-
- return 0, false
-}
diff --git a/pkg/exec/sudo_others.go b/pkg/exec/sudo_others.go
deleted file mode 100644
index 788be5f..0000000
--- a/pkg/exec/sudo_others.go
+++ /dev/null
@@ -1,22 +0,0 @@
-//go:build !plan9 && !nacl
-// +build !plan9,!nacl
-
-// Copyright © 2020 Hedzr Yeh.
-
-package exec
-
-import (
- "os/exec"
- "syscall"
-)
-
-// IsExitError checks the error object
-func IsExitError(err error) (int, bool) {
- if ee, ok := err.(*exec.ExitError); ok {
- if status, ok := ee.Sys().(syscall.WaitStatus); ok {
- return status.ExitStatus(), true
- }
- }
-
- return 0, false
-}
diff --git a/pkg/exec/sudo_plan9.go b/pkg/exec/sudo_plan9.go
deleted file mode 100644
index fee9566..0000000
--- a/pkg/exec/sudo_plan9.go
+++ /dev/null
@@ -1,19 +0,0 @@
-//go:build plan9
-// +build plan9
-
-// Copyright © 2020 Hedzr Yeh.
-
-package exec
-
-import (
- "os/exec"
-)
-
-// IsExitError checks the error object
-func IsExitError(err error) (int, bool) {
- if ee, ok := err.(*exec.ExitError); ok {
- return ee.ExitCode(), true
- }
-
- return 0, false
-}
diff --git a/pkg/exec/sudo_test.go b/pkg/exec/sudo_test.go
deleted file mode 100644
index 5904c1b..0000000
--- a/pkg/exec/sudo_test.go
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright © 2020 Hedzr Yeh.
-
-package exec
-
-import (
- "io"
- "io/ioutil"
- "os"
- "os/exec"
- "runtime"
- "testing"
-)
-
-func TestRun(t *testing.T) {
- _ = Run("ls", "-a")
- _, _, _ = Sudo("ls", "-a")
-}
-
-func TestRunWithOutput(t *testing.T) {
- _, out, err := RunWithOutput("ls", "-la", "/not-exits")
- t.Logf("stdout: %v", out)
- t.Logf("stderr: %v", err)
-}
-
-func TestRunCommand(t *testing.T) {
- cmd := exec.Command("ls", "-lah", "/not-exits")
- if runtime.GOOS == "windows" {
- cmd = exec.Command("tasklist")
- }
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- err := cmd.Run()
- if err != nil {
- t.Logf("cmd.Run() failed with %s\n", err)
- }
-}
-
-func TestCombineOutputs(t *testing.T) {
- cmd := exec.Command("ls", "-lah")
- out, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("cmd.Run() failed with %s\n%s", err, out)
- }
- t.Logf("combined out:\n%s\n", string(out))
-}
-
-func TestAlone(t *testing.T) {
- var stdout io.ReadCloser
- var stderr io.ReadCloser
- var err error
- cmd := exec.Command("ls", "-lah", "/not-exits")
- stderr, err = cmd.StderrPipe()
- if err != nil {
- t.Fatal(err)
- }
- // var errBuffer bytes.Buffer
- // cmd.Stderr = &errBuffer
- stdout, err = cmd.StdoutPipe()
- if err != nil {
- t.Fatal(err)
- }
- err = cmd.Start()
- if err != nil {
- t.Fatal(err)
- }
-
- slurp, _ := ioutil.ReadAll(stderr)
- // fmt.Printf("%s\n", slurp)
-
- err = cmd.Wait()
- if err != nil {
- // var sb bytes.Buffer
- // in := bufio.NewScanner(stderr)
- // for in.Scan() {
- // sb.Write(in.Bytes())
- // }
- t.Logf("cmd.Run() failed with %s\n%s", err, slurp)
- }
- out, _ := ioutil.ReadAll(stdout)
- t.Logf(" output:\n%s\n", string(out))
-}
diff --git a/pkg/exec/tool.go b/pkg/exec/tool.go
deleted file mode 100644
index b3d00f1..0000000
--- a/pkg/exec/tool.go
+++ /dev/null
@@ -1,218 +0,0 @@
-package exec
-
-import (
- "bufio"
- "fmt"
- "os/exec"
- "strings"
- "unicode/utf8"
-)
-
-// LookPath searches for an executable named file in the
-// directories named by the PATH environment variable.
-// If file contains a slash, it is tried directly and the PATH is not consulted.
-// The result may be an absolute path or a path relative to the current directory.
-func LookPath(file string) (string, error) {
- return exec.LookPath(file)
-}
-
-func toStringSimple(i interface{}) string {
- return fmt.Sprintf("%v", i)
-}
-
-// StripLeftTabs removes the padding tabs at left margin.
-// The least tab chars will be erased at left side of lines, and the
-// tab chars beyond the least at left will be kept.
-func StripLeftTabs(s string) string { return stripLeftTabs(s) }
-
-func stripLeftTabs(s string) string {
- var lines []string
- var tabs int = 1000
- var emptyLines []int
- var sb strings.Builder
- var line int
- var noLastLF bool = !strings.HasSuffix(s, "\n")
-
- scanner := bufio.NewScanner(bufio.NewReader(strings.NewReader(s)))
- for scanner.Scan() {
- str := scanner.Text()
- i, n, allTabs := 0, len(str), true
- for ; i < n; i++ {
- if str[i] != '\t' {
- allTabs = false
- if tabs > i && i > 0 {
- tabs = i
- break
- }
- }
- }
- if i == n && allTabs {
- emptyLines = append(emptyLines, line)
- }
- lines = append(lines, str)
- line++
- }
-
- pad := strings.Repeat("\t", tabs)
- for i, str := range lines {
- if strings.HasPrefix(str, pad) {
- sb.WriteString(str[tabs:])
- } else if inIntSlice(i, emptyLines) {
- } else {
- sb.WriteString(str)
- }
- if noLastLF && i == len(lines)-1 {
- break
- }
- sb.WriteRune('\n')
- }
-
- return sb.String()
-}
-
-func inIntSlice(i int, slice []int) bool {
- for _, n := range slice {
- if n == i {
- return true
- }
- }
- return false
-}
-
-// LeftPad inserts spaces at beginning of each line
-func LeftPad(s string, pad int) string { return leftPad(s, pad) }
-
-func leftPad(s string, pad int) string {
- if pad <= 0 {
- return s
- }
-
- var sb strings.Builder
- padStr := strings.Repeat(" ", pad)
- scanner := bufio.NewScanner(bufio.NewReader(strings.NewReader(s)))
- for scanner.Scan() {
- sb.WriteString(padStr)
- sb.WriteString(scanner.Text())
- sb.WriteRune('\n')
- }
- return sb.String()
-}
-
-// StripHtmlTags aggressively strips HTML tags from a string.
-// It will only keep anything between `>` and `<`.
-func StripHtmlTags(s string) string { return stripHtmlTags(s) }
-
-const (
- htmlTagStart = 60 // Unicode `<`
- htmlTagEnd = 62 // Unicode `>`
-)
-
-// Aggressively strips HTML tags from a string.
-// It will only keep anything between `>` and `<`.
-func stripHtmlTags(s string) string {
- // Setup a string builder and allocate enough memory for the new string.
- var builder strings.Builder
- builder.Grow(len(s) + utf8.UTFMax)
-
- in := false // True if we are inside an HTML tag.
- start := 0 // The index of the previous start tag character `<`
- end := 0 // The index of the previous end tag character `>`
-
- for i, c := range s {
- // If this is the last character and we are not in an HTML tag, save it.
- if (i+1) == len(s) && end >= start {
- builder.WriteString(s[end:])
- }
-
- // Keep going if the character is not `<` or `>`
- if c != htmlTagStart && c != htmlTagEnd {
- continue
- }
-
- if c == htmlTagStart {
- // Only update the start if we are not in a tag.
- // This make sure we strip out `<
` not just `
`
- if !in {
- start = i
- }
- in = true
-
- // Write the valid string between the close and start of the two tags.
- builder.WriteString(s[end:start])
- continue
- }
- // else c == htmlTagEnd
- in = false
- end = i + 1
- }
- s = builder.String()
- return s
-}
-
-// StripQuotes strips first and last quote char (double quote or single quote).
-func StripQuotes(s string) string { return trimQuotes(s) }
-
-// TrimQuotes strips first and last quote char (double quote or single quote).
-func TrimQuotes(s string) string { return trimQuotes(s) }
-
-// func trimQuotes(s string) string {
-// if len(s) >= 2 {
-// if c := s[len(s)-1]; s[0] == c && (c == '"' || c == '\'') {
-// return s[1 : len(s)-1]
-// }
-// }
-// return s
-// }
-
-func trimQuotes(s string) string {
- switch {
- case s[0] == '\'':
- if s[len(s)-1] == '\'' {
- return s[1 : len(s)-1]
- }
- return s[1:]
- case s[0] == '"':
- if s[len(s)-1] == '"' {
- return s[1 : len(s)-1]
- }
- return s[1:]
- case s[len(s)-1] == '\'':
- return s[0 : len(s)-1]
- case s[len(s)-1] == '"':
- return s[0 : len(s)-1]
- }
- return s
-}
-
-// SplitCommandString allows split command-line by quote
-// characters (default is double-quote).
-//
-// In: `bash -c 'echo hello world!'`
-// Out: []string{ "bash", "-c", "echo hello world!"}
-func SplitCommandString(s string, quoteChars ...rune) []string {
- var qc rune = '"'
- var m = map[rune]bool{qc: true}
- for _, q := range quoteChars {
- qc, m[q] = q, true //nolint:ineffassign
- }
-
- quoted, ch := false, rune(0)
-
- a := strings.FieldsFunc(s, func(r rune) bool {
- if ch == 0 {
- if _, ok := m[r]; ok {
- quoted, ch = !quoted, r
- }
- } else if ch == r {
- quoted, ch = !quoted, r
- }
- return !quoted && r == ' '
- })
-
- var b []string
- for _, s := range a {
- b = append(b, trimQuotes(s))
- }
-
- return b
-}
diff --git a/pkg/exec/tool_test.go b/pkg/exec/tool_test.go
deleted file mode 100644
index 1eeabb9..0000000
--- a/pkg/exec/tool_test.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package exec
-
-import "testing"
-
-func TestSplitCommandString(t *testing.T) {
- in := `bash -c 'echo hello world!'`
- out := SplitCommandString(in, '"', '\'')
- t.Log(out)
-}