Skip to content

Commit

Permalink
feat(golang-rewrite): create settings and config structs for loading …
Browse files Browse the repository at this point in the history
…config

* rename commands package to cmd
* add go-ini as a dependency
* write code to parse asdfrc file into Settings struct
* add go-envconfig as a dependency
* add go-homedir as a dependency
* implement first version of LoadConfig function to load environment variables into Config struct
  • Loading branch information
Stratus3D committed Feb 19, 2024
1 parent 58f433f commit 7097b97
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 4 deletions.
1 change: 1 addition & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ jobs:
outputs:
documentation: ${{ steps.filter.outputs.documentation }}
cli: ${{ steps.filter.outputs.cli }}
go: ${{ steps.filter.outputs.go }}
steps:
- uses: actions/checkout@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion commands/commands.go → cmd/main.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package commands
package cmd

import (
"fmt"
Expand Down
105 changes: 105 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package main

import (
"context"
"strings"

"github.com/mitchellh/go-homedir"
"github.com/sethvargo/go-envconfig"
"gopkg.in/ini.v1"
)

// Not sure how best to represent this enum type
//type PluginRepositoryLastCheckDuration struct {
// Never bool
// Every int
//}

type Settings struct {
LegacyVersionFile bool
// I don't think this setting should be supported in the Golang implementation
//UseReleaseCandidates bool
AlwaysKeepDownload bool
PluginRepositoryLastCheckDuration string
DisablePluginShortNameRepository bool
}

type Config struct {
Home string
ConfigFile string `env:"ASDF_CONFIG_FILE"`
DefaultToolVersionsFilename string `env:"ASDF_DEFAULT_TOOL_VERSIONS_FILENAME"`
// Unclear if this value will be needed with the golang implementation.
//AsdfDir string
DataDir string `env:"ASDF_DATA_DIR"`
ForcePrepend bool `env:"ASDF_FORCE_PREPEND"`
}

func LoadConfig() (Config, error) {
config, err := loadConfigEnv()

if err != nil {
return config, err
}

homeDir, err := homedir.Dir()

if err != nil {
return config, err
}

config.Home = homeDir

return config, nil
}

func loadConfigEnv() (Config, error) {
context := context.Background()
config := Config{}

err := envconfig.Process(context, &config)

return config, err
}

func LoadSettings(asdfrcPath string) (Settings, error) {
// asdfrc is effectively formatted as ini
config, err := ini.Load(asdfrcPath)

if err != nil {
return Settings{}, err
}

mainConf := config.Section("")
checkDuration := stringToCheckDuration(mainConf.Key("plugin_repository_last_check_duration").String(), "60")

return Settings{
LegacyVersionFile: YesNoToBool(mainConf, "legacy_version_file", false),
AlwaysKeepDownload: YesNoToBool(mainConf, "use_release_candidates", false),
PluginRepositoryLastCheckDuration: checkDuration,
DisablePluginShortNameRepository: YesNoToBool(mainConf, "disable_plugin_short_name_repository", false),
}, nil
}

func YesNoToBool(section *ini.Section, key string, defaultValue bool) bool {
yesOrNo := section.Key(key).String()
lcYesOrNo := strings.ToLower(yesOrNo)
if lcYesOrNo == "yes" {
return true
}
if lcYesOrNo == "no" {
return false
}

return defaultValue
}

// Eventually this should return a custom type but I need to figure out how to
// represent the (never string, duration int) type. For now it just returns a
// string.
func stringToCheckDuration(checkDuration string, defaultValue string) string {
if checkDuration != "" {
return checkDuration
}

return defaultValue
}
65 changes: 65 additions & 0 deletions config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package main

import (
"testing"
)

func TestLoadConfig(t *testing.T) {
config, err := LoadConfig()

assert(t, err == nil, "Returned error when building config")

assert(t, config.Home != "", "Expected Home to be set")
}

func TestLoadConfigEnv(t *testing.T) {
config, err := loadConfigEnv()

assert(t, err == nil, "Returned error when loading env for config")

assert(t, config.Home == "", "Shouldn't set Home property when loading config")
}

func TestLoadSettings(t *testing.T) {
t.Run("When given invalid path returns error", func(t *testing.T) {
_, err := LoadSettings("./foobar")

if err == nil {
t.Fatal("Didn't get an error")
}
})

t.Run("When given path to populated asdfrc returns populated settings struct", func(t *testing.T) {
settings, err := LoadSettings("testdata/asdfrc")

refuteError(t, err)

assert(t, settings.LegacyVersionFile == true, "LegacyVersionFile field has wrong value")
assert(t, settings.AlwaysKeepDownload == true, "AlwaysKeepDownload field has wrong value")
assert(t, settings.PluginRepositoryLastCheckDuration == "never", "PluginRepositoryLastCheckDuration field has wrong value")
assert(t, settings.DisablePluginShortNameRepository == true, "DisablePluginShortNameRepository field has wrong value")
})

t.Run("When given path to empty file returns settings struct with defaults", func(t *testing.T) {
settings, err := LoadSettings("testdata/empty-asdfrc")

refuteError(t, err)

assert(t, settings.LegacyVersionFile == false, "LegacyVersionFile field has wrong value")
assert(t, settings.AlwaysKeepDownload == false, "AlwaysKeepDownload field has wrong value")
assert(t, settings.PluginRepositoryLastCheckDuration == "60", "PluginRepositoryLastCheckDuration field has wrong value")
assert(t, settings.DisablePluginShortNameRepository == false, "DisablePluginShortNameRepository field has wrong value")
})
}

func assert(t *testing.T, expr bool, message string) {
if !expr {
t.Error(message)
}
}

func refuteError(t *testing.T, err error) {
if err != nil {
t.Fatal("Returned unexpected error", err)
}
}
9 changes: 8 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ module asdf
go 1.21.5

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/sethvargo/go-envconfig v1.0.0
github.com/spf13/cobra v1.8.0
gopkg.in/ini.v1 v1.67.0
)

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.4 // indirect
)
15 changes: 15 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sethvargo/go-envconfig v1.0.0 h1:1C66wzy4QrROf5ew4KdVw942CQDa55qmlYmw9FZxZdU=
github.com/sethvargo/go-envconfig v1.0.0/go.mod h1:Lzc75ghUn5ucmcRGIdGQ33DKJrcjk4kihFYgSTBmjIc=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package main

import (
"asdf/commands"
"asdf/cmd"
)

// Placeholder for the real code
func main() {
commands.Execute()
cmd.Execute()
}
7 changes: 7 additions & 0 deletions testdata/asdfrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This is a test asdfrc file containing all possible values. Each field to set
# to a value that is different than the default.
legacy_version_file = yes
use_release_candidates = yes
always_keep_download = yes
plugin_repository_last_check_duration = never
disable_plugin_short_name_repository = yes
Empty file added testdata/empty-asdfrc
Empty file.

0 comments on commit 7097b97

Please sign in to comment.