From 14a82ab17bea31a680e7d3136bda07b9813189a2 Mon Sep 17 00:00:00 2001 From: Joao Rodrigues Date: Sat, 26 Apr 2025 02:59:26 +0100 Subject: [PATCH 1/2] feat: add version validation when using set command These changes ensure that the specified version is available for the plugin. Fixes #1983 --- internal/cli/cli.go | 15 +++------------ internal/cli/set/set.go | 15 +++++++++++++-- internal/plugins/plugins.go | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/internal/cli/cli.go b/internal/cli/cli.go index c7a7e48f3..56cce8e47 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -1222,22 +1222,13 @@ func listAllCommand(logger *log.Logger, conf config.Config, toolName, filter str return err } - var stdout strings.Builder - var stderr strings.Builder - - err = plugin.RunCallback("list-all", []string{}, map[string]string{}, &stdout, &stderr) + versions, err := plugin.GetAvailableVersions() if err != nil { - fmt.Printf("Plugin %s's list-all callback script failed with output:\n", plugin.Name) - // Print to stderr - os.Stderr.WriteString(stderr.String()) - os.Stderr.WriteString(stdout.String()) - + logger.Printf("%v", err) cli.OsExiter(1) return err } - versions := strings.Split(stdout.String(), " ") - if filter != "" { versions = filterByExactMatch(versions, filter) } @@ -1249,7 +1240,7 @@ func listAllCommand(logger *log.Logger, conf config.Config, toolName, filter str } for _, version := range versions { - fmt.Printf("%s\n", version) + logger.Printf("%s\n", version) } return nil diff --git a/internal/cli/set/set.go b/internal/cli/set/set.go index 407872e81..68d8097f7 100644 --- a/internal/cli/set/set.go +++ b/internal/cli/set/set.go @@ -7,6 +7,7 @@ import ( "io" "os" "path/filepath" + "slices" "strings" "github.com/asdf-vm/asdf/internal/config" @@ -35,11 +36,15 @@ func Main(_ io.Writer, stderr io.Writer, args []string, home bool, parent bool, } resolvedVersions := []string{} - + plugin := plugins.New(conf, args[0]) + pluginAvailableVersions, err := plugin.GetAvailableVersions() + if err != nil { + return printError(stderr, fmt.Sprintf("error getting available plugin versions: %s", err)) + } + for _, version := range args[1:] { parsedVersion := toolversions.ParseFromCliArg(version) if parsedVersion.Type == "latest" { - plugin := plugins.New(conf, args[0]) resolvedVersion, err := versions.Latest(plugin, parsedVersion.Value) if err != nil { return fmt.Errorf("unable to resolve latest version for %s", plugin.Name) @@ -49,6 +54,12 @@ func Main(_ io.Writer, stderr io.Writer, args []string, home bool, parent bool, } resolvedVersions = append(resolvedVersions, version) } + + for _, version := range resolvedVersions { + if !slices.Contains(pluginAvailableVersions, version) { + return printError(stderr, fmt.Sprintf("version %s is not available for plugin %s\n", version, plugin.Name)) + } + } tv := toolversions.ToolVersions{Name: args[0], Versions: resolvedVersions} diff --git a/internal/plugins/plugins.go b/internal/plugins/plugins.go index faf8f0f6f..516a0fc6c 100644 --- a/internal/plugins/plugins.go +++ b/internal/plugins/plugins.go @@ -298,6 +298,26 @@ func (p Plugin) Update(conf config.Config, ref string, out, errout io.Writer) (s return newRef, nil } +// GetAvailableVersions retrieves all available versions of the plugin +func (p Plugin) GetAvailableVersions() ([]string, error) { + var stdout, stderr strings.Builder + + err := p.RunCallback("list-all", []string{}, map[string]string{}, &stdout, &stderr) + if err != nil { + msg := fmt.Sprintf( + "Plugin %s's list-all callback script failed with error:\n%v\nStderr:\n%v\nStdout:\n%v\n", + p.Name, err, stderr.String(), stdout.String(), + ) + + return nil, errors.New(msg) + } + + versions := strings.Split(stdout.String(), " ") + return versions, 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) { From df11d4be9f7508e4d17098a2a6c62246c4d349a5 Mon Sep 17 00:00:00 2001 From: Joao Rodrigues Date: Sat, 26 Apr 2025 03:03:51 +0100 Subject: [PATCH 2/2] style: run make lint and format targets --- internal/cli/set/set.go | 4 ++-- internal/git/git.go | 1 - internal/plugins/plugins.go | 2 -- internal/shims/shims.go | 1 - internal/versions/versions_test.go | 4 ++-- 5 files changed, 4 insertions(+), 8 deletions(-) diff --git a/internal/cli/set/set.go b/internal/cli/set/set.go index 68d8097f7..025cf3490 100644 --- a/internal/cli/set/set.go +++ b/internal/cli/set/set.go @@ -41,7 +41,7 @@ func Main(_ io.Writer, stderr io.Writer, args []string, home bool, parent bool, if err != nil { return printError(stderr, fmt.Sprintf("error getting available plugin versions: %s", err)) } - + for _, version := range args[1:] { parsedVersion := toolversions.ParseFromCliArg(version) if parsedVersion.Type == "latest" { @@ -54,7 +54,7 @@ func Main(_ io.Writer, stderr io.Writer, args []string, home bool, parent bool, } resolvedVersions = append(resolvedVersions, version) } - + for _, version := range resolvedVersions { if !slices.Contains(pluginAvailableVersions, version) { return printError(stderr, fmt.Sprintf("version %s is not available for plugin %s\n", version, plugin.Name)) diff --git a/internal/git/git.go b/internal/git/git.go index f36537d35..41c3fcf57 100644 --- a/internal/git/git.go +++ b/internal/git/git.go @@ -104,7 +104,6 @@ func (r Repo) Update(ref string) (string, string, string, error) { // If no ref is provided we take the default branch of the remote if strings.TrimSpace(ref) == "" { ref, err = r.remoteDefaultBranch() - if err != nil { return "", "", "", err } diff --git a/internal/plugins/plugins.go b/internal/plugins/plugins.go index 516a0fc6c..b2935c0b4 100644 --- a/internal/plugins/plugins.go +++ b/internal/plugins/plugins.go @@ -316,8 +316,6 @@ func (p Plugin) GetAvailableVersions() ([]string, error) { return versions, 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) { diff --git a/internal/shims/shims.go b/internal/shims/shims.go index 5c6dc65a8..27472395c 100644 --- a/internal/shims/shims.go +++ b/internal/shims/shims.go @@ -81,7 +81,6 @@ func FindExecutable(conf config.Config, shimName, currentDirectory string) (path } versions, found, err := resolve.Version(conf, plugin, currentDirectory) - if err != nil { return "", plugins.Plugin{}, "", false, nil } diff --git a/internal/versions/versions_test.go b/internal/versions/versions_test.go index b015a1803..37fbd9fa7 100644 --- a/internal/versions/versions_test.go +++ b/internal/versions/versions_test.go @@ -263,7 +263,7 @@ func TestInstallOneVersion(t *testing.T) { stdout, stderr := buildOutputs() installScript := filepath.Join(conf.DataDir, "plugins", plugin.Name, "bin", "install") - f, err := os.OpenFile(installScript, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0777) + f, err := os.OpenFile(installScript, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o777) assert.Nil(t, err) _, err = f.WriteString("\nexit 1") assert.Nil(t, err) @@ -347,7 +347,7 @@ func TestLatest(t *testing.T) { // Replace latest-stable script so it returns a dev version that would be otherwise filtered out latestScript := filepath.Join(pluginDir, "bin", "latest-stable") - err = os.WriteFile(latestScript, []byte("#!/usr/bin/env bash\necho 1.2.3-dev"), 0777) + err = os.WriteFile(latestScript, []byte("#!/usr/bin/env bash\necho 1.2.3-dev"), 0o777) assert.Nil(t, err) version, err := Latest(plugin, "")