feat(golang-rewrite): create asdf exec command

* Add `rogpeppe/go-internal` as a dependency
* Create `exec.Exec` function
* Create asdf exec command
* Address linter warnings
This commit is contained in:
Trevor Brown 2024-09-12 09:02:59 -04:00
parent 05b9c37232
commit b966ca6627
6 changed files with 99 additions and 0 deletions

View File

@ -10,6 +10,7 @@ import (
"strings" "strings"
"asdf/internal/config" "asdf/internal/config"
"asdf/internal/exec"
"asdf/internal/info" "asdf/internal/info"
"asdf/internal/installs" "asdf/internal/installs"
"asdf/internal/plugins" "asdf/internal/plugins"
@ -44,6 +45,15 @@ func Execute(version string) {
Usage: "The multiple runtime version manager", Usage: "The multiple runtime version manager",
UsageText: usageText, UsageText: usageText,
Commands: []*cli.Command{ Commands: []*cli.Command{
{
Name: "exec",
Action: func(cCtx *cli.Context) error {
command := cCtx.Args().Get(0)
args := cCtx.Args().Slice()
return execCommand(logger, command, args)
},
},
{ {
Name: "info", Name: "info",
Action: func(_ *cli.Context) error { Action: func(_ *cli.Context) error {
@ -159,6 +169,43 @@ func Execute(version string) {
} }
} }
func execCommand(logger *log.Logger, command string, args []string) error {
if command == "" {
logger.Printf("no command specified")
return fmt.Errorf("no command specified")
}
conf, err := config.LoadConfig()
if err != nil {
logger.Printf("error loading config: %s", err)
return err
}
currentDir, err := os.Getwd()
if err != nil {
logger.Printf("unable to get current directory: %s", err)
return err
}
executable, found, err := shims.FindExecutable(conf, command, currentDir)
if err != nil {
logger.Printf("executable not found due to reason: %s", err.Error())
return err
}
if !found {
logger.Print("executable not found")
return fmt.Errorf("executable not found")
}
if len(args) > 1 {
args = args[1:]
} else {
args = []string{}
}
return exec.Exec(executable, args, os.Environ())
}
func pluginAddCommand(_ *cli.Context, conf config.Config, logger *log.Logger, pluginName, pluginRepo string) error { func pluginAddCommand(_ *cli.Context, conf config.Config, logger *log.Logger, pluginName, pluginRepo string) error {
if pluginName == "" { if pluginName == "" {
// Invalid arguments // Invalid arguments

1
go.mod
View File

@ -6,6 +6,7 @@ require (
github.com/go-git/go-git/v5 v5.11.0 github.com/go-git/go-git/v5 v5.11.0
github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir v1.1.0
github.com/otiai10/copy v1.14.0 github.com/otiai10/copy v1.14.0
github.com/rogpeppe/go-internal v1.11.0
github.com/sethvargo/go-envconfig v1.0.0 github.com/sethvargo/go-envconfig v1.0.0
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/urfave/cli/v2 v2.27.1 github.com/urfave/cli/v2 v2.27.1

12
internal/exec/exec.go Normal file
View File

@ -0,0 +1,12 @@
// Package exec handles replacing the asdf go process with
package exec
import (
"syscall"
)
// Exec invokes syscall.Exec to exec an executable. Requires an absolute path to
// executable.
func Exec(executablePath string, args []string, env []string) error {
return syscall.Exec(executablePath, append([]string{executablePath}, args...), env)
}

View File

@ -0,0 +1,34 @@
package exec
import (
"fmt"
"os"
"os/exec"
"testing"
"github.com/rogpeppe/go-internal/testscript"
)
func execit() int {
// Exec only works with absolute path
cmdPath, _ := exec.LookPath(os.Args[1])
err := Exec(cmdPath, os.Args[2:], os.Environ())
if err != nil {
fmt.Printf("Err: %#+v\n", err.Error())
}
return 0
}
func TestMain(m *testing.M) {
os.Exit(testscript.RunMain(m, map[string]func() int{
"execit": execit,
}))
}
func TestExec(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testdata/script",
})
}

View File

@ -0,0 +1,3 @@
env ENV=foo
execit echo this is a $ENV
stdout 'this is a foo\n'

View File

@ -0,0 +1,2 @@
execit echo this is a test
stdout 'this is a test\n'