feat(golang-rewrite): use plugin index

* Create `pluginindex.Build` function
* Use `pluginindex` when no plugin URL provided for plugin add command
* Get more `plugin_add_command` BATS tests passing against Golang version
* Only use `pluginindex` when it is not disabled
* Update error message so it matches legacy format
* Add staticcheck.conf
This commit is contained in:
Trevor Brown 2024-06-04 21:03:03 -04:00
parent a5d7ebf8bc
commit 8394e858fe
8 changed files with 76 additions and 19 deletions

View File

@ -2,6 +2,7 @@
package cmd package cmd
import ( import (
"errors"
"log" "log"
"os" "os"
@ -115,17 +116,23 @@ func pluginAddCommand(_ *cli.Context, conf config.Config, logger *log.Logger, pl
// Maybe one day switch this to show the generated help // Maybe one day switch this to show the generated help
// cli.ShowSubcommandHelp(cCtx) // cli.ShowSubcommandHelp(cCtx)
return cli.Exit("usage: asdf plugin add <name> [<git-url>]", 1) return cli.Exit("usage: asdf plugin add <name> [<git-url>]", 1)
} else if pluginRepo == "" {
// add from plugin repo
// TODO: implement
return cli.Exit("Not implemented yet", 1)
} }
err := plugins.Add(conf, pluginName, pluginRepo) err := plugins.Add(conf, pluginName, pluginRepo)
if err != nil { if err != nil {
logger.Printf("error adding plugin: %s", err) logger.Printf("%s", err)
var existsErr plugins.PluginAlreadyExists
if errors.As(err, &existsErr) {
os.Exit(0)
return nil
}
os.Exit(1)
return nil
} }
os.Exit(0)
return nil return nil
} }

View File

@ -130,7 +130,7 @@ func TestBatsTests(t *testing.T) {
// cmd.Stderr = &stderr // cmd.Stderr = &stderr
// // Add dir to asdf test variables // // Add dir to asdf test variables
// asdfTestHome := fmt.Sprintf("HOME=%s", dir) // asdfTestHome := fmt.Sprintf("BASE_DIR=%s", dir)
// asdfBinPath := fmt.Sprintf("ASDF_BIN=%s", dir) // asdfBinPath := fmt.Sprintf("ASDF_BIN=%s", dir)
// cmd.Env = []string{asdfBinPath, asdfTestHome} // cmd.Env = []string{asdfBinPath, asdfTestHome}

View File

@ -28,6 +28,12 @@ type PluginIndex struct {
updateDurationMinutes int updateDurationMinutes int
} }
// Build returns a complete PluginIndex struct with default values set
func Build(dataDir string, URL string, disableUpdate bool, updateDurationMinutes int) PluginIndex {
directory := filepath.Join(dataDir, pluginIndexDir)
return New(directory, URL, disableUpdate, updateDurationMinutes, &git.Repo{Directory: directory})
}
// New initializes a new PluginIndex instance with the options passed in. // New initializes a new PluginIndex instance with the options passed in.
func New(directory, url string, disableUpdate bool, updateDurationMinutes int, repo git.Repoer) PluginIndex { func New(directory, url string, disableUpdate bool, updateDurationMinutes int, repo git.Repoer) PluginIndex {
return PluginIndex{ return PluginIndex{
@ -134,7 +140,7 @@ func readPlugin(dir, name string) (string, error) {
pluginInfo, err := ini.Load(filename) pluginInfo, err := ini.Load(filename)
if err != nil { if err != nil {
return "", fmt.Errorf("no such plugin found in plugin index: %s", name) return "", fmt.Errorf("plugin %s not found in repository", name)
} }
return pluginInfo.Section("").Key("repository").String(), nil return pluginInfo.Section("").Key("repository").String(), nil

View File

@ -114,7 +114,7 @@ func TestGetPluginSourceURL(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
pluginIndex := New(dir, realIndexURL, false, 10, &MockIndex{Directory: dir}) pluginIndex := New(dir, realIndexURL, false, 10, &MockIndex{Directory: dir})
url, err := pluginIndex.GetPluginSourceURL("foobar") url, err := pluginIndex.GetPluginSourceURL("foobar")
assert.EqualError(t, err, "no such plugin found in plugin index: foobar") assert.EqualError(t, err, "plugin foobar not found in repository")
assert.Equal(t, url, "") assert.Equal(t, url, "")
}) })

View File

@ -10,12 +10,29 @@ import (
"asdf/config" "asdf/config"
"asdf/git" "asdf/git"
"asdf/pluginindex"
) )
// NewPluginAlreadyExists generates a new PluginAlreadyExists error instance for
// a particular plugin
func NewPluginAlreadyExists(plugin string) PluginAlreadyExists {
return PluginAlreadyExists{plugin: plugin}
}
// PluginAlreadyExists is an error returned when the specified plugin already
// exists
type PluginAlreadyExists struct {
plugin string
}
func (e PluginAlreadyExists) Error() string {
return fmt.Sprintf(pluginAlreadyExistsMsg, e.plugin)
}
const ( const (
dataDirPlugins = "plugins" dataDirPlugins = "plugins"
invalidPluginNameMsg = "'%q' is invalid. Name may only contain lowercase letters, numbers, '_', and '-'" invalidPluginNameMsg = "%s is invalid. Name may only contain lowercase letters, numbers, '_', and '-'"
pluginAlreadyExists = "plugin named %q already added" pluginAlreadyExistsMsg = "Plugin named %s already added"
) )
// Plugin struct represents an asdf plugin to all asdf code. The name and dir // Plugin struct represents an asdf plugin to all asdf code. The name and dir
@ -96,7 +113,7 @@ func Add(config config.Config, pluginName, pluginURL string) error {
} }
if exists { if exists {
return fmt.Errorf(pluginAlreadyExists, pluginName) return NewPluginAlreadyExists(pluginName)
} }
pluginDir := PluginDirectory(config.DataDir, pluginName) pluginDir := PluginDirectory(config.DataDir, pluginName)
@ -105,6 +122,30 @@ func Add(config config.Config, pluginName, pluginURL string) error {
return fmt.Errorf("unable to create plugin directory: %w", err) return fmt.Errorf("unable to create plugin directory: %w", err)
} }
if pluginURL == "" {
// Ignore error here as the default value is fine
disablePluginIndex, _ := config.DisablePluginShortNameRepository()
if disablePluginIndex {
return fmt.Errorf("Short-name plugin repository is disabled")
}
lastCheckDuration := 0
// We don't care about errors here as we can use the default value
checkDuration, _ := config.PluginRepositoryLastCheckDuration()
if !checkDuration.Never {
lastCheckDuration = checkDuration.Every
}
index := pluginindex.Build(config.DataDir, "https://github.com/asdf-vm/asdf-plugins.git", false, lastCheckDuration)
var err error
pluginURL, err = index.GetPluginSourceURL(pluginName)
if err != nil {
return fmt.Errorf("error fetching plugin URL: %s", err)
}
}
return git.NewRepo(pluginDir).Clone(pluginURL) return git.NewRepo(pluginDir).Clone(pluginURL)
} }

