2024-06-23 13:35:02 -07:00
|
|
|
// Package execute is a simple package that wraps the os/exec Command features
|
|
|
|
// for convenient use in asdf. It was inspired by
|
|
|
|
// https://github.com/chen-keinan/go-command-eval
|
|
|
|
package execute
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os/exec"
|
2024-07-03 17:27:13 -07:00
|
|
|
"strings"
|
2024-06-23 13:35:02 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
// Command represents a Bash command that can be executed by asdf
|
|
|
|
type Command struct {
|
2024-07-03 17:27:13 -07:00
|
|
|
Command string
|
|
|
|
Expression string
|
|
|
|
Args []string
|
|
|
|
Stdin io.Reader
|
|
|
|
Stdout io.Writer
|
|
|
|
Stderr io.Writer
|
|
|
|
Env map[string]string
|
2024-06-23 13:35:02 -07:00
|
|
|
}
|
|
|
|
|
2024-07-03 17:27:13 -07:00
|
|
|
// New takes a string containing the path to a Bash script, and a slice of
|
|
|
|
// string arguments and returns a Command struct
|
2024-06-23 13:35:02 -07:00
|
|
|
func New(command string, args []string) Command {
|
|
|
|
return Command{Command: command, Args: args}
|
|
|
|
}
|
|
|
|
|
2024-07-03 17:27:13 -07:00
|
|
|
// NewExpression takes a string containing a Bash expression and a slice of
|
|
|
|
// string arguments and returns a Command struct
|
|
|
|
func NewExpression(expression string, args []string) Command {
|
|
|
|
return Command{Expression: expression, Args: args}
|
|
|
|
}
|
|
|
|
|
2024-06-23 13:35:02 -07:00
|
|
|
// Run executes a Command with Bash and returns the error if there is one
|
|
|
|
func (c Command) Run() error {
|
2024-07-03 17:27:13 -07:00
|
|
|
var command string
|
|
|
|
if c.Expression != "" {
|
|
|
|
// Expressions need to be invoked inside a Bash function, so variables like
|
|
|
|
// $0 and $@ are available
|
|
|
|
command = fmt.Sprintf("fn() { %s; }; fn %s", c.Expression, formatArgString(c.Args))
|
|
|
|
} else {
|
|
|
|
// Scripts can be invoked directly, with args provided
|
|
|
|
command = fmt.Sprintf("%s %s", c.Command, formatArgString(c.Args))
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd := exec.Command("bash", "-c", command)
|
2024-06-23 13:35:02 -07:00
|
|
|
|
|
|
|
cmd.Env = mapToSlice(c.Env)
|
|
|
|
cmd.Stdin = c.Stdin
|
|
|
|
|
|
|
|
// Capture stdout and stderr
|
|
|
|
cmd.Stdout = c.Stdout
|
|
|
|
cmd.Stderr = c.Stderr
|
|
|
|
|
|
|
|
return cmd.Run()
|
|
|
|
}
|
|
|
|
|
2024-07-03 17:27:13 -07:00
|
|
|
func formatArgString(args []string) string {
|
|
|
|
var newArgs []string
|
|
|
|
for _, str := range args {
|
|
|
|
newArgs = append(newArgs, fmt.Sprintf("\"%s\"", str))
|
|
|
|
}
|
|
|
|
return strings.Join(newArgs, " ")
|
|
|
|
}
|
|
|
|
|
2024-06-23 13:35:02 -07:00
|
|
|
func mapToSlice(env map[string]string) (slice []string) {
|
|
|
|
for key, value := range env {
|
|
|
|
slice = append(slice, fmt.Sprintf("%s=%s", key, value))
|
|
|
|
}
|
|
|
|
|
|
|
|
return slice
|
|
|
|
}
|