mirror of
https://github.com/asdf-vm/asdf.git
synced 2024-12-19 09:55:01 -07:00
feat(golang-rewrite): version file parsing
* Create toolversions package * Address linter errors for toolversions package * Write tests
This commit is contained in:
parent
160ca04444
commit
3155dc374e
83
internal/toolversions/toolversions.go
Normal file
83
internal/toolversions/toolversions.go
Normal file
@ -0,0 +1,83 @@
|
||||
// Package toolversions handles reading and writing tools and versions from
|
||||
// asdf's .tool-versions files
|
||||
package toolversions
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ToolVersions represents a tool along with versions specified for it
|
||||
type ToolVersions struct {
|
||||
Name string
|
||||
Versions []string
|
||||
}
|
||||
|
||||
// FindToolVersions looks up a tool version in a tool versions file and if found
|
||||
// returns a slice of versions for it.
|
||||
func FindToolVersions(filepath, toolName string) (versions []string, found bool, err error) {
|
||||
content, err := os.ReadFile(filepath)
|
||||
if err != nil {
|
||||
return versions, false, err
|
||||
}
|
||||
|
||||
versions, found = findToolVersionsInContent(string(content), toolName)
|
||||
return versions, found, nil
|
||||
}
|
||||
|
||||
func findToolVersionsInContent(content, toolName string) (versions []string, found bool) {
|
||||
toolVersions := getAllToolsAndVersionsInContent(content)
|
||||
for _, tool := range toolVersions {
|
||||
if tool.Name == toolName {
|
||||
return tool.Versions, true
|
||||
}
|
||||
}
|
||||
|
||||
return versions, found
|
||||
}
|
||||
|
||||
// GetAllToolsAndVersions returns a list of all tools and associated versions
|
||||
// contained in a .tool-versions file
|
||||
func GetAllToolsAndVersions(filepath string) (toolVersions []ToolVersions, err error) {
|
||||
content, err := os.ReadFile(filepath)
|
||||
if err != nil {
|
||||
return toolVersions, err
|
||||
}
|
||||
|
||||
toolVersions = getAllToolsAndVersionsInContent(string(content))
|
||||
return toolVersions, nil
|
||||
}
|
||||
|
||||
func getAllToolsAndVersionsInContent(content string) (toolVersions []ToolVersions) {
|
||||
for _, line := range readLines(content) {
|
||||
tokens := parseLine(line)
|
||||
newTool := ToolVersions{Name: tokens[0], Versions: tokens[1:]}
|
||||
toolVersions = append(toolVersions, newTool)
|
||||
}
|
||||
|
||||
return toolVersions
|
||||
}
|
||||
|
||||
// readLines reads all the lines in a given file
|
||||
// removing spaces and comments which are marked by '#'
|
||||
func readLines(content string) (lines []string) {
|
||||
for _, line := range strings.Split(content, "\n") {
|
||||
line = strings.SplitN(line, "#", 2)[0]
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) > 0 {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseLine(line string) (tokens []string) {
|
||||
for _, token := range strings.Split(line, " ") {
|
||||
token = strings.TrimSpace(token)
|
||||
if len(token) > 0 {
|
||||
tokens = append(tokens, token)
|
||||
}
|
||||
}
|
||||
|
||||
return tokens
|
||||
}
|
106
internal/toolversions/toolversions_test.go
Normal file
106
internal/toolversions/toolversions_test.go
Normal file
@ -0,0 +1,106 @@
|
||||
package toolversions
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetAllToolsAndVersions(t *testing.T) {
|
||||
t.Run("returns error when non-existant file", func(t *testing.T) {
|
||||
toolVersions, err := GetAllToolsAndVersions("non-existant-file")
|
||||
assert.Error(t, err)
|
||||
assert.Empty(t, toolVersions)
|
||||
})
|
||||
|
||||
t.Run("returns list of tool versions when populated file", func(t *testing.T) {
|
||||
toolVersionsPath := filepath.Join(t.TempDir(), ".tool-versions")
|
||||
file, err := os.Create(toolVersionsPath)
|
||||
assert.Nil(t, err)
|
||||
defer file.Close()
|
||||
file.WriteString("ruby 2.0.0")
|
||||
|
||||
toolVersions, err := GetAllToolsAndVersions(toolVersionsPath)
|
||||
assert.Nil(t, err)
|
||||
expected := []ToolVersions{{Name: "ruby", Versions: []string{"2.0.0"}}}
|
||||
assert.Equal(t, expected, toolVersions)
|
||||
})
|
||||
}
|
||||
|
||||
func TestFindToolVersions(t *testing.T) {
|
||||
t.Run("returns error when non-existant file", func(t *testing.T) {
|
||||
versions, found, err := FindToolVersions("non-existant-file", "nonexistant-tool")
|
||||
assert.Error(t, err)
|
||||
assert.False(t, found)
|
||||
assert.Empty(t, versions)
|
||||
})
|
||||
|
||||
t.Run("returns list of versions and found true when file contains tool versions", func(t *testing.T) {
|
||||
toolVersionsPath := filepath.Join(t.TempDir(), ".tool-versions")
|
||||
file, err := os.Create(toolVersionsPath)
|
||||
assert.Nil(t, err)
|
||||
defer file.Close()
|
||||
file.WriteString("ruby 2.0.0")
|
||||
|
||||
versions, found, err := FindToolVersions(toolVersionsPath, "ruby")
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, found)
|
||||
assert.Equal(t, []string{"2.0.0"}, versions)
|
||||
})
|
||||
}
|
||||
|
||||
func TestfindToolVersionsInContent(t *testing.T) {
|
||||
t.Run("returns empty list with found false when empty content", func(t *testing.T) {
|
||||
versions, found := findToolVersionsInContent("", "ruby")
|
||||
assert.False(t, found)
|
||||
assert.Empty(t, versions)
|
||||
})
|
||||
|
||||
t.Run("returns empty list with found false when tool not found", func(t *testing.T) {
|
||||
versions, found := findToolVersionsInContent("lua 5.4.5", "ruby")
|
||||
assert.False(t, found)
|
||||
assert.Empty(t, versions)
|
||||
})
|
||||
|
||||
t.Run("returns list of versions with found true when tool found", func(t *testing.T) {
|
||||
versions, found := findToolVersionsInContent("lua 5.4.5 5.4.6\nruby 2.0.0", "lua")
|
||||
assert.True(t, found)
|
||||
assert.Equal(t, []string{"5.4.5", "5.4.6"}, versions)
|
||||
})
|
||||
}
|
||||
|
||||
func TestgetAllToolsAndVersionsInContent(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
input string
|
||||
want []ToolVersions
|
||||
}{
|
||||
{
|
||||
desc: "returns empty list with found true and no error when empty content",
|
||||
input: "",
|
||||
want: []ToolVersions{},
|
||||
},
|
||||
{
|
||||
desc: "returns list with one tool when single tool in content",
|
||||
input: "lua 5.4.5 5.4.6",
|
||||
want: []ToolVersions{{Name: "lua", Versions: []string{"5.4.5", "5.4.6"}}},
|
||||
},
|
||||
{
|
||||
desc: "returns list with multiple tools when multiple tools in content",
|
||||
input: "lua 5.4.5 5.4.6\nruby 2.0.0",
|
||||
want: []ToolVersions{
|
||||
{Name: "lua", Versions: []string{"5.4.5", "5.4.6"}},
|
||||
{Name: "ruby", Versions: []string{"2.0.0"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
toolsAndVersions := getAllToolsAndVersionsInContent(tt.input)
|
||||
assert.Equal(t, tt.want, toolsAndVersions)
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user