Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Improve asdf update experience #1601

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ asdf shim-versions <command> List the plugins and versions that
provide a command
asdf update Update asdf to the latest stable release
asdf update --head Update asdf to the latest on the master branch
asdf update --interactive|-i Update asdf interactively, choosing from versioned local git tags
asdf update <ref> Update asdf to specified ref

RESOURCES
GitHub: https://github.com/asdf-vm/asdf
Expand Down
79 changes: 60 additions & 19 deletions lib/commands/command-update.bash
Original file line number Diff line number Diff line change
@@ -1,44 +1,66 @@
# -*- sh -*-

update_command() {
local update_to_head=$1
local arg=$1

(
cd "$(asdf_dir)" || exit 1
local asdf_dir=
asdf_dir=$(asdf_dir)
cd "$asdf_dir" || exit 1

if [ -f asdf_updates_disabled ] || ! git rev-parse --is-inside-work-tree &>/dev/null; then
printf "Update command disabled. Please use the package manager that you used to install asdf to upgrade asdf.\n"
exit 42
else
do_update "$update_to_head"
fi

local ref=
case $arg in
--head)
ref='--head'
;;
--interactive | -i)
source "$asdf_dir/lib/vendor/bash-term.bash"
source "$asdf_dir/lib/utils-tty.bash"

local -a tags=()
readarray -d $'\n' -t tags <<<"$(print_tags | tac)"
tty.array_select "${tags[0]}" tags
local tag="$REPLY"

ref=$tag
;;
*)
if [ -n "$1" ]; then
ref="$1"

if ! git rev-parse --verify "$ref"; then
display_error "String '$ref' is not a valid git ref"
exit 1
fi
else
echo vvvv "$ref" >&3
ref=$(print_tags --fetch | sed '$!d') || exit 1
fi
;;
esac

do_update "$ref"
)
}

do_update() {
local update_to_head=$1
local ref=$1

if [ "$update_to_head" = "--head" ]; then
if [ "$ref" = "--head" ]; then
# Update to latest on the master branch
git fetch origin master
git checkout master
git reset --hard origin/master
printf "Updated asdf to latest on the master branch\n"
else
# Update to latest release
git fetch origin --tags || exit 1

if [ "$(get_asdf_config_value "use_release_candidates")" = "yes" ]; then
# Use the latest tag whether or not it is an RC
tag=$(git tag | sort_versions | sed '$!d') || exit 1
else
# Exclude RC tags when selecting latest tag
tag=$(git tag | sort_versions | grep -vi "rc" | sed '$!d') || exit 1
fi

# Update
git checkout "$tag" || exit 1
printf "Updated asdf to release %s\n" "$tag"
git checkout "$ref" || exit 1
printf "Updated asdf to release or ref: %s\n" "$ref"
fi
}

Expand All @@ -48,4 +70,23 @@ sort_versions() {
LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5n | awk '{print $2}'
}

print_tags() {
local should_fetch=$1

if [ "$should_fetch" = '--fetch' ]; then
local default_branch='master'
local remote=
remote=$(git config "branch.$default_branch.remote") || exit 1
git fetch "$remote" --tags || exit 1
fi

if [ "$(get_asdf_config_value "use_release_candidates")" = "yes" ]; then
# Use the latest tag whether or not it is an RC
git tag | sort_versions || exit 1
else
# Exclude RC tags when selecting latest tag
git tag | sort_versions | grep -vi "rc" || exit 1
fi
}

update_command "$@"
248 changes: 248 additions & 0 deletions lib/utils-tty.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
# shellcheck shell=bash

tty.fullscreen_init() {
stty -echo
term.cursor_hide -p
term.cursor_savepos -p
term.screen_save -p

term.erase_saved_lines -p
read -r g_tty_height g_tty_width < <(stty size)
}

tty.fullscreen_deinit() {
term.screen_restore -p
term.cursor_restorepos -p
term.cursor_show -p
stty echo
}

tty.all_save() {
term.cursor_savepos -p
term.screen_save -p
}

tty.all_restore() {
term.screen_restore -p
term.cursor_restorepos -p
}

# backwards
tty._backwards_all() {
value_idx=0
}

tty._backwards_full_screen() {
if ((value_idx - g_tty_height > 0)); then
value_idx=$((value_idx - g_tty_height))
else
value_idx=0
fi
}

tty._backwards_half_screen() {
if ((value_idx - (g_tty_height/2) > 0)); then
value_idx=$((value_idx - (g_tty_height/2)))
else
value_idx=0
fi
}

tty._backwards_one() {
if ((value_idx > 0)); then
value_idx=$((value_idx-1))
fi
}

