diff --git a/docs/plugins/create.md b/docs/plugins/create.md index 4c61577b6..b900622d1 100644 --- a/docs/plugins/create.md +++ b/docs/plugins/create.md @@ -136,6 +136,19 @@ See also the related hooks: - `post_asdf_plugin_add` - `post_asdf_plugin_add_${plugin_name}` +#### bin/post-plugin-update + +This can be used to run any post-plugin-update actions after asdf has downloaded the updated plugin + +The script has access to the path the plugin was installed (`${ASDF_PLUGIN_PATH}`), previous git-ref (`${ASDF_PLUGIN_PREV_REF}`), and updated git-ref (`${ASDF_PLUGIN_POST_REF}`). + +See also the related hooks: + +- `pre_asdf_plugin_updated` +- `pre_asdf_plugin_updated_${plugin_name}` +- `post_asdf_plugin_updated` +- `post_asdf_plugin_updated_${plugin_name}` + #### bin/pre-plugin-remove This can be used to run any pre-removal actions before the plugin will be removed from asdf. diff --git a/lib/commands/command-plugin-update.bash b/lib/commands/command-plugin-update.bash index acabb9256..8819bc9f8 100644 --- a/lib/commands/command-plugin-update.bash +++ b/lib/commands/command-plugin-update.bash @@ -32,10 +32,32 @@ update_plugin() { plugin_remote_default_branch=$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" ls-remote --symref origin HEAD | awk '{ sub(/refs\/heads\//, ""); print $2; exit }') local gitref=${3:-${plugin_remote_default_branch}} logfile=$(mktemp) + + local common_git_options=(--git-dir "$plugin_path/.git" --work-tree "$plugin_path") + local prev_ref= + local post_ref= { + asdf_run_hook "pre_asdf_plugin_update" "$plugin_name" + asdf_run_hook "pre_asdf_plugin_update_${plugin_name}" + printf "Updating %s to %s\\n" "$plugin_name" "$gitref" - git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" fetch --prune --update-head-ok origin "$gitref:$gitref" - git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" -c advice.detachedHead=false checkout --force "$gitref" + + git "${common_git_options[@]}" fetch --prune --update-head-ok origin "$gitref:$gitref" + prev_ref=$(git "${common_git_options[@]}" rev-parse --short HEAD) + post_ref=$(git "${common_git_options[@]}" rev-parse --short "${gitref}") + git "${common_git_options[@]}" -c advice.detachedHead=false checkout --force "$gitref" + + if [ -f "${plugin_path}/bin/post-plugin-update" ]; then + ( + export ASDF_PLUGIN_PATH=$plugin_path + export ASDF_PLUGIN_PREV_REF=$prev_ref + export ASDF_PLUGIN_POST_REF=$post_ref + "${plugin_path}/bin/post-plugin-update" + ) + fi + + asdf_run_hook "post_asdf_plugin_update" "$plugin_name" + asdf_run_hook "post_asdf_plugin_update_${plugin_name}" } >"$logfile" 2>&1 cat "$logfile" rm "$logfile" diff --git a/test/fixtures/dummy_plugin/bin/post-plugin-update b/test/fixtures/dummy_plugin/bin/post-plugin-update new file mode 100755 index 000000000..d0e216c65 --- /dev/null +++ b/test/fixtures/dummy_plugin/bin/post-plugin-update @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +echo "plugin updated path=${ASDF_PLUGIN_PATH} old git-ref=${ASDF_PLUGIN_PREV_REF} new git-ref=${ASDF_PLUGIN_POST_REF}" diff --git a/test/plugin_update_command.bats b/test/plugin_update_command.bats index 3769c70f9..cb6e0aaec 100644 --- a/test/plugin_update_command.bats +++ b/test/plugin_update_command.bats @@ -119,3 +119,105 @@ teardown() { run bash -c "${command} >/dev/null && ps -o 'ppid,args' | awk '{if(\$1==1 && \$0 ~ /${command}/ ) print}' | wc -l" [[ 0 -eq "$output" ]] } + +@test "asdf plugin-update executes post-plugin update script" { + local plugin_path + plugin_path="$(get_plugin_path dummy)" + + old_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + run asdf plugin-update dummy + new_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + + local expected_output="plugin updated path=${plugin_path} old git-ref=${old_ref} new git-ref=${new_ref}" + [[ "$output" = *"${expected_output}" ]] +} + +@test "asdf plugin-update executes post-plugin update script if git-ref updated" { + local plugin_path + plugin_path="$(get_plugin_path dummy)" + + old_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + + # setup mock plugin remote + install_mock_plugin_repo "dummy-remote" + remote_dir="$BASE_DIR/repo-dummy-remote" + # set HEAD to refs/head/main in dummy-remote + git -C "${remote_dir}" checkout -b main + # track & fetch remote repo (dummy-remote) in plugin (dummy) + git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" remote remove origin + git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" remote add origin "$remote_dir" + git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" fetch origin + + # update plugin to the default branch + run asdf plugin-update dummy + new_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + + local expected_output="plugin updated path=${plugin_path} old git-ref=${old_ref} new git-ref=${new_ref}" + [[ "$output" = *"${expected_output}" ]] +} + +@test "asdf plugin-update executes configured pre hook (generic)" { + cat >$HOME/.asdfrc <<-'EOM' +pre_asdf_plugin_update = echo UPDATE ${@} +EOM + + local plugin_path + plugin_path="$(get_plugin_path dummy)" + + old_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + run asdf plugin-update dummy + new_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + + local expected_output="plugin updated path=${plugin_path} old git-ref=${old_ref} new git-ref=${new_ref}" + [[ "$output" = "UPDATE dummy"*"${expected_output}" ]] +} + +@test "asdf plugin-update executes configured pre hook (specific)" { + cat >$HOME/.asdfrc <<-'EOM' +pre_asdf_plugin_update_dummy = echo UPDATE +EOM + + local plugin_path + plugin_path="$(get_plugin_path dummy)" + + old_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + run asdf plugin-update dummy + new_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + + local expected_output="plugin updated path=${plugin_path} old git-ref=${old_ref} new git-ref=${new_ref}" + [[ "$output" = "UPDATE"*"${expected_output}" ]] +} + +@test "asdf plugin-update executes configured post hook (generic)" { + cat >$HOME/.asdfrc <<-'EOM' +post_asdf_plugin_update = echo UPDATE ${@} +EOM + + local plugin_path + plugin_path="$(get_plugin_path dummy)" + + old_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + run asdf plugin-update dummy + new_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + + local expected_output="plugin updated path=${plugin_path} old git-ref=${old_ref} new git-ref=${new_ref} +UPDATE dummy" + [[ "$output" = *"${expected_output}" ]] +} + +@test "asdf plugin-update executes configured post hook (specific)" { + cat >$HOME/.asdfrc <<-'EOM' +post_asdf_plugin_update_dummy = echo UPDATE +EOM + + local plugin_path + plugin_path="$(get_plugin_path dummy)" + + old_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + run asdf plugin-update dummy + new_ref="$(git --git-dir "$plugin_path/.git" --work-tree "$plugin_path" rev-parse --short HEAD)" + + local expected_output="plugin updated path=${plugin_path} old git-ref=${old_ref} new git-ref=${new_ref} +UPDATE" + [[ "$output" = *"${expected_output}" ]] +}