diff --git a/CHANGELOG.md b/CHANGELOG.md index b1397b49..2fb6c94e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,23 @@ Features +* Add support for asdf extension commands. + + When a plugin provides custom executables or bash-scripts under its `bin/` directory, + it's now possible to invoke them with: + + ```shell + asdf nodejs import-release-team-keyring + + # instead of people having to know where the executable is installed: + ~/.asdf/plugins/nodejs/bin/import-release-team-keyring + ``` + + As in nodejs case, plugin authors can use this feature to provide utilities, + or people can create plugins that are just extensions to asdf itself. + + See `docs/plugins-create.md` for more info. + * Add support for installing the latest stable version of a tool (#216, #575) ```shell diff --git a/bin/asdf b/bin/asdf index 3139f5f8..d5cd103c 100755 --- a/bin/asdf +++ b/bin/asdf @@ -114,8 +114,23 @@ case "$1" in "--version") asdf_version "${cmd_args[@]}";; - *) + "--help") load_cmd "help" - help_command + help_command;; + + *) + plugin_cmd="$(get_plugin_path "$1")/bin/${cmd_args[0]}" + + if [ -x "$plugin_cmd" ]; then + exec "$plugin_cmd" "${cmd_args[@]:1}" + elif [ -f "$plugin_cmd" ]; then + set -- "${cmd_args[@]:1}" + source "$plugin_cmd" + exit $? + fi + + echo "Unknown asdf command: \`${*}\`" >&2 + load_cmd "help" + help_command >&2 exit 1;; esac diff --git a/docs/plugins-create.md b/docs/plugins-create.md index c08164dc..4f28c537 100644 --- a/docs/plugins-create.md +++ b/docs/plugins-create.md @@ -88,6 +88,23 @@ Note: This will only apply for users who have enabled the `legacy_version_file` This can be used to further parse the legacy file found by asdf. If `parse-legacy-file` isn't implemented, asdf will simply cat the file to determine the version. The script will be passed the file path as its first argument. +## asdf extension commands + +It's possible for plugins to define new asdf commands. This way plugins can extend asdf capabilities or expose utilities related to their managed tool. + +For example, a `foo` plugin might expose the command `asdf foo bar` by providing an executable file at `bin/bar`. +If `bin/bar` is a file but has no executable bit set, then its considered a source-able bash script, and will be sourced +with all the functions in `$ASDF_DIR/lib/utils.sh` already loaded. + +A good example of this feature is the `nodejs` plugin, where people must import the release team keyring before +installing a nodejs version. People can execute the following command without having to know where exactly is the plugin located. + +```bash +asdf nodejs import-release-team-keyring +``` + +If your plugin provides an asdf extension command, be sure to mention about it on your plugin's README. + ## Custom shim templates **PLEASE use this feature only if absolutely required** diff --git a/test/plugin_extension_command.bats b/test/plugin_extension_command.bats new file mode 100644 index 00000000..079139f9 --- /dev/null +++ b/test/plugin_extension_command.bats @@ -0,0 +1,42 @@ +#!/usr/bin/env bats + +load test_helpers + +setup() { + setup_asdf_dir + install_dummy_plugin +} + +teardown() { + clean_asdf_dir +} + +@test "asdf can execute plugin bin commands" { + plugin_path="$(get_plugin_path dummy)" + + # this plugin defines a new `asdf dummy foo` command + cat <<'EOF' > "$plugin_path/bin/foo" +#!/usr/bin/env bash +echo this is an executable $* +EOF + chmod +x "$plugin_path/bin/foo" + + expected="this is an executable bar" + + run asdf dummy foo bar + [ "$status" -eq 0 ] + [ "$output" = "$expected" ] +} + +@test "asdf can source plugin bin scripts" { + plugin_path="$(get_plugin_path dummy)" + + # this plugin defines a new `asdf dummy foo` command + echo 'echo sourced script has asdf utils $(get_plugin_path dummy) $*' > "$plugin_path/bin/foo" + + expected="sourced script has asdf utils $plugin_path bar" + + run asdf dummy foo bar + [ "$status" -eq 0 ] + [ "$output" = "$expected" ] +}