From 387a98db5ff00fe962496f253192921b6db37d42 Mon Sep 17 00:00:00 2001 From: Trevor Brown Date: Sat, 14 Sep 2024 16:06:08 -0400 Subject: [PATCH] feat(golang-rewrite): create `asdf current` command * Create asdf current command * Correct output of asdf exec command when no command is provided * Enable current_command.bats tests * Fix current_command.bats test code --- cmd/cmd.go | 119 +++++++++++++++++++++++++++++++++++- internal/plugins/plugins.go | 5 ++ main_test.go | 6 +- test/current_command.bats | 4 +- 4 files changed, 127 insertions(+), 7 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 401e3eee..bf3df123 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -7,13 +7,16 @@ import ( "io" "log" "os" + "path/filepath" "strings" + "text/tabwriter" "asdf/internal/config" "asdf/internal/exec" "asdf/internal/info" "asdf/internal/installs" "asdf/internal/plugins" + "asdf/internal/resolve" "asdf/internal/shims" "asdf/internal/versions" @@ -45,6 +48,14 @@ func Execute(version string) { Usage: "The multiple runtime version manager", UsageText: usageText, Commands: []*cli.Command{ + { + Name: "current", + Action: func(cCtx *cli.Context) error { + tool := cCtx.Args().Get(0) + + return currentCommand(logger, tool) + }, + }, { Name: "exec", Action: func(cCtx *cli.Context) error { @@ -169,10 +180,114 @@ func Execute(version string) { } } +// This function is a whole mess and needs to be refactored +func currentCommand(logger *log.Logger, tool string) error { + 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 + } + + // settings here to match legacy implementation + w := tabwriter.NewWriter(os.Stdout, 16, 0, 1, ' ', 0) + + if tool == "" { + // show all + allPlugins, err := plugins.List(conf, false, false) + if err != nil { + return err + } + + if len(allPlugins) < 1 { + fmt.Println("No plugins installed") + return nil + } + + for _, plugin := range allPlugins { + toolversion, versionFound, versionInstalled := getVersionInfo(conf, plugin, currentDir) + formatCurrentVersionLine(w, plugin, toolversion, versionFound, versionInstalled, err) + } + w.Flush() + return nil + } + + // show single tool + plugin := plugins.New(conf, tool) + + err = plugin.Exists() + _, ok := err.(plugins.PluginMissing) + pluginExists := !ok + + if pluginExists { + toolversion, versionFound, versionInstalled := getVersionInfo(conf, plugin, currentDir) + formatCurrentVersionLine(w, plugin, toolversion, versionFound, versionInstalled, err) + w.Flush() + if !versionFound { + os.Exit(126) + } + + if !versionInstalled { + os.Exit(1) + } + } else { + fmt.Printf("No such plugin: %s\n", tool) + return err + } + + return nil +} + +func getVersionInfo(conf config.Config, plugin plugins.Plugin, currentDir string) (resolve.ToolVersions, bool, bool) { + toolversion, found, _ := resolve.Version(conf, plugin, currentDir) + installed := false + if found { + firstVersion := toolversion.Versions[0] + versionType, version := versions.ParseString(firstVersion) + installed = installs.IsInstalled(conf, plugin, versionType, version) + } + return toolversion, found, 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)) + return nil +} + +func formatSource(toolversion resolve.ToolVersions, plugin plugins.Plugin, found bool, installed 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) +} + +func formatVersions(versions []string) string { + switch len(versions) { + case 0: + return "______" + case 1: + return versions[0] + default: + return strings.Join(versions, " ") + } +} + func execCommand(logger *log.Logger, command string, args []string) error { if command == "" { - logger.Printf("no command specified") - return fmt.Errorf("no command specified") + logger.Printf("usage: asdf exec ") + return fmt.Errorf("usage: asdf exec ") } conf, err := config.LoadConfig() diff --git a/internal/plugins/plugins.go b/internal/plugins/plugins.go index ef864cb4..0167438b 100644 --- a/internal/plugins/plugins.go +++ b/internal/plugins/plugins.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "io/fs" "os" "path/filepath" "regexp" @@ -175,6 +176,10 @@ func List(config config.Config, urls, refs bool) (plugins []Plugin, err error) { pluginsDir := DataDirectory(config.DataDir) files, err := os.ReadDir(pluginsDir) if err != nil { + if _, ok := err.(*fs.PathError); ok { + return []Plugin{}, nil + } + return plugins, err } diff --git a/main_test.go b/main_test.go index cfa09315..5e2396be 100644 --- a/main_test.go +++ b/main_test.go @@ -19,9 +19,9 @@ func TestBatsTests(t *testing.T) { // Run tests with the asdf binary in the temp directory // Uncomment these as they are implemented - //t.Run("current_command", func(t *testing.T) { - // runBatsFile(t, dir, "current_command.bats") - //}) + t.Run("current_command", func(t *testing.T) { + runBatsFile(t, dir, "current_command.bats") + }) //t.Run("help_command", func(t *testing.T) { // runBatsFile(t, dir, "help_command.bats") diff --git a/test/current_command.bats b/test/current_command.bats index 687bc9da..6921f4a3 100755 --- a/test/current_command.bats +++ b/test/current_command.bats @@ -88,7 +88,7 @@ teardown() { @test "should output all plugins when no plugin passed" { - install_dummy_plugin + #install_dummy_plugin install_dummy_version "1.1.0" install_mock_plugin "foobar" @@ -109,7 +109,7 @@ foobar 1.0.0 $PROJECT_DIR/.tool-versions" } @test "should always match the tool name exactly" { - install_dummy_plugin + #install_dummy_plugin install_dummy_version "1.1.0" install_mock_plugin "y"