mirror of
https://github.com/asdf-vm/asdf.git
synced 2024-12-23 20:05:09 -07:00
feat(golang-rewrite): create asdf where
command
* Move `versions.ParseString` function to the toolversions package * Create `toolversions.FormatForFS` function * use new `toolversions.FormatForFS` function * Create `asdf where` command * Enable BATS tests for `asdf where` command
This commit is contained in:
parent
ec8985af8f
commit
09d06ff125
74
cmd/cmd.go
74
cmd/cmd.go
@ -19,6 +19,7 @@ import (
|
||||
"asdf/internal/plugins"
|
||||
"asdf/internal/resolve"
|
||||
"asdf/internal/shims"
|
||||
"asdf/internal/toolversions"
|
||||
"asdf/internal/versions"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
@ -175,6 +176,15 @@ func Execute(version string) {
|
||||
return reshimCommand(logger, args.Get(0), args.Get(1))
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "where",
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
tool := cCtx.Args().Get(0)
|
||||
version := cCtx.Args().Get(1)
|
||||
|
||||
return whereCommand(logger, tool, version)
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "which",
|
||||
Action: func(cCtx *cli.Context) error {
|
||||
@ -265,7 +275,7 @@ func getVersionInfo(conf config.Config, plugin plugins.Plugin, currentDir string
|
||||
installed := false
|
||||
if found {
|
||||
firstVersion := toolversion.Versions[0]
|
||||
versionType, version := versions.ParseString(firstVersion)
|
||||
versionType, version := toolversions.Parse(firstVersion)
|
||||
installed = installs.IsInstalled(conf, plugin, versionType, version)
|
||||
}
|
||||
return toolversion, found, installed
|
||||
@ -663,8 +673,68 @@ func whichCommand(logger *log.Logger, command string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func whereCommand(logger *log.Logger, tool, version 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
|
||||
}
|
||||
|
||||
plugin := plugins.New(conf, tool)
|
||||
err = plugin.Exists()
|
||||
if err != nil {
|
||||
if _, ok := err.(plugins.PluginMissing); ok {
|
||||
logger.Printf("No such plugin: %s", tool)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
versionType, parsedVersion := toolversions.Parse(version)
|
||||
|
||||
if version == "" {
|
||||
// resolve version
|
||||
toolversions, found, err := resolve.Version(conf, plugin, currentDir)
|
||||
if err != nil {
|
||||
fmt.Printf("err %#+v\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if found && len(toolversions.Versions) > 0 && installs.IsInstalled(conf, plugin, "version", toolversions.Versions[0]) {
|
||||
installPath := installs.InstallPath(conf, plugin, "version", toolversions.Versions[0])
|
||||
logger.Printf("%s", installPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// not found
|
||||
msg := fmt.Sprintf("No version is set for %s; please run `asdf <global | shell | local> %s <version>`", tool, tool)
|
||||
logger.Print(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
if version == "system" {
|
||||
logger.Printf("System version is selected")
|
||||
return errors.New("System version is selected")
|
||||
}
|
||||
|
||||
if !installs.IsInstalled(conf, plugin, versionType, parsedVersion) {
|
||||
logger.Printf("Version not installed")
|
||||
return errors.New("Version not installed")
|
||||
}
|
||||
|
||||
installPath := installs.InstallPath(conf, plugin, versionType, parsedVersion)
|
||||
logger.Printf("%s", installPath)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func reshimToolVersion(conf config.Config, tool, version string, out io.Writer, errOut io.Writer) error {
|
||||
versionType, version := versions.ParseString(version)
|
||||
versionType, version := toolversions.Parse(version)
|
||||
return shims.GenerateForVersion(conf, plugins.New(conf, tool), versionType, version, out, errOut)
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
"asdf/internal/config"
|
||||
"asdf/internal/plugins"
|
||||
"asdf/internal/versions"
|
||||
"asdf/internal/toolversions"
|
||||
)
|
||||
|
||||
//go:embed help.txt
|
||||
@ -80,7 +80,7 @@ func writePluginHelp(conf config.Config, toolName, toolVersion string, writer io
|
||||
}
|
||||
|
||||
if toolVersion != "" {
|
||||
versionType, version := versions.ParseString(toolVersion)
|
||||
versionType, version := toolversions.Parse(toolVersion)
|
||||
env["ASDF_INSTALL_VERSION"] = version
|
||||
env["ASDF_INSTALL_TYPE"] = versionType
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"asdf/internal/config"
|
||||
"asdf/internal/plugins"
|
||||
"asdf/internal/toolversions"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -45,7 +46,8 @@ func InstallPath(conf config.Config, plugin plugins.Plugin, versionType, version
|
||||
if versionType == "path" {
|
||||
return version
|
||||
}
|
||||
return filepath.Join(pluginInstallPath(conf, plugin), version)
|
||||
|
||||
return filepath.Join(pluginInstallPath(conf, plugin), toolversions.FormatForFS(versionType, version))
|
||||
}
|
||||
|
||||
// DownloadPath returns the download path for a particular plugin and version
|
||||
@ -53,7 +55,8 @@ func DownloadPath(conf config.Config, plugin plugins.Plugin, versionType, versio
|
||||
if versionType == "path" {
|
||||
return ""
|
||||
}
|
||||
return filepath.Join(conf.DataDir, dataDirDownloads, plugin.Name, version)
|
||||
|
||||
return filepath.Join(conf.DataDir, dataDirDownloads, plugin.Name, toolversions.FormatForFS(versionType, version))
|
||||
}
|
||||
|
||||
// IsInstalled checks if a specific version of a tool is installed
|
||||
|
@ -1,8 +1,10 @@
|
||||
// Package toolversions handles reading and writing tools and versions from
|
||||
// asdf's .tool-versions files
|
||||
// asdf's .tool-versions files. It also handles parsing version strings from
|
||||
// .tool-versions files and command line arguments.
|
||||
package toolversions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
@ -81,6 +83,39 @@ func Unique(versions []ToolVersions) (uniques []ToolVersions) {
|
||||
return uniques
|
||||
}
|
||||
|
||||
// Parse parses a version string into versionType and version components
|
||||
func Parse(version string) (string, string) {
|
||||
segments := strings.Split(version, ":")
|
||||
if len(segments) >= 1 {
|
||||
remainder := strings.Join(segments[1:], ":")
|
||||
switch segments[0] {
|
||||
case "ref":
|
||||
return "ref", remainder
|
||||
case "path":
|
||||
// This is for people who have the local source already compiled
|
||||
// Like those who work on the language, etc
|
||||
// We'll allow specifying path:/foo/bar/project in .tool-versions
|
||||
// And then use the binaries there
|
||||
return "path", remainder
|
||||
default:
|
||||
return "version", version
|
||||
}
|
||||
}
|
||||
|
||||
return "version", version
|
||||
}
|
||||
|
||||
// FormatForFS takes a versionType and version strings and generate a version
|
||||
// string suitable for the file system
|
||||
func FormatForFS(versionType, version string) string {
|
||||
switch versionType {
|
||||
case "ref":
|
||||
return fmt.Sprintf("ref-%s", version)
|
||||
default:
|
||||
return version
|
||||
}
|
||||
}
|
||||
|
||||
// readLines reads all the lines in a given file
|
||||
// removing spaces and comments which are marked by '#'
|
||||
func readLines(content string) (lines []string) {
|
||||
|
@ -157,3 +157,33 @@ func TestgetAllToolsAndVersionsInContent(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
t.Run("returns 'version', and unmodified version when passed semantic version", func(t *testing.T) {
|
||||
versionType, version := Parse("1.2.3")
|
||||
assert.Equal(t, versionType, "version")
|
||||
assert.Equal(t, version, "1.2.3")
|
||||
})
|
||||
|
||||
t.Run("returns 'ref' and reference version when passed a ref version", func(t *testing.T) {
|
||||
versionType, version := Parse("ref:abc123")
|
||||
assert.Equal(t, versionType, "ref")
|
||||
assert.Equal(t, version, "abc123")
|
||||
})
|
||||
|
||||
t.Run("returns 'ref' and empty string when passed 'ref:'", func(t *testing.T) {
|
||||
versionType, version := Parse("ref:")
|
||||
assert.Equal(t, versionType, "ref")
|
||||
assert.Equal(t, version, "")
|
||||
})
|
||||
}
|
||||
|
||||
func TestFormatForFS(t *testing.T) {
|
||||
t.Run("returns version when version type is not ref", func(t *testing.T) {
|
||||
assert.Equal(t, FormatForFS("version", "foobar"), "foobar")
|
||||
})
|
||||
|
||||
t.Run("returns version prefixed with 'ref-' when version type is ref", func(t *testing.T) {
|
||||
assert.Equal(t, FormatForFS("ref", "foobar"), "ref-foobar")
|
||||
})
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"asdf/internal/plugins"
|
||||
"asdf/internal/resolve"
|
||||
"asdf/internal/shims"
|
||||
"asdf/internal/toolversions"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -131,7 +132,7 @@ func InstallOneVersion(conf config.Config, plugin plugins.Plugin, version string
|
||||
return UninstallableVersionError{versionType: "system"}
|
||||
}
|
||||
|
||||
versionType, version := ParseString(version)
|
||||
versionType, version := toolversions.Parse(version)
|
||||
|
||||
if versionType == "path" {
|
||||
return UninstallableVersionError{versionType: "path"}
|
||||
@ -306,25 +307,3 @@ func parseVersions(rawVersions string) []string {
|
||||
}
|
||||
return versions
|
||||
}
|
||||
|
||||
// ParseString parses a version string into versionType and version components
|
||||
func ParseString(version string) (string, string) {
|
||||
segments := strings.Split(version, ":")
|
||||
if len(segments) >= 1 {
|
||||
remainder := strings.Join(segments[1:], ":")
|
||||
switch segments[0] {
|
||||
case "ref":
|
||||
return "ref", remainder
|
||||
case "path":
|
||||
// This is for people who have the local source already compiled
|
||||
// Like those who work on the language, etc
|
||||
// We'll allow specifying path:/foo/bar/project in .tool-versions
|
||||
// And then use the binaries there
|
||||
return "path", remainder
|
||||
default:
|
||||
return "version", version
|
||||
}
|
||||
}
|
||||
|
||||
return "version", version
|
||||
}
|
||||
|
@ -308,26 +308,6 @@ func TestLatest(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseString(t *testing.T) {
|
||||
t.Run("returns 'version', and unmodified version when passed semantic version", func(t *testing.T) {
|
||||
versionType, version := ParseString("1.2.3")
|
||||
assert.Equal(t, versionType, "version")
|
||||
assert.Equal(t, version, "1.2.3")
|
||||
})
|
||||
|
||||
t.Run("returns 'ref' and reference version when passed a ref version", func(t *testing.T) {
|
||||
versionType, version := ParseString("ref:abc123")
|
||||
assert.Equal(t, versionType, "ref")
|
||||
assert.Equal(t, version, "abc123")
|
||||
})
|
||||
|
||||
t.Run("returns 'ref' and empty string when passed 'ref:'", func(t *testing.T) {
|
||||
versionType, version := ParseString("ref:")
|
||||
assert.Equal(t, versionType, "ref")
|
||||
assert.Equal(t, version, "")
|
||||
})
|
||||
}
|
||||
|
||||
func TestAllVersions(t *testing.T) {
|
||||
pluginName := "list-all-test"
|
||||
conf, _ := generateConfig(t)
|
||||
|
@ -95,9 +95,9 @@ func TestBatsTests(t *testing.T) {
|
||||
// runBatsFile(t, dir, "version_commands.bats")
|
||||
//})
|
||||
|
||||
//t.Run("where_command", func(t *testing.T) {
|
||||
// runBatsFile(t, dir, "where_command.bats")
|
||||
//})
|
||||
t.Run("where_command", func(t *testing.T) {
|
||||
runBatsFile(t, dir, "where_command.bats")
|
||||
})
|
||||
|
||||
t.Run("which_command", func(t *testing.T) {
|
||||
runBatsFile(t, dir, "which_command.bats")
|
||||
|
@ -8,6 +8,7 @@ setup() {
|
||||
install_dummy_version 1.0
|
||||
install_dummy_version 2.1
|
||||
install_dummy_version ref-master
|
||||
cd "$HOME" || exit
|
||||
}
|
||||
|
||||
teardown() {
|
||||
|
Loading…
Reference in New Issue
Block a user