diff --git a/CHANGELOG.md b/CHANGELOG.md index 825fce75..d5228c81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,17 @@ Features +* Configurable command hooks from `.asdfrc` + Suppose a `foo` plugin is installed and provides a `bar` executable, + The following hooks will be executed when set: + + ```shell + post_asdf_install_foo = echo installed foo version ${1} + post_asdf_reshim_foo = echo reshimmed foo version ${1} + + pre_foo_bar = echo about to execute command bar from foo with args: ${@} + post_foo_bar = echo just executed command bar from foo with args: ${@} + ``` * New shim version meta-data allows shims to not depend on a particular plugin nor on its relative executable path (#431) Upgrading requires shim re-generation and should happen automatically by `asdf-exec`: diff --git a/bin/private/asdf-tool-exec b/bin/private/asdf-tool-exec index a8874835..dc34cdfa 100755 --- a/bin/private/asdf-tool-exec +++ b/bin/private/asdf-tool-exec @@ -35,19 +35,29 @@ if [ -z "$selected_version" ]; then fi if [ ! -z "$selected_version" ]; then - plugin=$(cut -d ' ' -f 1 <<< "$selected_version"); + plugin_name=$(cut -d ' ' -f 1 <<< "$selected_version"); version=$(cut -d ' ' -f 2- <<< "$selected_version"); - plugin_path=$(get_plugin_path "$plugin") + plugin_path=$(get_plugin_path "$plugin_name") - plugin_exec_env $plugin $version + plugin_exec_env $plugin_name $version executable_path=$(command -v "$shim_name") if [ -x "${plugin_path}/bin/exec-path" ]; then - install_path=$(find_install_path "$plugin" "$version") + install_path=$(find_install_path "$plugin_name" "$version") executable_path=$(get_custom_executable_path "${plugin_path}" "${install_path}" "${executable_path}") fi - exec "$executable_path" "${@:2}" + asdf_run_hook "pre_${plugin_name}_${shim_name}" "${@:2}" + pre_status=$? + if [ "$pre_status" -eq 0 ]; then + "$executable_path" "${@:2}" + exit_status=$? + fi + if [ "${exit_status:-${pre_status}}" -eq 0 ]; then + asdf_run_hook "post_${plugin_name}_${shim_name}" "${@:2}" + post_status=$? + fi + exit "${post_status:-${exit_status:-${pre_status}}}" fi ( diff --git a/lib/commands/install.sh b/lib/commands/install.sh index 76ad0d05..6d81bfa2 100644 --- a/lib/commands/install.sh +++ b/lib/commands/install.sh @@ -102,6 +102,7 @@ install_tool_version() { local exit_code=$? if [ $exit_code -eq 0 ]; then reshim_command "$plugin_name" "$full_version" + asdf_run_hook "post_asdf_install_${plugin_name}" "$full_version" else handle_failure "$install_path" fi diff --git a/lib/commands/reshim.sh b/lib/commands/reshim.sh index 39933aa1..cdd233be 100644 --- a/lib/commands/reshim.sh +++ b/lib/commands/reshim.sh @@ -21,6 +21,7 @@ reshim_command() { if [ "$full_version" != "" ]; then # generate for the whole package version generate_shims_for_version "$plugin_name" "$full_version" + asdf_run_hook "post_asdf_reshim_$plugin_name" "$full_version" else # generate for all versions of the package local plugin_installs_path @@ -31,8 +32,10 @@ reshim_command() { full_version_name=$(basename "$install" | sed 's/ref\-/ref\:/') generate_shims_for_version "$plugin_name" "$full_version_name" remove_obsolete_shims "$plugin_name" "$full_version_name" + asdf_run_hook "post_asdf_reshim_$plugin_name" "$full_version_name" done fi + } diff --git a/lib/utils.sh b/lib/utils.sh index 357028d0..881787f1 100644 --- a/lib/utils.sh +++ b/lib/utils.sh @@ -310,7 +310,7 @@ get_asdf_config_value_from_file() { fi local result - result=$(grep -E "^\\s*$key\\s*=" "$config_path" | awk -F '=' '{ gsub(/ /, "", $2); print $2 }') + result=$(grep -E "^\\s*$key\\s*=\\s*" "$config_path" | head | awk -F '=' '{print $2}' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') if [ -n "$result" ]; then echo "$result" fi @@ -540,3 +540,15 @@ shim_plugin_versions() { } +asdf_run_hook() { + local hook_name=$1 + local hook_cmd + hook_cmd="$(get_asdf_config_value "$hook_name")" + if [ -n "$hook_cmd" ]; then + asdf_hook_fun() { + unset asdf_hook_fun + ev'al' "$hook_cmd" # ignore banned command just here + } + asdf_hook_fun "${@:2}" + fi +} diff --git a/test/install_command.bats b/test/install_command.bats index 020a8c1f..1b7253b3 100644 --- a/test/install_command.bats +++ b/test/install_command.bats @@ -138,3 +138,12 @@ teardown() { [ "$status" -eq 0 ] [ ! -f $ASDF_DIR/installs/dummy/system/version ] } + +@test "install command executes configured post plugin install hook" { + cat > $HOME/.asdfrc <<-'EOM' +post_asdf_install_dummy = eval echo HEY $version FROM $plugin_name +EOM + + run install_command dummy 1.0 + [ "$output" == "HEY 1.0 FROM dummy" ] +} diff --git a/test/reshim_command.bats b/test/reshim_command.bats index 991bfbe3..054b8e9b 100644 --- a/test/reshim_command.bats +++ b/test/reshim_command.bats @@ -98,3 +98,14 @@ teardown() { [ "$status" -eq 0 ] [ "1" -eq "$(ls $ASDF_DIR/shims/dummy* | wc -l)" ] } + +@test "reshim command executes configured post hook" { + run install_command dummy 1.0 + + cat > $HOME/.asdfrc <<-'EOM' +post_asdf_reshim_dummy = echo RESHIM +EOM + + run reshim_command dummy 1.0 + [ "$output" == "RESHIM" ] +} diff --git a/test/shim_exec.bats b/test/shim_exec.bats index 15840e02..109ab153 100644 --- a/test/shim_exec.bats +++ b/test/shim_exec.bats @@ -279,3 +279,65 @@ teardown() { run $ASDF_DIR/shims/dummy [ "$output" == "CUSTOM" ] } + +@test "shim exec executes configured pre-hook" { + run install_command dummy 1.0 + echo dummy 1.0 > $PROJECT_DIR/.tool-versions + + cat > $HOME/.asdfrc <<-'EOM' +pre_dummy_dummy = echo PRE $version $1 $2 +EOM + + run $ASDF_DIR/shims/dummy hello world + [ "$status" -eq 0 ] + echo "$output" | grep "PRE 1.0 hello world" + echo "$output" | grep "This is Dummy 1.0! world hello" +} + +@test "shim exec doesnt execute command if pre-hook failed" { + run install_command dummy 1.0 + echo dummy 1.0 > $PROJECT_DIR/.tool-versions + + mkdir $HOME/hook + pre_cmd="$HOME/hook/pre" + echo 'echo $* && false' > "$pre_cmd" + chmod +x "$pre_cmd" + + cat > $HOME/.asdfrc <<'EOM' +pre_dummy_dummy = pre $1 no $plugin_name $2 +EOM + + run env PATH=$PATH:$HOME/hook $ASDF_DIR/shims/dummy hello world + [ "$output" == "hello no dummy world" ] + [ "$status" -eq 1 ] +} + +@test "shim exec executes configured post-hook if command was successful" { + run install_command dummy 1.0 + echo dummy 1.0 > $PROJECT_DIR/.tool-versions + + cat > $HOME/.asdfrc <<-'EOM' +post_dummy_dummy = echo POST $version $1 $2 +EOM + + run $ASDF_DIR/shims/dummy hello world + [ "$status" -eq 0 ] + echo "$output" | grep "This is Dummy 1.0! world hello" + echo "$output" | grep "POST 1.0 hello world" +} + +@test "shim exec does not executes configured post-hook if command failed" { + run install_command dummy 1.0 + echo dummy 1.0 > $PROJECT_DIR/.tool-versions + + cat > $HOME/.asdfrc <<-'EOM' +post_dummy_dummy = echo POST +EOM + + echo "false" > $ASDF_DIR/installs/dummy/1.0/bin/dummy + chmod +x $ASDF_DIR/installs/dummy/1.0/bin/dummy + + run $ASDF_DIR/shims/dummy hello world + [ "$status" -eq 1 ] + [ "$output" == "" ] +}