# forwards
tty._forwards_full_screen() {
local array_length=$1

if ((value_idx + g_tty_height < array_length)); then
value_idx=$((value_idx + g_tty_height))
else
value_idx=$((array_length-1))
fi
}

tty._forwards_half_screen() {
local array_length=$1

if ((value_idx + (g_tty_height/2) < array_length)); then
value_idx=$((value_idx + (g_tty_height/2)))
else
value_idx=$((array_length-1))
fi
}

tty._forwards_one() {
local array_length=$1

if ((value_idx+1 < array_length)); then
value_idx=$((value_idx+1))
fi
}

tty._forwards_all() {
local array_length=$1

value_idx=$((array_length-1))
}

tty._print_list() {
local index="$1"
if ! shift; then
display_error 'Failed to shift'
exit 1
fi

# index represents the center (ex. 17)

local start=$((index - (g_tty_height / 2)))
local end=$((start + g_tty_height))

term.cursor_to -p 0 0

local i=
local str=
local prefix=
for ((i=start; i<end; i++)); do
if ((i != start)); then
term.cursor_down -p 1
fi

if ((index+1 == i)); then
prefix='> '
else
prefix=' '
fi

# Greater than zero since "$0"
if ((i > 0 && i<$#+1)); then
str="${prefix}${*:$i:1}"
else
str="${prefix}\033[1;30m~\033[0m"
fi

printf '\r'
term.erase_line_end -p
# shellcheck disable=SC2059
printf "$str"
done; unset -v i
}

tty.array_select() {
unset -v REPLY; REPLY=
local initial_value="$1"
local arr_name="$2"
local -n arr="$arr_name"

if (( ${#arr[@]} == 0)); then
display_error "Array must not be empty"
exit 1
fi

local value_is_in_array=no
local value_idx=
local i=
for ((i=0; i < ${#arr[@]}; i++)); do
if [ "${arr[$i]}" = "$initial_value" ]; then
value_is_in_array=yes
value_idx=$i
break
fi
done; unset -v i
if [ "$value_is_in_array" = 'no' ]; then
display_error "Value '$initial_value' not found in array '$arr_name'"
exit 1
fi
unset -v value_is_in_array

declare -g g_tty_height
declare -g g_tty_width
tty.fullscreen_init
trap.sigint_tty() {
tty.fullscreen_deinit
}
trap.sigcont_tty() {
tty.fullscreen_init
}
trap 'trap.sigint_tty' 'EXIT'
trap 'trap.sigcont_tty' 'SIGCONT'

tty._print_list "$value_idx" "${arr[@]}"
while :; do
local key=
if ! read -rsN1 key; then
display_error 'Could not read input'
exit 1
fi

case $key in
g) tty._backwards_all ;;
$'\x02') tty._backwards_full_screen ;; # C-b
$'\x15') tty._backwards_half_screen ;; # C-u
k|$'\x10') tty._backwards_one ;; # k, C-p
$'\x06') tty._forwards_full_screen ${#arr[@]} ;; # C-f
$'\x04') tty._forwards_half_screen ${#arr[@]} ;; # C-d
j|$'\x0e') tty._forwards_one ${#arr[@]} ;; # j, C-n
G) tty._forwards_all ${#arr[@]} ;;
$'\n'|$'\x0d') break ;; # enter (success)
q|$'\x7f') # q, backspace (fail)
break
;;
$'\x1b') # escape
if ! read -rsN1 -t 0.1 key; then
# escape (fail)
break
fi

case $key in
$'\x5b')
if ! read -rsN1 -t 0.1 key; then
# escape (fail)
break
fi

case $key in
$'\x41') tty._backwards_one ;; # up
$'\x42') tty._forwards_one ${#arr[@]} ;; # down
$'\x43') tty._forwards_one ${#arr[@]} ;; # right
$'\x44') tty._backwards_one ;; # left
$'\x48') tty._backwards_all ;; # home
$'\x46') tty._forwards_all ${#arr[@]} ;; # end
$'\x35')
if ! read -rsN1 -t 0.1 key; then
# escape (fail)
break
fi

case $key in
$'\x7e') tty._backwards_full_screen ;; # pageup
esac
;;
$'\x36')
if ! read -rsN1 -t 0.1 key; then
# escape (fail)
break
fi

case "$key" in
$'\x7e') tty._forwards_full_screen ${#arr[@]} ;; # pagedown
esac
esac
;;
esac
;;
esac

tty._print_list "$value_idx" "${arr[@]}"
done
unset -v key
tty.fullscreen_deinit

trap - 'EXIT'
trap - 'SIGCONT'

REPLY=${arr[$value_idx]}
}
Loading
Loading