feat(golang-rewrite): implement asdf env command

* Create `CallbackPath` method on `Plugin` struct
* Correct behavior of `asdf shimversions` command
* Update `shims.FindExecutable` function to return plugin
* Create `repotest.WritePluginCallback` function
* Create `execenv` package for invoking `exec-env` plugin callback
* Make `MapToSlice` a public function
* Return resolved version from `shims.FindExecutable` function
* Create `shims.ExecutablePaths` function
* Enable `shim_env_command.bats` tests
* Implement `asdf env` command
This commit is contained in:
Trevor Brown 2024-11-24 11:00:40 -05:00
parent 0e43521ea7
commit 26a3815948
11 changed files with 390 additions and 59 deletions

View File

@ -7,6 +7,7 @@ import (
"io"
"log"
"os"
osexec "os/exec"
"path/filepath"
"slices"
"strings"
@ -14,9 +15,12 @@ import (
"asdf/internal/config"
"asdf/internal/exec"
"asdf/internal/execenv"
"asdf/internal/execute"
"asdf/internal/help"
"asdf/internal/info"
"asdf/internal/installs"
"asdf/internal/paths"
"asdf/internal/plugins"
"asdf/internal/resolve"
"asdf/internal/shims"
@ -59,6 +63,15 @@ func Execute(version string) {
return currentCommand(logger, tool)
},
},
{
Name: "env",
Action: func(cCtx *cli.Context) error {
shimmedCommand := cCtx.Args().Get(0)
args := cCtx.Args().Slice()
return envCommand(logger, shimmedCommand, args)
},
},
{
Name: "exec",
Action: func(cCtx *cli.Context) error {
@ -335,6 +348,83 @@ func formatVersions(versions []string) string {
}
}
func envCommand(logger *log.Logger, shimmedCommand string, args []string) error {
command := "env"
if shimmedCommand == "" {
logger.Printf("usage: asdf env <command>")
return fmt.Errorf("usage: asdf env <command>")
}
if len(args) >= 2 {
command = args[1]
}
realArgs := []string{}
if len(args) > 2 {
realArgs = args[2:]
}
conf, err := config.LoadConfig()
if err != nil {
logger.Printf("error loading config: %s", err)
return err
}
_, plugin, version, err := getExecutable(logger, conf, shimmedCommand)
if err != nil {
return err
}
parsedVersion := toolversions.Parse(version)
execPaths, err := shims.ExecutablePaths(conf, plugin, parsedVersion)
if err != nil {
return err
}
callbackEnv := map[string]string{
"ASDF_INSTALL_TYPE": parsedVersion.Type,
"ASDF_INSTALL_VERSION": parsedVersion.Value,
"ASDF_INSTALL_PATH": installs.InstallPath(conf, plugin, parsedVersion),
"PATH": setPath(conf, execPaths),
}
var env map[string]string
var fname string
if parsedVersion.Type == "system" {
env = execute.SliceToMap(os.Environ())
newPath := paths.RemoveFromPath(env["PATH"], shims.Directory(conf))
env["PATH"] = newPath
var found bool
fname, found = shims.FindSystemExecutable(conf, command)
if !found {
fmt.Println("not found")
return err
}
} else {
env, err = execenv.Generate(plugin, callbackEnv)
if _, ok := err.(plugins.NoCallbackError); !ok && err != nil {
return err
}
fname, err = osexec.LookPath(command)
if err != nil {
return err
}
}
err = exec.Exec(fname, realArgs, execute.MapToSlice(env))
if err != nil {
fmt.Printf("err %#+v\n", err.Error())
}
return err
}
func setPath(conf config.Config, pathes []string) string {
currentPath := os.Getenv("PATH")
return strings.Join(pathes, ":") + ":" + paths.RemoveFromPath(currentPath, shims.Directory(conf))
}
func execCommand(logger *log.Logger, command string, args []string) error {
if command == "" {
logger.Printf("usage: asdf exec <command>")
@ -347,16 +437,51 @@ func execCommand(logger *log.Logger, command string, args []string) error {
return err
}
currentDir, err := os.Getwd()
executable, plugin, version, err := getExecutable(logger, conf, command)
fmt.Printf("version %#+v\n", version)
fmt.Println("here")
if err != nil {
logger.Printf("unable to get current directory: %s", err)
return err
}
executable, found, err := shims.FindExecutable(conf, command, currentDir)
if len(args) > 1 {
args = args[1:]
} else {
args = []string{}
}
parsedVersion := toolversions.Parse(version)
fmt.Printf("parsedVersion %#+v\n", parsedVersion)
paths, err := shims.ExecutablePaths(conf, plugin, parsedVersion)
if err != nil {
return err
}
callbackEnv := map[string]string{
"ASDF_INSTALL_TYPE": parsedVersion.Type,
"ASDF_INSTALL_VERSION": parsedVersion.Value,
"ASDF_INSTALL_PATH": installs.InstallPath(conf, plugin, parsedVersion),
"PATH": setPath(conf, paths),
}
env, _ := execenv.Generate(plugin, callbackEnv)
return exec.Exec(executable, args, execute.MapToSlice(env))
}
func getExecutable(logger *log.Logger, conf config.Config, command string) (executable string, plugin plugins.Plugin, version string, err error) {
currentDir, err := os.Getwd()
if err != nil {
logger.Printf("unable to get current directory: %s", err)
return "", plugins.Plugin{}, "", err
}
executable, plugin, version, found, err := shims.FindExecutable(conf, command, currentDir)
if err != nil {
if _, ok := err.(shims.NoExecutableForPluginError); ok {
logger.Printf("No executable %s found for current version. Please select a different version or install %s manually for the current version", command, command)
os.Exit(1)
return "", plugin, version, err
}
shimPath := shims.Path(conf, command)
toolVersions, _ := shims.GetToolsAndVersionsFromShimFile(shimPath)
@ -383,21 +508,16 @@ func execCommand(logger *log.Logger, command string, args []string) error {
}
os.Exit(126)
return err
return executable, plugins.Plugin{}, "", err
}
if !found {
logger.Print("executable not found")
os.Exit(126)
return fmt.Errorf("executable not found")
}
if len(args) > 1 {
args = args[1:]
} else {
args = []string{}
return executable, plugins.Plugin{}, "", fmt.Errorf("executable not found")
}
return exec.Exec(executable, args, os.Environ())
return executable, plugin, version, nil
}
func anyInstalled(conf config.Config, toolVersions []toolversions.ToolVersions) bool {
@ -842,6 +962,11 @@ func reshimCommand(logger *log.Logger, tool, version string) (err error) {
}
func shimVersionsCommand(logger *log.Logger, shimName string) error {
if shimName == "" {
logger.Printf("usage: asdf shimversions <command>")
return fmt.Errorf("usage: asdf shimversions <command>")
}
conf, err := config.LoadConfig()
if err != nil {
logger.Printf("error loading config: %s", err)
@ -852,7 +977,7 @@ func shimVersionsCommand(logger *log.Logger, shimName string) error {
toolVersions, err := shims.GetToolsAndVersionsFromShimFile(shimPath)
for _, toolVersion := range toolVersions {
for _, version := range toolVersion.Versions {
fmt.Printf("%s %s", toolVersion.Name, version)
fmt.Printf("%s %s\n", toolVersion.Name, version)
}
}
return err
@ -877,7 +1002,7 @@ func whichCommand(logger *log.Logger, command string) error {
return errors.New("must provide command")
}
path, _, err := shims.FindExecutable(conf, command, currentDir)
path, _, _, _, err := shims.FindExecutable(conf, command, currentDir)
if _, ok := err.(shims.UnknownCommandError); ok {
logger.Printf("unknown command: %s. Perhaps you have to reshim?", command)
return errors.New("command not found")

View File

@ -20,6 +20,7 @@ versions are supported. The affected commands:
* `asdf plugin-list-all` -> `asdf plugin list all`
* `asdf plugin-update` -> `asdf plugin update`
* `asdf plugin-remove` -> `asdf plugin remove`
* `asdf shim-versions` -> `asdf shimversions`
### `asdf global` and `asdf local` commands have been replaced by the `asdf set` command

View File

@ -0,0 +1,49 @@
// Package execenv contains logic for generating execution environing using a plugin's
// exec-env callback script if available.
package execenv
import (
"fmt"
"strings"
"asdf/internal/execute"
"asdf/internal/plugins"
)
const execEnvCallbackName = "exec-env"
// Generate runs exec-env callback if available and captures the environment
// variables it sets. It then parses them and returns them as a map.
func Generate(plugin plugins.Plugin, callbackEnv map[string]string) (env map[string]string, err error) {
execEnvPath, err := plugin.CallbackPath(execEnvCallbackName)
if err != nil {
return callbackEnv, err
}
var stdout strings.Builder
// This is done to support the legacy behavior. exec-env is the only asdf
// callback that works by exporting environment variables. Because of this,
// executing the callback isn't enough. We actually need to source it (.) so
// the environment variables get set, and then run `env` so they get printed
// to STDOUT.
expression := execute.NewExpression(fmt.Sprintf(". \"%s\"; env", execEnvPath), []string{})
expression.Env = callbackEnv
expression.Stdout = &stdout
err = expression.Run()
return envMap(stdout.String()), err
}
func envMap(env string) map[string]string {
slice := map[string]string{}
for _, envVar := range strings.Split(env, "\n") {
varValue := strings.Split(envVar, "=")
if len(varValue) == 2 {
slice[varValue[0]] = varValue[1]
}
}
return slice
}

View File

@ -0,0 +1,43 @@
package execenv
import (
"testing"
"asdf/internal/config"
"asdf/internal/plugins"
"asdf/repotest"
"github.com/stretchr/testify/assert"
)
const (
testPluginName = "lua"
testPluginName2 = "ruby"
)
func TestGenerate(t *testing.T) {
testDataDir := t.TempDir()
t.Run("returns map of environment variables", func(t *testing.T) {
conf := config.Config{DataDir: testDataDir}
_, err := repotest.InstallPlugin("dummy_plugin", testDataDir, testPluginName)
assert.Nil(t, err)
plugin := plugins.New(conf, testPluginName)
assert.Nil(t, repotest.WritePluginCallback(plugin.Dir, "exec-env", "#!/usr/bin/env bash\nexport BAZ=bar"))
env, err := Generate(plugin, map[string]string{"ASDF_INSTALL_VERSION": "test"})
assert.Nil(t, err)
assert.Equal(t, "bar", env["BAZ"])
assert.Equal(t, "test", env["ASDF_INSTALL_VERSION"])
})
t.Run("returns error when plugin lacks exec-env callback", func(t *testing.T) {
conf := config.Config{DataDir: testDataDir}
_, err := repotest.InstallPlugin("dummy_plugin", testDataDir, testPluginName2)
assert.Nil(t, err)
plugin := plugins.New(conf, testPluginName2)
env, err := Generate(plugin, map[string]string{})
assert.Equal(t, err.(plugins.NoCallbackError).Error(), "Plugin named ruby does not have a callback named exec-env")
_, found := env["FOO"]
assert.False(t, found)
})
}

View File

@ -47,7 +47,7 @@ func (c Command) Run() error {
cmd := exec.Command("bash", "-c", command)
cmd.Env = mapToSlice(c.Env)
cmd.Env = MapToSlice(c.Env)
cmd.Stdin = c.Stdin
// Capture stdout and stderr
@ -57,6 +57,29 @@ func (c Command) Run() error {
return cmd.Run()
}
// MapToSlice converts an env map to env slice suitable for syscall.Exec
func MapToSlice(env map[string]string) (slice []string) {
for key, value := range env {
slice = append(slice, fmt.Sprintf("%s=%s", key, value))
}
return slice
}
// SliceToMap converts an env map to env slice suitable for syscall.Exec
func SliceToMap(env []string) map[string]string {
envMap := map[string]string{}
for _, envVar := range env {
varValue := strings.Split(envVar, "=")
if len(varValue) == 2 {
envMap[varValue[0]] = varValue[1]
}
}
return envMap
}
func formatArgString(args []string) string {
var newArgs []string
for _, str := range args {
@ -64,11 +87,3 @@ func formatArgString(args []string) string {
}
return strings.Join(newArgs, " ")
}
func mapToSlice(env map[string]string) (slice []string) {
for key, value := range env {
slice = append(slice, fmt.Sprintf("%s=%s", key, value))
}
return slice
}

View File

@ -154,11 +154,9 @@ func (p Plugin) Exists() error {
// RunCallback invokes a callback with the given name if it exists for the plugin
func (p Plugin) RunCallback(name string, arguments []string, environment map[string]string, stdOut io.Writer, errOut io.Writer) error {
callback := filepath.Join(p.Dir, "bin", name)
_, err := os.Stat(callback)
if errors.Is(err, os.ErrNotExist) {
return NoCallbackError{callback: name, plugin: p.Name}
callback, err := p.CallbackPath(name)
if err != nil {
return err
}
cmd := execute.New(fmt.Sprintf("'%s'", callback), arguments)
@ -170,6 +168,17 @@ func (p Plugin) RunCallback(name string, arguments []string, environment map[str
return cmd.Run()
}
// CallbackPath returns the full file path to a callback script
func (p Plugin) CallbackPath(name string) (string, error) {
path := filepath.Join(p.Dir, "bin", name)
_, err := os.Stat(path)
if errors.Is(err, os.ErrNotExist) {
return "", NoCallbackError{callback: name, plugin: p.Name}
}
return path, nil
}
// List takes config and flags for what to return and builds a list of plugins
// representing the currently installed plugins on the system.
func List(config config.Config, urls, refs bool) (plugins []Plugin, err error) {

View File

@ -183,7 +183,7 @@ func TestRemove(t *testing.T) {
t.Run("returns error when plugin with name does not exist", func(t *testing.T) {
var stdout strings.Builder
var stderr strings.Builder
err := Remove(conf, "nonexistant", &stdout, &stderr)
err := Remove(conf, "nonexistent", &stdout, &stderr)
assert.NotNil(t, err)
assert.ErrorContains(t, err, "No such plugin")
})
@ -251,10 +251,10 @@ func TestUpdate(t *testing.T) {
{
desc: "returns error when plugin with name does not exist",
givenConf: conf,
givenName: "nonexistant",
givenName: "nonexistent",
givenRef: "",
wantSomeRef: false,
wantErrMsg: "no such plugin: nonexistant",
wantErrMsg: "no such plugin: nonexistent",
},
{
desc: "returns error when plugin repo does not exist",
@ -352,7 +352,7 @@ func TestPluginExists(t *testing.T) {
})
t.Run("returns false when plugin dir does not exist", func(t *testing.T) {
exists, err := PluginExists(testDataDir, "non-existant")
exists, err := PluginExists(testDataDir, "non-existent")
if err != nil {
t.Errorf("got %v, expected nil", err)
}
@ -396,9 +396,9 @@ func TestRunCallback(t *testing.T) {
var stdout strings.Builder
var stderr strings.Builder
err = plugin.RunCallback("non-existant", []string{}, emptyEnv, &stdout, &stderr)
err = plugin.RunCallback("non-existent", []string{}, emptyEnv, &stdout, &stderr)
assert.Equal(t, err.(NoCallbackError).Error(), "Plugin named lua does not have a callback named non-existant")
assert.Equal(t, err.(NoCallbackError).Error(), "Plugin named lua does not have a callback named non-existent")
})
t.Run("passes argument to command", func(t *testing.T) {
@ -432,6 +432,28 @@ func TestRunCallback(t *testing.T) {
})
}
func TestCallbackPath(t *testing.T) {
testDataDir := t.TempDir()
conf := config.Config{DataDir: testDataDir}
_, err := repotest.InstallPlugin("dummy_plugin", testDataDir, testPluginName)
assert.Nil(t, err)
plugin := New(conf, testPluginName)
t.Run("returns callback path when callback exists", func(t *testing.T) {
path, err := plugin.CallbackPath("install")
assert.Nil(t, err)
assert.Equal(t, filepath.Base(path), "install")
assert.Equal(t, filepath.Base(filepath.Dir(filepath.Dir(path))), plugin.Name)
assert.Equal(t, filepath.Base(filepath.Dir(filepath.Dir(filepath.Dir(path)))), "plugins")
})
t.Run("returns error when callback does not exist", func(t *testing.T) {
path, err := plugin.CallbackPath("non-existent")
assert.Equal(t, err.(NoCallbackError).Error(), "Plugin named lua does not have a callback named non-existent")
assert.Equal(t, path, "")
})
}
func TestLegacyFilenames(t *testing.T) {
testDataDir := t.TempDir()
conf := config.Config{DataDir: testDataDir}
@ -488,7 +510,7 @@ func TestParseLegacyVersionFile(t *testing.T) {
})
t.Run("returns error when passed file that doesn't exist", func(t *testing.T) {
versions, err := plugin.ParseLegacyVersionFile("non-existant-file")
versions, err := plugin.ParseLegacyVersionFile("non-existent-file")
assert.Error(t, err)
assert.Empty(t, versions)
})

View File

@ -56,16 +56,16 @@ func (e NoExecutableForPluginError) Error() string {
// FindExecutable takes a shim name and a current directory and returns the path
// to the executable that the shim resolves to.
func FindExecutable(conf config.Config, shimName, currentDirectory string) (string, bool, error) {
func FindExecutable(conf config.Config, shimName, currentDirectory string) (string, plugins.Plugin, string, bool, error) {
shimPath := Path(conf, shimName)
if _, err := os.Stat(shimPath); err != nil {
return "", false, UnknownCommandError{shim: shimName}
return "", plugins.Plugin{}, "", false, UnknownCommandError{shim: shimName}
}
toolVersions, err := GetToolsAndVersionsFromShimFile(shimPath)
if err != nil {
return "", false, err
return "", plugins.Plugin{}, "", false, err
}
existingPluginToolVersions := make(map[plugins.Plugin]resolve.ToolVersions)
@ -77,7 +77,7 @@ func FindExecutable(conf config.Config, shimName, currentDirectory string) (stri
versions, found, err := resolve.Version(conf, plugin, currentDirectory)
if err != nil {
return "", false, nil
return "", plugins.Plugin{}, "", false, nil
}
if found {
@ -93,21 +93,21 @@ func FindExecutable(conf config.Config, shimName, currentDirectory string) (stri
}
if len(existingPluginToolVersions) == 0 {
return "", false, NoVersionSetError{shim: shimName}
return "", plugins.Plugin{}, "", false, NoVersionSetError{shim: shimName}
}
for plugin, toolVersions := range existingPluginToolVersions {
for _, version := range toolVersions.Versions {
if version == "system" {
if executablePath, found := FindSystemExecutable(conf, shimName); found {
return executablePath, true, nil
return executablePath, plugin, version, true, nil
}
break
}
executablePath, err := GetExecutablePath(conf, plugin, shimName, version)
if err == nil {
return executablePath, true, nil
return executablePath, plugin, version, true, nil
}
}
}
@ -119,7 +119,7 @@ func FindExecutable(conf config.Config, shimName, currentDirectory string) (stri
versions = append(versions, existingPluginToolVersions[plugin].Versions...)
}
return "", false, NoExecutableForPluginError{shim: shimName, tools: tools, versions: versions}
return "", plugins.Plugin{}, "", false, NoExecutableForPluginError{shim: shimName, tools: tools, versions: versions}
}
// FindSystemExecutable returns the path to the system
@ -127,7 +127,7 @@ func FindExecutable(conf config.Config, shimName, currentDirectory string) (stri
func FindSystemExecutable(conf config.Config, executableName string) (string, bool) {
currentPath := os.Getenv("PATH")
defer os.Setenv("PATH", currentPath)
os.Setenv("PATH", paths.RemoveFromPath(currentPath, shimsDirectory(conf)))
os.Setenv("PATH", paths.RemoveFromPath(currentPath, Directory(conf)))
executablePath, err := exec.LookPath(executableName)
return executablePath, err == nil
}
@ -288,7 +288,9 @@ func Path(conf config.Config, shimName string) string {
return filepath.Join(conf.DataDir, shimDirName, shimName)
}
func shimsDirectory(conf config.Config) string {
// Directory returns the path to the shims directory for the current
// configuration.
func Directory(conf config.Config) string {
return filepath.Join(conf.DataDir, shimDirName)
}
@ -298,14 +300,11 @@ func ensureShimDirExists(conf config.Config) error {
// ToolExecutables returns a slice of executables for a given tool version
func ToolExecutables(conf config.Config, plugin plugins.Plugin, versionType, version string) (executables []string, err error) {
dirs, err := ExecutableDirs(plugin)
paths, err := ExecutablePaths(conf, plugin, toolversions.Version{Type: versionType, Value: version})
if err != nil {
return executables, err
return []string{}, err
}
installPath := installs.InstallPath(conf, plugin, toolversions.Version{Type: versionType, Value: version})
paths := dirsToPaths(dirs, installPath)
for _, path := range paths {
entries, err := os.ReadDir(path)
if _, ok := err.(*os.PathError); err != nil && !ok {
@ -325,6 +324,18 @@ func ToolExecutables(conf config.Config, plugin plugins.Plugin, versionType, ver
return executables, err
}
// ExecutablePaths returns a slice of absolute directory paths that tool
// executables are contained in.
func ExecutablePaths(conf config.Config, plugin plugins.Plugin, version toolversions.Version) ([]string, error) {
dirs, err := ExecutableDirs(plugin)
if err != nil {
return []string{}, err
}
installPath := installs.InstallPath(conf, plugin, version)
return dirsToPaths(dirs, installPath), nil
}
// ExecutableDirs returns a slice of directory names that tool executables are
// contained in
func ExecutableDirs(plugin plugins.Plugin) ([]string, error) {

View File

@ -30,16 +30,18 @@ func TestFindExecutable(t *testing.T) {
currentDir := t.TempDir()
t.Run("returns error when shim with name does not exist", func(t *testing.T) {
executable, found, err := FindExecutable(conf, "foo", currentDir)
executable, _, version, found, err := FindExecutable(conf, "foo", currentDir)
assert.Empty(t, executable)
assert.False(t, found)
assert.Empty(t, version)
assert.Equal(t, err.(UnknownCommandError).Error(), "unknown command: foo")
})
t.Run("returns error when shim is present but no version is set", func(t *testing.T) {
executable, found, err := FindExecutable(conf, "dummy", currentDir)
executable, _, version, found, err := FindExecutable(conf, "dummy", currentDir)
assert.Empty(t, executable)
assert.False(t, found)
assert.Empty(t, version)
assert.Equal(t, err.(NoVersionSetError).Error(), "no versions set for dummy")
})
@ -48,9 +50,11 @@ func TestFindExecutable(t *testing.T) {
data := []byte("lua 1.1.0")
assert.Nil(t, os.WriteFile(filepath.Join(currentDir, ".tool-versions"), data, 0o666))
executable, found, err := FindExecutable(conf, "dummy", currentDir)
executable, gotPlugin, version, found, err := FindExecutable(conf, "dummy", currentDir)
assert.Equal(t, filepath.Base(filepath.Dir(filepath.Dir(executable))), "1.1.0")
assert.Equal(t, filepath.Base(executable), "dummy")
assert.Equal(t, plugin, gotPlugin)
assert.Equal(t, version, "1.1.0")
assert.True(t, found)
assert.Nil(t, err)
})
@ -66,7 +70,9 @@ func TestFindExecutable(t *testing.T) {
assert.Nil(t, os.WriteFile(toolpath, []byte("lua system\n"), 0o666))
assert.Nil(t, GenerateAll(conf, &stdout, &stderr))
executable, found, err := FindExecutable(conf, "ls", currentDir)
executable, gotPlugin, version, found, err := FindExecutable(conf, "ls", currentDir)
assert.Equal(t, plugin, gotPlugin)
assert.Equal(t, version, "system")
assert.True(t, found)
assert.Nil(t, err)
@ -336,6 +342,32 @@ func TestToolExecutables(t *testing.T) {
})
}
func TestExecutablePaths(t *testing.T) {
conf, plugin := generateConfig(t)
installVersion(t, conf, plugin, "1.2.3")
t.Run("returns list only containing 'bin' when list-bin-paths callback missing", func(t *testing.T) {
executables, err := ExecutablePaths(conf, plugin, toolversions.Version{Type: "version", Value: "1.2.3"})
path := executables[0]
assert.Nil(t, err)
assert.Equal(t, filepath.Base(filepath.Dir(path)), "1.2.3")
assert.Equal(t, filepath.Base(path), "bin")
})
t.Run("returns list of executable paths for tool version", func(t *testing.T) {
data := []byte("echo 'foo bar'")
err := os.WriteFile(filepath.Join(plugin.Dir, "bin", "list-bin-paths"), data, 0o777)
assert.Nil(t, err)
executables, err := ExecutablePaths(conf, plugin, toolversions.Version{Type: "version", Value: "1.2.3"})
path1 := executables[0]
path2 := executables[1]
assert.Nil(t, err)
assert.Equal(t, filepath.Base(path1), "foo")
assert.Equal(t, filepath.Base(path2), "bar")
})
}
func TestExecutableDirs(t *testing.T) {
conf, plugin := generateConfig(t)
installVersion(t, conf, plugin, "1.2.3")

View File

@ -75,9 +75,9 @@ func TestBatsTests(t *testing.T) {
runBatsFile(t, dir, "reshim_command.bats")
})
//t.Run("shim_env_command", func(t *testing.T) {
// runBatsFile(t, dir, "shim_env_command.bats")
//})
t.Run("shim_env_command", func(t *testing.T) {
runBatsFile(t, dir, "shim_env_command.bats")
})
//t.Run("shim_exec", func(t *testing.T) {
// runBatsFile(t, dir, "shim_exec.bats")

View File

@ -38,7 +38,8 @@ teardown() {
echo "dummy 1.0" >"$PROJECT_DIR/.tool-versions"
run asdf install
echo "export FOO=bar" >"$ASDF_DIR/plugins/dummy/bin/exec-env"
echo '#!/usr/bin/env bash
export FOO=bar' >"$ASDF_DIR/plugins/dummy/bin/exec-env"
chmod +x "$ASDF_DIR/plugins/dummy/bin/exec-env"
run asdf env dummy
@ -46,13 +47,34 @@ teardown() {
echo "$output" | grep 'FOO=bar'
}
@test "asdf env should print error when plugin version lacks the specified executable" {
echo "dummy 1.0" >"$PROJECT_DIR/.tool-versions"
run asdf install
echo '#!/usr/bin/env bash
export FOO=bar' >"$ASDF_DIR/plugins/dummy/bin/exec-env"
chmod +x "$ASDF_DIR/plugins/dummy/bin/exec-env"
echo "dummy system" >"$PROJECT_DIR/.tool-versions"
run asdf env dummy
[ "$status" -eq 1 ]
[ "$output" = "No executable dummy found for current version. Please select a different version or install dummy manually for the current version" ]
}
@test "asdf env should ignore plugin custom environment on system version" {
echo "dummy 1.0" >"$PROJECT_DIR/.tool-versions"
run asdf install
echo "export FOO=bar" >"$ASDF_DIR/plugins/dummy/bin/exec-env"
echo '#!/usr/bin/env bash
export FOO=bar' >"$ASDF_DIR/plugins/dummy/bin/exec-env"
chmod +x "$ASDF_DIR/plugins/dummy/bin/exec-env"
# Create a "system" dummy executable
echo '#!/usr/bin/env bash
echo "system dummy"' >"$ASDF_BIN/dummy"
chmod +x "$ASDF_BIN/dummy"
echo "dummy system" >"$PROJECT_DIR/.tool-versions"
run asdf env dummy
@ -63,8 +85,10 @@ teardown() {
[ "$status" -eq 1 ]
run asdf env dummy which dummy
[ "$output" = "$ASDF_DIR/shims/dummy" ]
[ "$output" = "$ASDF_BIN/dummy" ]
[ "$status" -eq 0 ]
# Remove "system" dummy executable
rm "$ASDF_BIN/dummy"
}
@test "asdf env should set PATH correctly" {