From 9ed4216525a2076b84e9e5fc6d454746a3b4d825 Mon Sep 17 00:00:00 2001 From: Trevor Brown Date: Sun, 15 Dec 2024 14:16:28 -0500 Subject: [PATCH] feat(golang-rewrite): misc. version improvements * Update `pluginListCommand` to print tools and versions to STDOUT * Improve output of `asdf current` command --- cli/cli.go | 53 +++++++++++---- docs/guide/upgrading-from-v0-14-to-v0-15.md | 10 +++ test/current_command.bats | 75 ++++++++++++++++----- 3 files changed, 106 insertions(+), 32 deletions(-) diff --git a/cli/cli.go b/cli/cli.go index e25caee4..4a370ce2 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -65,10 +65,17 @@ func Execute(version string) { }, { Name: "current", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "no-header", + Usage: "Whether or not to print a header line", + }, + }, Action: func(cCtx *cli.Context) error { tool := cCtx.Args().Get(0) - return currentCommand(logger, tool) + noHeader := cCtx.Bool("no-header") + return currentCommand(logger, tool, noHeader) }, }, { @@ -286,7 +293,7 @@ func Execute(version string) { } // This function is a whole mess and needs to be refactored -func currentCommand(logger *log.Logger, tool string) error { +func currentCommand(logger *log.Logger, tool string, noHeader bool) error { conf, err := config.LoadConfig() if err != nil { logger.Printf("error loading config: %s", err) @@ -301,6 +308,9 @@ func currentCommand(logger *log.Logger, tool string) error { // settings here to match legacy implementation w := tabwriter.NewWriter(os.Stdout, 16, 0, 1, ' ', 0) + if !noHeader { + writeHeader(w) + } if tool == "" { // show all @@ -358,23 +368,38 @@ func getVersionInfo(conf config.Config, plugin plugins.Plugin, currentDir string return toolversion, found, installed } +func writeHeader(w *tabwriter.Writer) { + fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", "Name", "Version", "Source", "Installed") +} + func formatCurrentVersionLine(w *tabwriter.Writer, plugin plugins.Plugin, toolversion resolve.ToolVersions, found bool, installed bool, err error) error { if err != nil { return err } - fmt.Fprintf(w, "%s\t%s\t%s\n", plugin.Name, formatVersions(toolversion.Versions), formatSource(toolversion, plugin, found, installed)) + // columns are: name, version, source, installed + version := formatVersions(toolversion.Versions) + source := formatSource(toolversion, found) + installedStatus := formatInstalled(toolversion, plugin.Name, found, installed) + fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", plugin.Name, version, source, installedStatus) return nil } -func formatSource(toolversion resolve.ToolVersions, plugin plugins.Plugin, found bool, installed bool) string { +func formatInstalled(toolversion resolve.ToolVersions, name string, found, installed bool) string { + if !found { + return "" + } + if !installed { + return fmt.Sprintf("false - Run `asdf install %s %s`", name, toolversion.Versions[0]) + } + return "true" +} + +func formatSource(toolversion resolve.ToolVersions, found bool) string { if found { - if !installed { - return fmt.Sprintf("Not installed. Run \"asdf install %s %s\"", plugin.Name, toolversion.Versions[0]) - } return filepath.Join(toolversion.Directory, toolversion.Source) } - return fmt.Sprintf("No version is set. Run \"asdf %s \"", plugin.Name) + return "______" } func formatVersions(versions []string) string { @@ -693,13 +718,13 @@ func pluginListCommand(cCtx *cli.Context, logger *log.Logger) error { // logic for _, plugin := range plugins { if urls && refs { - logger.Printf("%s\t\t%s\t%s\n", plugin.Name, plugin.URL, plugin.Ref) + fmt.Printf("%s\t\t%s\t%s\n", plugin.Name, plugin.URL, plugin.Ref) } else if refs { - logger.Printf("%s\t\t%s\n", plugin.Name, plugin.Ref) + fmt.Printf("%s\t\t%s\n", plugin.Name, plugin.Ref) } else if urls { - logger.Printf("%s\t\t%s\n", plugin.Name, plugin.URL) + fmt.Printf("%s\t\t%s\n", plugin.Name, plugin.URL) } else { - logger.Printf("%s\n", plugin.Name) + fmt.Printf("%s\n", plugin.Name) } } @@ -1370,7 +1395,7 @@ func whereCommand(logger *log.Logger, tool, versionStr string) error { versionStruct := toolversions.Version{Type: "version", Value: versions.Versions[0]} if installs.IsInstalled(conf, plugin, versionStruct) { installPath := installs.InstallPath(conf, plugin, versionStruct) - logger.Printf("%s", installPath) + fmt.Printf("%s", installPath) return nil } } @@ -1387,7 +1412,7 @@ func whereCommand(logger *log.Logger, tool, versionStr string) error { } installPath := installs.InstallPath(conf, plugin, version) - logger.Printf("%s", installPath) + fmt.Printf("%s", installPath) return nil } diff --git a/docs/guide/upgrading-from-v0-14-to-v0-15.md b/docs/guide/upgrading-from-v0-14-to-v0-15.md index ca32771c..ef62545f 100644 --- a/docs/guide/upgrading-from-v0-14-to-v0-15.md +++ b/docs/guide/upgrading-from-v0-14-to-v0-15.md @@ -50,6 +50,16 @@ not an executable. The new rewrite removes all shell code from asdf, and it is now a binary rather than a shell function, so setting environment variables directly in the shell is no longer possible. +### `asdf current` has changed + +Instead of three columns in the output, with the last being either the location +the version is set or a suggested command that could be run to set or install a +version. The third column has been split into two columns. The third column now +only indicates the source of the version if it is set (typically either version +file or environment variable) and the fourth is a boolean indicating whether +the specified version is actually installed. If it is not installed, a +suggested install command is shown. + ### Plugin extension commands must now be prefixed with `cmd` Previously plugin extension commands could be run like this: diff --git a/test/current_command.bats b/test/current_command.bats index 6921f4a3..78db17dd 100755 --- a/test/current_command.bats +++ b/test/current_command.bats @@ -20,42 +20,62 @@ teardown() { @test "current should derive from the current .tool-versions" { cd "$PROJECT_DIR" echo 'dummy 1.1.0' >>"$PROJECT_DIR/.tool-versions" - expected="dummy 1.1.0 $PROJECT_DIR/.tool-versions" + expected="Name Version Source Installed +dummy 1.1.0 $PROJECT_DIR/.tool-versions true" run asdf current "dummy" + + # shellcheck disable=SC2001 + condensed_output="$(sed -e 's/ [ ]*/ /g' <<<"$output")" + [ "$status" -eq 0 ] - [ "$output" = "$expected" ] + [ "$condensed_output" = "$expected" ] } @test "current should handle long version name" { cd "$PROJECT_DIR" echo "dummy nightly-2000-01-01" >>"$PROJECT_DIR/.tool-versions" - expected="dummy nightly-2000-01-01 $PROJECT_DIR/.tool-versions" + expected="Name Version Source Installed +dummy nightly-2000-01-01 $PROJECT_DIR/.tool-versions true" run asdf current "dummy" + + # shellcheck disable=SC2001 + condensed_output="$(sed -e 's/ [ ]*/ /g' <<<"$output")" + [ "$status" -eq 0 ] - [ "$output" = "$expected" ] + [ "$condensed_output" = "$expected" ] } @test "current should handle multiple versions" { cd "$PROJECT_DIR" echo "dummy 1.2.0 1.1.0" >>"$PROJECT_DIR/.tool-versions" - expected="dummy 1.2.0 1.1.0 $PROJECT_DIR/.tool-versions" + expected="Name Version Source Installed +dummy 1.2.0 1.1.0 $PROJECT_DIR/.tool-versions true" run asdf current "dummy" + + # shellcheck disable=SC2001 + condensed_output="$(sed -e 's/ [ ]*/ /g' <<<"$output")" + [ "$status" -eq 0 ] - [ "$output" = "$expected" ] + [ "$condensed_output" = "$expected" ] } @test "current should derive from the legacy file if enabled" { cd "$PROJECT_DIR" echo 'legacy_version_file = yes' >"$HOME/.asdfrc" echo '1.2.0' >>"$PROJECT_DIR/.dummy-version" - expected="dummy 1.2.0 $PROJECT_DIR/.dummy-version" + expected="Name Version Source Installed +dummy 1.2.0 $PROJECT_DIR/.dummy-version true" run asdf current "dummy" + + # shellcheck disable=SC2001 + condensed_output="$(sed -e 's/ [ ]*/ /g' <<<"$output")" + [ "$status" -eq 0 ] - [ "$output" = "$expected" ] + [ "$condensed_output" = "$expected" ] } # TODO: Need to fix plugin error as well @@ -69,21 +89,33 @@ teardown() { @test "current should error when no version is set" { cd "$PROJECT_DIR" - expected="dummy ______ No version is set. Run \"asdf dummy \"" + expected="Name Version Source Installed +dummy ______ ______ " run asdf current "dummy" + + # shellcheck disable=SC2001 + condensed_output="$(sed -e 's/ [ ]*/ /g' <<<"$output")" + [ "$status" -eq 126 ] - [ "$output" = "$expected" ] + [ "$condensed_output" = "$expected" ] } @test "current should error when a version is set that isn't installed" { cd "$PROJECT_DIR" echo 'dummy 9.9.9' >>"$PROJECT_DIR/.tool-versions" - expected="dummy 9.9.9 Not installed. Run \"asdf install dummy 9.9.9\"" + expected="Name Version Source Installed +dummy 9.9.9 $PROJECT_DIR/.tool-versions false - Run \`asdf install dummy 9.9.9\`" + asdf uninstall dummy 9.9.9 || true run asdf current "dummy" + + # shellcheck disable=SC2001 + condensed_output="$(sed -e 's/ [ ]*/ /g' -e 's/ $//g' <<<"$output")" + [ "$status" -eq 1 ] - [ "$output" = "$expected" ] + + [ "$condensed_output" = "$expected" ] } @test "should output all plugins when no plugin passed" { @@ -99,13 +131,17 @@ teardown() { cd "$PROJECT_DIR" echo 'dummy 1.1.0' >>"$PROJECT_DIR/.tool-versions" echo 'foobar 1.0.0' >>"$PROJECT_DIR/.tool-versions" + expected="Name Version Source Installed +baz ______ ______ +dummy 1.1.0 $PROJECT_DIR/.tool-versions true +foobar 1.0.0 $PROJECT_DIR/.tool-versions true" run asdf current - expected="baz ______ No version is set. Run \"asdf baz \" -dummy 1.1.0 $PROJECT_DIR/.tool-versions -foobar 1.0.0 $PROJECT_DIR/.tool-versions" - [ "$expected" = "$output" ] + # shellcheck disable=SC2001 + condensed_output="$(sed -e 's/ [ ]*/ /g' -e 's/ $//g' <<<"$output")" + + [ "$expected" = "$condensed_output" ] } @test "should always match the tool name exactly" { @@ -136,9 +172,12 @@ foobar 1.0.0 $PROJECT_DIR/.tool-versions" @test "current should handle comments" { cd "$PROJECT_DIR" echo "dummy 1.2.0 # this is a comment" >>"$PROJECT_DIR/.tool-versions" - expected="dummy 1.2.0 $PROJECT_DIR/.tool-versions" + expected="Name Version Source Installed +dummy 1.2.0 $PROJECT_DIR/.tool-versions true" run asdf current "dummy" [ "$status" -eq 0 ] - [ "$output" = "$expected" ] + # shellcheck disable=SC2001 + condensed_output="$(sed -e 's/ [ ]*/ /g' <<<"$output")" + [ "$condensed_output" = "$expected" ] }