Support customizing plugin-add and plugin-remove

* Add support for custom `plugin-add` and `plugin-remove` in plugins
* Add configurable command hooks for plugin installation and removal

```shell
pre_asdf_plugin_remove = echo will remove plugin ${1}
pre_asdf_plugin_remove_foo = echo will remove plugin foo
post_asdf_plugin_remove = echo removed plugin ${1}
post_asdf_plugin_remove_foo = echo removed plugin foo
```

Closes #670
This commit is contained in:
Jochen Schalanda 2020-03-21 14:59:33 +01:00
parent 3246c26d52
commit 57186be6d9
No known key found for this signature in database
GPG Key ID: 2FC1B61A8D1F4BB0
9 changed files with 204 additions and 1 deletions

View File

@ -2,6 +2,18 @@
## 0.7.8-dev
Features
* Add support for custom `plugin-add` and `plugin-remove` in plugins (#670)
* Add configurable command hooks for plugin installation and removal (#670)
```shell
pre_asdf_plugin_remove = echo will remove plugin ${1}
pre_asdf_plugin_remove_foo = echo will remove plugin foo
post_asdf_plugin_remove = echo removed plugin ${1}
post_asdf_plugin_remove_foo = echo removed plugin foo
```
Fixed Bugs
* Make sure extension commands are properly displayed by `asdf help`

View File

@ -88,6 +88,32 @@ 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.
#### bin/plugin-add
This can be used to run any post-installation actions after the plugin has been added to asdf.
The script has access to the path the plugin was installed (`${ASDF_PLUGIN_PATH}`) and the source URL (`${ASDF_PLUGIN_SOURCE_URL}`), if any was used.
See also the related hooks:
* `pre_asdf_plugin_add`
* `pre_asdf_plugin_add_${plugin_name}`
* `post_asdf_plugin_add`
* `post_asdf_plugin_add_${plugin_name}`
#### bin/plugin-remove
This can be used to run any pre-removal actions before the plugin will be removed from asdf.
The script has access to the path the plugin was installed in (`${ASDF_PLUGIN_PATH}`).
See also the related hooks:
* `pre_asdf_plugin_remove`
* `pre_asdf_plugin_remove_${plugin_name}`
* `post_asdf_plugin_remove`
* `post_asdf_plugin_remove_${plugin_name}`
## Extension commands for asdf CLI.
It's possible for plugins to define new asdf commands by providing `lib/commands/command*.bash` scripts or executables that

View File

@ -30,9 +30,23 @@ plugin_add_command() {
display_error "Plugin named $plugin_name already added"
exit 2
else
asdf_run_hook "pre_asdf_plugin_add" "$plugin_name"
asdf_run_hook "pre_asdf_plugin_add_${plugin_name}"
if ! git clone -q "$source_url" "$plugin_path"; then
exit 1
fi
if [ -f "${plugin_path}/bin/plugin-add" ]; then
(
export ASDF_PLUGIN_SOURCE_URL=$source_url
export ASDF_PLUGIN_PATH=$plugin_path
bash "${plugin_path}/bin/plugin-add"
)
fi
asdf_run_hook "post_asdf_plugin_add" "$plugin_name"
asdf_run_hook "post_asdf_plugin_add_${plugin_name}"
fi
}

View File

@ -7,10 +7,23 @@ plugin_remove_command() {
local plugin_path
plugin_path=$(get_plugin_path "$plugin_name")
asdf_run_hook "pre_asdf_plugin_remove" "$plugin_name"
asdf_run_hook "pre_asdf_plugin_remove_${plugin_name}"
if [ -f "${plugin_path}/bin/plugin-remove" ]; then
(
export ASDF_PLUGIN_PATH=$plugin_path
bash "${plugin_path}/bin/plugin-remove"
)
fi
rm -rf "$plugin_path"
rm -rf "$(asdf_data_dir)/installs/${plugin_name}"
grep -l "asdf-plugin: ${plugin_name}" "$(asdf_data_dir)"/shims/* 2>/dev/null | xargs rm -f
asdf_run_hook "post_asdf_plugin_remove" "$plugin_name"
asdf_run_hook "post_asdf_plugin_remove_${plugin_name}"
}
plugin_remove_command "$@"

View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
echo "plugin-add path=${ASDF_PLUGIN_PATH} source_url=${ASDF_PLUGIN_SOURCE_URL}"

View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
echo "plugin-remove ${ASDF_PLUGIN_PATH}"

View File

@ -19,8 +19,75 @@ teardown() {
[ "$output" = "elixir" ]
}
@test "plugin_add command with URL specified adds a plugin using repo" {
install_mock_plugin_repo "dummy"
run asdf plugin-add "dummy" "${BASE_DIR}/repo-dummy"
[ "$status" -eq 0 ]
run asdf plugin-list
# whitespace between 'elixir' and url is from printf %-15s %s format
[ "$output" = "dummy" ]
}
@test "plugin_add command with no URL specified fails if the plugin doesn't exist" {
run asdf plugin-add "does-not-exist"
[ "$status" -eq 1 ]
echo "$output" | grep "plugin does-not-exist not found in repository"
}
@test "plugin_add command executes configured pre hook (generic)" {
install_mock_plugin_repo "dummy"
cat > $HOME/.asdfrc <<-'EOM'
pre_asdf_plugin_add = echo ADD ${@}
EOM
run asdf plugin-add "dummy" "${BASE_DIR}/repo-dummy"
local expected_output="ADD dummy
plugin-add path=${ASDF_DIR}/plugins/dummy source_url=${BASE_DIR}/repo-dummy"
[ "$output" = "${expected_output}" ]
}
@test "plugin_add command executes configured pre hook (specific)" {
install_mock_plugin_repo "dummy"
cat > $HOME/.asdfrc <<-'EOM'
pre_asdf_plugin_add_dummy = echo ADD
EOM
run asdf plugin-add "dummy" "${BASE_DIR}/repo-dummy"
local expected_output="ADD
plugin-add path=${ASDF_DIR}/plugins/dummy source_url=${BASE_DIR}/repo-dummy"
[ "$output" = "${expected_output}" ]
}
@test "plugin_add command executes configured post hook (generic)" {
install_mock_plugin_repo "dummy"
cat > $HOME/.asdfrc <<-'EOM'
post_asdf_plugin_add = echo ADD ${@}
EOM
run asdf plugin-add "dummy" "${BASE_DIR}/repo-dummy"
local expected_output="plugin-add path=${ASDF_DIR}/plugins/dummy source_url=${BASE_DIR}/repo-dummy
ADD dummy"
[ "$output" = "${expected_output}" ]
}
@test "plugin_add command executes configured post hook (specific)" {
install_mock_plugin_repo "dummy"
cat > $HOME/.asdfrc <<-'EOM'
post_asdf_plugin_add_dummy = echo ADD
EOM
run asdf plugin-add "dummy" "${BASE_DIR}/repo-dummy"
local expected_output="plugin-add path=${ASDF_DIR}/plugins/dummy source_url=${BASE_DIR}/repo-dummy
ADD"
[ "$output" = "${expected_output}" ]
}

View File

@ -15,7 +15,7 @@ teardown() {
run asdf plugin-remove "dummy"
[ "$status" -eq 0 ]
[ "$output" = "" ]
[ "$output" = "plugin-remove ${ASDF_DIR}/plugins/dummy" ]
}
@test "plugin_remove_command should exit with 1 when not passed any arguments" {
@ -66,3 +66,59 @@ teardown() {
# unrelated shim should exist
[ -f $ASDF_DIR/shims/gummy ]
}
@test "plugin_remove_command executes configured pre hook (generic)" {
install_dummy_plugin
cat > $HOME/.asdfrc <<-'EOM'
pre_asdf_plugin_remove = echo REMOVE ${@}
EOM
run asdf plugin-remove dummy
local expected_output="REMOVE dummy
plugin-remove ${ASDF_DIR}/plugins/dummy"
[ "$output" = "${expected_output}" ]
}
@test "plugin_remove_command executes configured pre hook (specific)" {
install_dummy_plugin
cat > $HOME/.asdfrc <<-'EOM'
pre_asdf_plugin_remove_dummy = echo REMOVE
EOM
run asdf plugin-remove dummy
local expected_output="REMOVE
plugin-remove ${ASDF_DIR}/plugins/dummy"
[ "$output" = "${expected_output}" ]
}
@test "plugin_remove_command executes configured post hook (generic)" {
install_dummy_plugin
cat > $HOME/.asdfrc <<-'EOM'
post_asdf_plugin_remove = echo REMOVE ${@}
EOM
run asdf plugin-remove dummy
local expected_output="plugin-remove ${ASDF_DIR}/plugins/dummy
REMOVE dummy"
[ "$output" = "${expected_output}" ]
}
@test "plugin_remove_command executes configured post hook (specific)" {
install_dummy_plugin
cat > $HOME/.asdfrc <<-'EOM'
post_asdf_plugin_remove_dummy = echo REMOVE
EOM
run asdf plugin-remove dummy
local expected_output="plugin-remove ${ASDF_DIR}/plugins/dummy
REMOVE"
[ "$output" = "${expected_output}" ]
}

View File

@ -27,6 +27,15 @@ install_mock_plugin() {
cp -r "$BATS_TEST_DIRNAME/fixtures/dummy_plugin" "$location/plugins/$plugin_name"
}
install_mock_plugin_repo() {
local plugin_name=$1
local location="${BASE_DIR}/repo-${plugin_name}"
cp -r "$BATS_TEST_DIRNAME/fixtures/dummy_plugin" "${location}"
git -C "${location}" init -q
git -C "${location}" add -A
git -C "${location}" commit -q -m 'asdf dummy plugin'
}
install_mock_plugin_version() {
local plugin_name=$1
local plugin_version=$2