View File

@ -107,7 +107,7 @@ func TestAdd(t *testing.T) {
t.Fatal("expected error got nil") t.Fatal("expected error got nil")
} }
expectedErrMsg := "plugin named \"lua\" already added" expectedErrMsg := "Plugin named lua already added"
if !strings.Contains(err.Error(), expectedErrMsg) { if !strings.Contains(err.Error(), expectedErrMsg) {
t.Errorf("Expected an error with message %v", expectedErrMsg) t.Errorf("Expected an error with message %v", expectedErrMsg)
} }

1
staticcheck.conf Normal file
View File

@ -0,0 +1 @@
checks = ["all", "-ST1005"]

View File

@ -7,19 +7,18 @@ bats_require_minimum_version 1.7.0
setup_asdf_dir() { setup_asdf_dir() {
if [ "$BATS_TEST_NAME" = 'test_shim_exec_should_use_path_executable_when_specified_version_path-3a-3cpath-3e' ]; then if [ "$BATS_TEST_NAME" = 'test_shim_exec_should_use_path_executable_when_specified_version_path-3a-3cpath-3e' ]; then
BASE_DIR="$HOME/asdf_with_no_spaces/" BASE_DIR="$BASE_DIR/asdf_with_no_spaces"
else else
BASE_DIR="$HOME/asdf with spaces/" BASE_DIR="$BASE_DIR/w space${BATS_TEST_NAME}"
fi fi
# We don't call mktemp anymore so we need to create this sub directory manually # We don't call mktemp anymore so we need to create this sub directory manually
mkdir "$BASE_DIR" mkdir "$BASE_DIR"
# HOME is now defined by the Golang test code in main_test.go # HOME is now defined by the Golang test code in main_test.go
#HOME="$BASE_DIR/home" HOME="$BASE_DIR/home"
ASDF_DIR="$BASE_DIR/.asdf" export HOME
ASDF_DATA_DIR="$BASE_DIR/.asdf" ASDF_DIR="$HOME/.asdf"
export ASDF_DATA_DIR
mkdir -p "$ASDF_DIR/plugins" mkdir -p "$ASDF_DIR/plugins"
mkdir -p "$ASDF_DIR/installs" mkdir -p "$ASDF_DIR/installs"
mkdir -p "$ASDF_DIR/shims" mkdir -p "$ASDF_DIR/shims"
@ -27,6 +26,9 @@ setup_asdf_dir() {
# ASDF_BIN is now defined by the Golang test code in main_test.go # ASDF_BIN is now defined by the Golang test code in main_test.go
#ASDF_BIN="$(dirname "$BATS_TEST_DIRNAME")/bin" #ASDF_BIN="$(dirname "$BATS_TEST_DIRNAME")/bin"
ASDF_DATA_DIR="$BASE_DIR/.asdf"
export ASDF_DATA_DIR
# shellcheck disable=SC2031,SC2153 # shellcheck disable=SC2031,SC2153
PATH="$ASDF_BIN:$ASDF_DIR/shims:$PATH" PATH="$ASDF_BIN:$ASDF_DIR/shims:$PATH"
} }