diff --git a/internal/shims/shims.go b/internal/shims/shims.go index e4dfea5bd..941986e6c 100644 --- a/internal/shims/shims.go +++ b/internal/shims/shims.go @@ -308,9 +308,10 @@ func ToolExecutables(conf config.Config, plugin plugins.Plugin, versionType, ver for _, path := range paths { entries, err := os.ReadDir(path) - if err != nil { + if _, ok := err.(*os.PathError); err != nil && !ok { return executables, err } + for _, entry := range entries { // If entry is dir or cannot be executed by the current user ignore it filePath := filepath.Join(path, entry.Name()) @@ -320,9 +321,6 @@ func ToolExecutables(conf config.Config, plugin plugins.Plugin, versionType, ver executables = append(executables, filePath) } - if err != nil { - return executables, err - } } return executables, err } diff --git a/internal/shims/shims_test.go b/internal/shims/shims_test.go index abf7ce407..be3143623 100644 --- a/internal/shims/shims_test.go +++ b/internal/shims/shims_test.go @@ -318,6 +318,22 @@ func TestToolExecutables(t *testing.T) { assert.Equal(t, filenames, []string{"dummy"}) }) + + t.Run("returns list of executables even when one directory printed by list-bin-paths doesn't exist", func(t *testing.T) { + // foo is first in list returned by list-bin-paths but doesn't exist, do + // we still get the executables in the bin/ dir? + repotest.WritePluginCallback(plugin.Dir, "list-bin-paths", "#!/usr/bin/env bash\necho 'foo bin'") + executables, err := ToolExecutables(conf, plugin, "version", version.Value) + assert.Nil(t, err) + + var filenames []string + for _, executablePath := range executables { + assert.True(t, strings.HasPrefix(executablePath, conf.DataDir)) + filenames = append(filenames, filepath.Base(executablePath)) + } + + assert.Equal(t, filenames, []string{"dummy"}) + }) } func TestExecutableDirs(t *testing.T) { diff --git a/repotest/repotest.go b/repotest/repotest.go index d28d7d8ea..9f887b6d5 100644 --- a/repotest/repotest.go +++ b/repotest/repotest.go @@ -31,6 +31,11 @@ func Setup(asdfDataDir string) error { return nil } +// WritePluginCallback is for creating new plugin callbacks on the fly. +func WritePluginCallback(pluginDir, callbackName, script string) error { + return os.WriteFile(filepath.Join(pluginDir, "bin", callbackName), []byte(script), 0o777) +} + // InstallPlugin copies in the specified plugin fixture into the asdfDataDir's // plugin directory and initializes a Git repo for it so asdf treats it as // installed.