From f24a1f33b0c5e03d2583dab6875250075bcb42b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 11:51:03 -0400 Subject: [PATCH 01/42] chore(deps): bump amannn/action-semantic-pull-request from 5.1.0 to 5.2.0 (#1505) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/semantic-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semantic-pr.yml b/.github/workflows/semantic-pr.yml index d5216b647..8b26fa428 100644 --- a/.github/workflows/semantic-pr.yml +++ b/.github/workflows/semantic-pr.yml @@ -11,7 +11,7 @@ jobs: semantic-pr: runs-on: ubuntu-latest steps: - - uses: amannn/action-semantic-pull-request@v5.1.0 + - uses: amannn/action-semantic-pull-request@v5.2.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: From 58611c7ba412bc44dccebde8c1eed452f0361c92 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Mar 2023 00:49:10 +0000 Subject: [PATCH 02/42] chore(deps): bump asdf-vm/actions from 1 to 2 (#1504) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c39b5619f..177a52905 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v3 - name: Install asdf dependencies - uses: asdf-vm/actions/install@v1 + uses: asdf-vm/actions/install@v2 - name: Run ShellCheck run: scripts/shellcheck.bash @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@v3 - name: Install asdf dependencies - uses: asdf-vm/actions/install@v1 + uses: asdf-vm/actions/install@v2 - name: List file to shfmt run: shfmt -f . From 3379af845ed2e281703bc0e9e4f388a7845edc2a Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Mon, 20 Mar 2023 22:06:57 -0700 Subject: [PATCH 03/42] fix!: rework POSIX entrypoint for greater shell support (#1480) --- asdf.sh | 100 ++++++++++++++++++-------- docs/guide/getting-started.md | 33 +++++++++ docs/pt-br/guide/getting-started.md | 33 +++++++++ docs/zh-hans/guide/getting-started.md | 33 +++++++++ lib/asdf.sh | 22 +++--- scripts/format.bash | 6 +- scripts/shellcheck.bash | 7 +- scripts/shfmt.bash | 6 +- 8 files changed, 187 insertions(+), 53 deletions(-) diff --git a/asdf.sh b/asdf.sh index 7a01f5e8c..d7dd4c7e6 100644 --- a/asdf.sh +++ b/asdf.sh @@ -1,37 +1,77 @@ -# For Korn shells (ksh, mksh, etc.), capture $_ (the final parameter passed to -# the last command) straightaway, as it will contain the path to this script. -# For Bash, ${BASH_SOURCE[0]} will be used to obtain this script's path. -# For Zsh and others, $0 (the path to the shell or script) will be used. -_under="$_" -if [ -z "${ASDF_DIR:-}" ]; then - if [ -n "${BASH_SOURCE[0]}" ]; then - current_script_path="${BASH_SOURCE[0]}" - elif [[ "$_under" == *".sh" ]]; then - current_script_path="$_under" - else - current_script_path="$0" +# shellcheck shell=sh +# shellcheck disable=SC1007 + +# This file is the entrypoint for all POSIX-compatible shells. If `ASDF_DIR` is +# not already set, this script is able to calculate it, but only if the shell is +# either Bash, Zsh, and Ksh. For other shells, `ASDF_DIR` must be manually set. + +export ASDF_DIR="${ASDF_DIR:-}" + +if [ -z "$ASDF_DIR" ]; then + if [ -n "$BASH_VERSION" ]; then + # Use BASH_SOURCE[0] to obtain the relative path to this source'd file. Since it's + # a relative path, 'cd' to its dirname and use '$PWD" to obtain the fullpath. + # Use 'builtin cd' to ensure user-defined 'cd()' functions aren't called. + # Use variable '_asdf_old_dir' to avoid using subshells. + + _asdf_old_dir=$PWD + # shellcheck disable=SC3028,SC3054 + if ! CDPATH= builtin cd -- "${BASH_SOURCE[0]%/*}"; then + printf '%s\n' 'asdf: Error: Failed to cd' >&2 + unset -v _asdf_old_dir + return 1 + fi + ASDF_DIR=$PWD + if ! CDPATH= builtin cd -- "$_asdf_old_dir"; then + printf '%s\n' 'asdf: Error: Failed to cd' >&2 + unset -v _asdf_old_dir + return 1 + fi + unset -v _asdf_old_dir + elif [ -n "$ZSH_VERSION" ]; then + # Use '%x' to expand to path of current file. It must be prefixed + # with '(%):-', so it expands in non-prompt-string contexts. + + # shellcheck disable=SC2296 + ASDF_DIR=${(%):-%x} + ASDF_DIR=${ASDF_DIR%/*} + elif [ -n "$KSH_VERSION" ] && [ -z "$PATHSEP" ]; then + # Only the original KornShell (kornshell.com) has a '.sh.file' variable with the path + # of the current file. To prevent errors with other variations, such as the MirBSD + # Korn shell (mksh), test for 'PATHSEP' which is _not_ set on the original Korn Shell. + + # shellcheck disable=SC2296 + ASDF_DIR=${.sh.file} + ASDF_DIR=${ASDF_DIR%/*} fi +fi - ASDF_DIR="$(dirname "$current_script_path")" +if [ -z "$ASDF_DIR" ]; then + printf "%s\n" "asdf: Error: Source directory could not be calculated. Please set it manually before sourcing this file." >&2 + return 1 fi -export ASDF_DIR -# shellcheck disable=SC2016 -[ -d "$ASDF_DIR" ] || printf "%s\n" "$ASDF_DIR is not a directory" - -# Add asdf to PATH -# -# if in $PATH, remove, regardless of if it is in the right place (at the front) or not. -# replace all occurrences - ${parameter//pattern/string} -ASDF_BIN="${ASDF_DIR}/bin" -ASDF_USER_SHIMS="${ASDF_DATA_DIR:-$HOME/.asdf}/shims" -[[ ":$PATH:" == *":${ASDF_BIN}:"* ]] && PATH="${PATH//$ASDF_BIN:/}" -[[ ":$PATH:" == *":${ASDF_USER_SHIMS}:"* ]] && PATH="${PATH//$ASDF_USER_SHIMS:/}" -# add to front of $PATH -PATH="${ASDF_BIN}:$PATH" -PATH="${ASDF_USER_SHIMS}:$PATH" + +if [ ! -d "$ASDF_DIR" ]; then + printf "%s\n" "asdf: Error: Variable '\$ASDF_DIR' is not a directory: $ASDF_DIR" >&2 + return 1 +fi + +_asdf_bin="${ASDF_DIR}/bin" +_asdf_shims="${ASDF_DATA_DIR:-$HOME/.asdf}/shims" + +# shellcheck disable=SC3060 +if [ -n "$BASH_VERSION" ] || [ -n "$ZSH_VERSION" ]; then + case ":$PATH:" in + *":${_asdf_bin}:"*) PATH="${PATH//$_asdf_bin:/}" ;; + esac + case ":$PATH:" in + *":${_asdf_shims}:"*) PATH="${PATH//$_asdf_shims:/}" ;; + esac +fi + +PATH="${_asdf_bin}:${_asdf_shims}:$PATH" +unset -v _asdf_bin _asdf_shims # shellcheck source=lib/asdf.sh -# Load the asdf wrapper function . "${ASDF_DIR}/lib/asdf.sh" -unset _under current_script_path ASDF_BIN ASDF_USER_SHIMS diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md index 5ec756976..0a2acc21e 100644 --- a/docs/guide/getting-started.md +++ b/docs/guide/getting-started.md @@ -294,6 +294,39 @@ Add `asdf.nu` to your `~/.config/nushell/config.nu` with: Completions are automatically configured. ::: +::: details POSIX Shell & Git + +Add the following to `~/.profile`: + +```shell +export ASDF_DIR="$HOME/.asdf" +. "$HOME/.asdf/asdf.sh" +``` + +::: + +::: details POSIX Shell & Homebrew + +Add `asdf.sh` to your `~/.profile` with: + +```shell:no-line-numbers +echo -e "\nexport ASDF_DIR=\"$(brew --prefix asdf)/libexec/asdf.sh\"" >> ~/.profile +echo -e "\n. \"$(brew --prefix asdf)/libexec/asdf.sh\"" >> ~/.profile +``` + +::: + +::: details POSIX Shell & Pacman + +Add the following to `~/.profile`: + +```shell +export ASDF_DIR="/opt/asdf-vm" +. /opt/asdf-vm/asdf.sh +``` + +::: + `asdf` scripts need to be sourced **after** you have set your `$PATH` and **after** you have sourced your framework (oh-my-zsh etc). Restart your shell so that `PATH` changes take effect. Opening a new terminal tab will usually do it. diff --git a/docs/pt-br/guide/getting-started.md b/docs/pt-br/guide/getting-started.md index c57fb35c2..69d902b5d 100644 --- a/docs/pt-br/guide/getting-started.md +++ b/docs/pt-br/guide/getting-started.md @@ -262,6 +262,39 @@ Adicione a seguinte linha ao seu `~/.zshrc`: . /opt/asdf-vm/asdf.sh ``` +::: details POSIX Shell & Git + +Adicione a seguinte linha ao seu `~/.profile`: + +```shell +export ASDF_DIR="$HOME/.asdf" +. "$HOME/.asdf/asdf.sh" +``` + +::: + +::: details POSIX Shell & Homebrew + +Adicione `asdf.sh` ao `~/.profile` através do comando: + +```shell:no-line-numbers +echo -e "\nexport ASDF_DIR=\"$(brew --prefix asdf)/libexec/asdf.sh\"" >> ~/.profile +echo -e "\n. \"$(brew --prefix asdf)/libexec/asdf.sh\"" >> ~/.profile +``` + +::: + +::: details POSIX Shell & Pacman + +Adicione a seguinte linha ao seu `~/.profile`: + +```shell +export ASDF_DIR="/opt/asdf-vm" +. /opt/asdf-vm/asdf.sh +``` + +::: + O auto completar é colocado em um local familiar para o ZSH, [mas o ZSH deve ser configurado para conseguir utilizá-lo](https://wiki.archlinux.org/index.php/zsh#Command_completion). ::: diff --git a/docs/zh-hans/guide/getting-started.md b/docs/zh-hans/guide/getting-started.md index fb39a0b82..f77fbb603 100644 --- a/docs/zh-hans/guide/getting-started.md +++ b/docs/zh-hans/guide/getting-started.md @@ -263,6 +263,39 @@ echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc 补全功能会被放在一个对 ZSH 很友好的位置,但是 [ZSH 必须使用自动补全完成配置](https://wiki.archlinux.org/index.php/zsh#Command_completion)。 ::: +::: details POSIX Shell & Git + +在 `~/.profile` 文件中加入以下内容: + +```shell +export ASDF_DIR="$HOME/.asdf" +. "$HOME/.asdf/asdf.sh" +``` + +::: + +::: details POSIX Shell & Homebrew + +使用以下命令将 `asdf.sh` 加入到 `~/.profile` 文件中: + +```shell:no-line-numbers +echo -e "\nexport ASDF_DIR=\"$(brew --prefix asdf)/libexec/asdf.sh\"" >> ~/.profile +echo -e "\n. \"$(brew --prefix asdf)/libexec/asdf.sh\"" >> ~/.profile +``` + +::: + +::: details POSIX Shell & Pacman + +在 `~/.profile` 文件中加入以下内容: + +```shell +export ASDF_DIR="/opt/asdf-vm" +. /opt/asdf-vm/asdf.sh +``` + +::: + `asdf` 脚本需要在设置好的 `$PATH` **之后**和已经生效的框架(比如 oh-my-zsh 等等)**之后**的位置生效。 通常打开一个新的终端标签页来重启你的 shell 让 `PATH` 更改即时生效。 diff --git a/lib/asdf.sh b/lib/asdf.sh index f43aae581..e5404aa86 100644 --- a/lib/asdf.sh +++ b/lib/asdf.sh @@ -1,20 +1,20 @@ +# shellcheck shell=sh + # The asdf function is a wrapper so we can export variables asdf() { - local command - command="$1" - if [ "$#" -gt 0 ]; then - shift - fi - - case "$command" in + case $1 in "shell") - # commands that need to export variables + if ! shift; then + printf '%s\n' 'asdf: Error: Failed to shift' >&2 + return 1 + fi + + # Invoke command that needs to export variables. eval "$(asdf export-shell-version sh "$@")" # asdf_allow: eval ;; *) - # forward other commands to asdf script - command asdf "$command" "$@" # asdf_allow: ' asdf ' + # Forward other commands to asdf script. + command asdf "$@" # asdf_allow: ' asdf ' ;; - esac } diff --git a/scripts/format.bash b/scripts/format.bash index 5be8205a8..1a2eae631 100755 --- a/scripts/format.bash +++ b/scripts/format.bash @@ -3,10 +3,8 @@ set -euo pipefail # check .sh files -# TODO(jthegedus): unlock this check later -# TODO shfmt --language-dialect posix --indent 2 --write \ -# TODO asdf.sh \ -# TODO lib/*.sh +shfmt --language-dialect posix --indent 2 --write \ + lib/*.sh # check .bash files shfmt --language-dialect bash --indent 2 --write \ diff --git a/scripts/shellcheck.bash b/scripts/shellcheck.bash index 223af27ae..ca49bd4c0 100755 --- a/scripts/shellcheck.bash +++ b/scripts/shellcheck.bash @@ -3,10 +3,9 @@ set -euo pipefail # check .sh files -# TODO(jthegedus): unlock this check later -# TODO shellcheck --shell sh --external-sources \ -# TODO asdf.sh \ -# TODO lib/*.sh +shellcheck --shell sh --external-sources \ + asdf.sh \ + lib/*.sh # check .bash files shellcheck --shell bash --external-sources \ diff --git a/scripts/shfmt.bash b/scripts/shfmt.bash index 7f256b865..d5db82264 100755 --- a/scripts/shfmt.bash +++ b/scripts/shfmt.bash @@ -3,10 +3,8 @@ set -euo pipefail # check .sh files -# TODO(jthegedus): unlock this check later -# TODO shfmt --language-dialect posix --indent 2 --diff \ -# TODO asdf.sh \ -# TODO lib/*.sh +shfmt --language-dialect posix --indent 2 --diff \ + lib/*.sh # check .bash files shfmt --language-dialect bash --indent 2 --diff \ From c5b8b3c128b48e1531f6d03d2083435f413a4738 Mon Sep 17 00:00:00 2001 From: Andrea Jemmett <1787979+acidghost@users.noreply.github.com> Date: Tue, 21 Mar 2023 09:53:10 +0100 Subject: [PATCH 04/42] fix: nushell plugin list all (#1501) (#1502) --- asdf.nu | 2 +- test/asdf_nu.bats | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/asdf.nu b/asdf.nu index 092fd3bec..bf787128e 100644 --- a/asdf.nu +++ b/asdf.nu @@ -99,7 +99,7 @@ module asdf { # list all available plugins export def "asdf plugin list all" [] { - let template = '(?P.+)\s+?(?P[*]?)(?P(?:git|http).+\.git)' + let template = '(?P.+)\s+?(?P[*]?)(?P(?:git|http|https).+)' let is_installed = { |it| $it.installed == '*' } ^asdf plugin list all | diff --git a/test/asdf_nu.bats b/test/asdf_nu.bats index 9319e7eae..b93a6ea7e 100644 --- a/test/asdf_nu.bats +++ b/test/asdf_nu.bats @@ -9,6 +9,14 @@ setup() { if ! command -v nu; then skip "Nu is not installed" fi + + setup_asdf_dir + setup_repo + install_dummy_plugin +} + +teardown() { + clean_asdf_dir } cleaned_path() { @@ -110,3 +118,20 @@ cleaned_path() { result=$(echo "$output" | grep "ASDF INSTALLED PLUGINS:") [ "$result" != "" ] } + +@test "parses the output of asdf plugin list all" { + run nu -c " + hide-env -i asdf + hide-env -i ASDF_DIR + let-env PATH = ( '$(cleaned_path)' | split row ':' ) + let-env ASDF_NU_DIR = '$PWD' + + source asdf.nu + asdf plugin list all | to csv -n" + + [ "$status" -eq 0 ] + [ "$output" = "\ +bar,false,http://example.com/bar +dummy,true,http://example.com/dummy +foo,false,http://example.com/foo" ] +} From 49e541a29ff7a2f35917a4544a8b9adbc02bb1b4 Mon Sep 17 00:00:00 2001 From: Jing Date: Tue, 21 Mar 2023 17:03:50 +0800 Subject: [PATCH 05/42] docs: fix Nushell-Homebrew setup instructions (#1495) --- docs/guide/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md index 0a2acc21e..03edfaf11 100644 --- a/docs/guide/getting-started.md +++ b/docs/guide/getting-started.md @@ -277,7 +277,7 @@ Completions are automatically configured Add `asdf.nu` to your `~/.config/nushell/config.nu` with: ```shell:no-line-numbers -"\nlet-env ASDF_NU_DIR = (brew --prefix asdf | into string | path join 'libexec')\n source " + (brew --prefix asdf | into string | path join 'libexec/asdf.nu') | save --append $nu.config-path +"\nlet-env ASDF_NU_DIR = (brew --prefix asdf | str trim | into string | path join 'libexec')\n source " + (brew --prefix asdf | into string | path join 'libexec/asdf.nu') | save --append $nu.config-path ``` Completions are automatically configured From 9363fb2f72e7fa08d3580b22d465af48a7d37031 Mon Sep 17 00:00:00 2001 From: Andrea Jemmett <1787979+acidghost@users.noreply.github.com> Date: Thu, 23 Mar 2023 02:23:53 +0100 Subject: [PATCH 06/42] fix: Nushell plugin list --urls (#1507) --- asdf.nu | 11 ++-- lib/functions/plugins.bash | 10 ++-- lib/utils.bash | 21 +++++++ test/asdf_nu.bats | 115 ++++++++++++++++++++++--------------- 4 files changed, 100 insertions(+), 57 deletions(-) diff --git a/asdf.nu b/asdf.nu index bf787128e..e4a9313ef 100644 --- a/asdf.nu +++ b/asdf.nu @@ -79,8 +79,10 @@ module asdf { ] { let params = [ - {name: 'urls', enabled: $urls, template: '\s+?(?Pgit@.+\.git)', flag: '--urls'} - {name: 'refs', enabled: $refs, template: '\s+?(?P\w+)\s+(?P\w+)', flag: '--refs'} + {name: 'urls', enabled: $urls, flag: '--urls', + template: '\s+?(?P(?:http[s]?|git).+\.git|/.+)'} + {name: 'refs', enabled: $refs, flag: '--refs', + template: '\s+?(?P\w+)\s+(?P\w+)'} ] let template = '(?P.+)' + ( @@ -91,10 +93,9 @@ module asdf { str trim ) - let parsed_urls_flag = ($params | where enabled and name == 'urls' | get --ignore-errors flag | default '' ) - let parsed_refs_flag = ($params | where enabled and name == 'refs' | get --ignore-errors flag | default '' ) + let flags = ($params | where enabled | get --ignore-errors flag | default '' ) - ^asdf plugin list $parsed_urls_flag $parsed_refs_flag | lines | parse -r $template | str trim + ^asdf plugin list $flags | lines | parse -r $template | str trim } # list all available plugins diff --git a/lib/functions/plugins.bash b/lib/functions/plugins.bash index 18d50af11..3e2d5257f 100644 --- a/lib/functions/plugins.bash +++ b/lib/functions/plugins.bash @@ -28,15 +28,13 @@ plugin_list_command() { printf "%s" "$plugin_name" if [ -n "$show_repo" ]; then - printf "\t%s" "$(git --git-dir "$plugin_path/.git" remote get-url origin 2>/dev/null)" + printf "\t%s" "$(get_plugin_remote_url "$plugin_name")" fi if [ -n "$show_ref" ]; then - local branch - local gitref - branch=$(git --git-dir "$plugin_path/.git" rev-parse --abbrev-ref HEAD 2>/dev/null) - gitref=$(git --git-dir "$plugin_path/.git" rev-parse --short HEAD 2>/dev/null) - printf "\t%s\t%s" "$branch" "$gitref" + printf "\t%s\t%s" \ + "$(get_plugin_remote_branch "$plugin_name")" \ + "$(get_plugin_remote_gitref "$plugin_name")" fi printf "\n" diff --git a/lib/utils.bash b/lib/utils.bash index 862c4449a..5a78605c9 100644 --- a/lib/utils.bash +++ b/lib/utils.bash @@ -860,3 +860,24 @@ util_resolve_user_path() { util_resolve_user_path_reply="$path" fi } + +get_plugin_remote_url() { + local plugin_name="$1" + local plugin_path + plugin_path="$(get_plugin_path "$plugin_name")" + git --git-dir "$plugin_path/.git" remote get-url origin 2>/dev/null +} + +get_plugin_remote_branch() { + local plugin_name="$1" + local plugin_path + plugin_path="$(get_plugin_path "$plugin_name")" + git --git-dir "$plugin_path/.git" rev-parse --abbrev-ref HEAD 2>/dev/null +} + +get_plugin_remote_gitref() { + local plugin_name="$1" + local plugin_path + plugin_path="$(get_plugin_path "$plugin_name")" + git --git-dir "$plugin_path/.git" rev-parse --short HEAD 2>/dev/null +} diff --git a/test/asdf_nu.bats b/test/asdf_nu.bats index b93a6ea7e..da16bac1a 100644 --- a/test/asdf_nu.bats +++ b/test/asdf_nu.bats @@ -11,8 +11,6 @@ setup() { fi setup_asdf_dir - setup_repo - install_dummy_plugin } teardown() { @@ -23,7 +21,7 @@ cleaned_path() { echo "$PATH" | tr ':' '\n' | grep -v "asdf" | tr '\n' ':' } -@test "exports ASDF_DIR" { +run_nushell() { run nu -c " hide-env -i asdf hide-env -i ASDF_DIR @@ -31,8 +29,11 @@ cleaned_path() { let-env ASDF_NU_DIR = '$PWD' source asdf.nu + $1" +} - echo \$env.ASDF_DIR" +@test "exports ASDF_DIR" { + run_nushell "echo \$env.ASDF_DIR" [ "$status" -eq 0 ] result=$(echo "$output" | grep "asdf") @@ -40,16 +41,7 @@ cleaned_path() { } @test "adds asdf dirs to PATH" { - run nu -c " - hide-env -i asdf - hide-env -i ASDF_DIR - let-env PATH = ( '$(cleaned_path)' | split row ':' ) - let-env ASDF_NU_DIR = '$PWD' - - source asdf.nu - - - \$env.PATH | to text" + run_nushell "\$env.PATH | to text" [ "$status" -eq 0 ] @@ -58,15 +50,8 @@ cleaned_path() { } @test "does not add paths to PATH more than once" { - run nu -c " - hide-env -i asdf - hide-env -i ASDF_DIR - let-env PATH = ( '$(cleaned_path)' | split row ':' ) - let-env ASDF_NU_DIR = '$PWD' - - source asdf.nu + run_nushell " source asdf.nu - echo \$env.PATH" [ "$status" -eq 0 ] @@ -91,27 +76,13 @@ cleaned_path() { } @test "defines the asdf or main function" { - run nu -c " - hide-env -i asdf - hide-env -i ASDF_DIR - let-env PATH = ( '$(cleaned_path)' | split row ':' ) - let-env ASDF_NU_DIR = '$PWD' - - source asdf.nu - which asdf | get path | to text" + run_nushell "which asdf | get path | to text" [ "$status" -eq 0 ] } @test "function calls asdf command" { - run nu -c " - hide-env -i asdf - hide-env -i ASDF_DIR - let-env PATH = ( '$(cleaned_path)' | split row ':' ) - let-env ASDF_NU_DIR = '$PWD' - - source asdf.nu - asdf info" + run_nushell "asdf info" [ "$status" -eq 0 ] @@ -119,15 +90,67 @@ cleaned_path() { [ "$result" != "" ] } -@test "parses the output of asdf plugin list all" { - run nu -c " - hide-env -i asdf - hide-env -i ASDF_DIR - let-env PATH = ( '$(cleaned_path)' | split row ':' ) - let-env ASDF_NU_DIR = '$PWD' +@test "parses the output of asdf plugin list" { + setup_repo + install_dummy_plugin + run_nushell "asdf plugin list | to csv -n" - source asdf.nu - asdf plugin list all | to csv -n" + [ "$status" -eq 0 ] + [ "$output" = "dummy" ] +} + +@test "parses the output of asdf plugin list --urls" { + setup_repo + install_mock_plugin_repo "dummy" + asdf plugin add "dummy" "${BASE_DIR}/repo-dummy" + + run_nushell "asdf plugin list --urls | to csv -n" + + [ "$status" -eq 0 ] + + local repo_url + repo_url=$(get_plugin_remote_url "dummy") + + [ "$output" = "dummy,$repo_url" ] +} + +@test "parses the output of asdf plugin list --refs" { + setup_repo + install_mock_plugin_repo "dummy" + asdf plugin add "dummy" "${BASE_DIR}/repo-dummy" + + run_nushell "asdf plugin list --refs | to csv -n" + + [ "$status" -eq 0 ] + + local branch gitref + branch=$(get_plugin_remote_branch "dummy") + gitref=$(get_plugin_remote_gitref "dummy") + + [ "$output" = "dummy,$branch,$gitref" ] +} + +@test "parses the output of asdf plugin list --urls --refs" { + setup_repo + install_mock_plugin_repo "dummy" + asdf plugin add "dummy" "${BASE_DIR}/repo-dummy" + + run_nushell "asdf plugin list --urls --refs | to csv -n" + + [ "$status" -eq 0 ] + + local repo_url branch gitref + repo_url=$(get_plugin_remote_url "dummy") + branch=$(get_plugin_remote_branch "dummy") + gitref=$(get_plugin_remote_gitref "dummy") + + [ "$output" = "dummy,$repo_url,$branch,$gitref" ] +} + +@test "parses the output of asdf plugin list all" { + setup_repo + install_dummy_plugin + run_nushell "asdf plugin list all | to csv -n" [ "$status" -eq 0 ] [ "$output" = "\ From 05a8bb940a9ce1a83dcda2a2bf52dc3d0786bd54 Mon Sep 17 00:00:00 2001 From: James Hegedus Date: Fri, 24 Mar 2023 01:30:29 +0000 Subject: [PATCH 07/42] ci: fix typo in workflow step name (#1511) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9842726d7..ded80768b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -150,6 +150,6 @@ jobs: working-directory: docs/ run: npm install - - name: Check errors by biulding Documentation site + - name: Check errors by building Documentation site working-directory: docs/ run: npm run build From bbcbddcdd4ffa0f49c3772b66d87331420fa5727 Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Fri, 24 Mar 2023 05:37:23 -0700 Subject: [PATCH 08/42] fix: Better handling with paths that include spaces (#1485) --- bin/asdf | 14 +++++++++++--- lib/commands/command-plugin-remove.bash | 11 ++++++++++- lib/utils.bash | 2 +- test/reshim_command.bats | 2 +- test/shim_exec.bats | 2 ++ test/test_helpers.bash | 7 ++++--- 6 files changed, 29 insertions(+), 9 deletions(-) diff --git a/bin/asdf b/bin/asdf index 0693133da..666732fb4 100755 --- a/bin/asdf +++ b/bin/asdf @@ -49,7 +49,10 @@ find_asdf_cmd() { find_plugin_cmd() { local ASDF_CMD_FILE args_offset if [ -d "$(get_plugin_path "$1")/bin" ]; then - IFS=' ' read -r ASDF_CMD_FILE args_offset <<<"$(find_cmd "$(get_plugin_path "$1")/lib/commands" "${@:2}")" + local result= + result="$(find_cmd "$(get_plugin_path "$1")/lib/commands" "${@:2}")" + ASDF_CMD_FILE=${result% *} + args_offset=${result##* } if [ -n "$ASDF_CMD_FILE" ]; then args_offset=$((args_offset + 1)) # since the first argument is the plugin name printf "%s %s\\n" "$ASDF_CMD_FILE" "$args_offset" @@ -65,9 +68,14 @@ asdf_cmd() { exit 1 fi - IFS=' ' read -r ASDF_CMD_FILE args_offset <<<"$(find_asdf_cmd "$@")" + local result= + result="$(find_asdf_cmd "$@")" + ASDF_CMD_FILE=${result% *} + args_offset=${result##* } if [ -z "$ASDF_CMD_FILE" ]; then - IFS=' ' read -r ASDF_CMD_FILE args_offset <<<"$(find_plugin_cmd "$@")" + result="$(find_plugin_cmd "$@")" + ASDF_CMD_FILE=${result% *} + args_offset=${result##* } fi if [ -x "$ASDF_CMD_FILE" ]; then diff --git a/lib/commands/command-plugin-remove.bash b/lib/commands/command-plugin-remove.bash index e4cee0532..6441c665e 100644 --- a/lib/commands/command-plugin-remove.bash +++ b/lib/commands/command-plugin-remove.bash @@ -21,7 +21,16 @@ plugin_remove_command() { rm -rf "$(asdf_data_dir)/installs/${plugin_name}" rm -rf "$(asdf_data_dir)/downloads/${plugin_name}" - grep -l "asdf-plugin: ${plugin_name}" "$(asdf_data_dir)"/shims/* 2>/dev/null | xargs rm -f + local is_nullglob_disabled= + shopt -q nullglob || is_nullglob_disabled=yes + shopt -s nullglob + for f in "$(asdf_data_dir)"/shims/*; do + if grep -q "asdf-plugin: ${plugin_name}" "$f"; then + rm -f "$f" + fi + done + [ "$is_nullglob_disabled" = 'yes' ] && shopt -u nullglob + unset -v is_nullglob_disabled asdf_run_hook "post_asdf_plugin_remove" "$plugin_name" asdf_run_hook "post_asdf_plugin_remove_${plugin_name}" diff --git a/lib/utils.bash b/lib/utils.bash index 5a78605c9..2c856e07f 100644 --- a/lib/utils.bash +++ b/lib/utils.bash @@ -206,7 +206,7 @@ find_versions() { local legacy_filenames="" if [ "$legacy_config" = "yes" ] && [ -f "$legacy_list_filenames_script" ]; then - legacy_filenames=$($legacy_list_filenames_script) + legacy_filenames=$("$legacy_list_filenames_script") fi while [ "$search_path" != "/" ]; do diff --git a/test/reshim_command.bats b/test/reshim_command.bats index dd98c882b..4b2bd549e 100644 --- a/test/reshim_command.bats +++ b/test/reshim_command.bats @@ -4,7 +4,7 @@ load test_helpers setup() { - ASDF_BATS_SPACE_IN_PATH=true setup_asdf_dir + setup_asdf_dir install_dummy_plugin PROJECT_DIR="$HOME/project" diff --git a/test/shim_exec.bats b/test/shim_exec.bats index ad8a89603..838b1a9ef 100644 --- a/test/shim_exec.bats +++ b/test/shim_exec.bats @@ -206,6 +206,8 @@ teardown() { [ "$output" = "System" ] } +# NOTE: The name of this test is linked to a condition in `test_helpers.bash. See +# the 'setup_asdf_dir' function for details. @test "shim exec should use path executable when specified version path:" { run asdf install dummy 1.0 diff --git a/test/test_helpers.bash b/test/test_helpers.bash index 814742ce4..103da76cd 100644 --- a/test/test_helpers.bash +++ b/test/test_helpers.bash @@ -6,11 +6,12 @@ bats_require_minimum_version 1.7.0 . "$(dirname "$BATS_TEST_DIRNAME")"/lib/utils.bash setup_asdf_dir() { - if [ -n "${ASDF_BATS_SPACE_IN_PATH:-}" ]; then - BASE_DIR="$(mktemp -dt "asdf with spaces.XXXX")" + if [ "$BATS_TEST_NAME" = 'test_shim_exec_should_use_path_executable_when_specified_version_path-3a-3cpath-3e' ]; then + BASE_DIR="$(mktemp -dt "asdf_with_no_spaces.XXXX")" else - BASE_DIR="$(mktemp -dt asdf.XXXX)" + BASE_DIR="$(mktemp -dt "asdf with spaces.XXXX")" fi + HOME="$BASE_DIR/home" ASDF_DIR="$HOME/.asdf" mkdir -p "$ASDF_DIR/plugins" From ec3eb2d64f0531be86d10e1202a92f6b7820e294 Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Sat, 25 Mar 2023 23:31:33 -0700 Subject: [PATCH 09/42] docs: Improve wording of env vars section (#1514) Co-authored-by: James Hegedus --- docs/manage/configuration.md | 50 +++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/docs/manage/configuration.md b/docs/manage/configuration.md index 17e22f4d4..2e714b90d 100644 --- a/docs/manage/configuration.md +++ b/docs/manage/configuration.md @@ -50,9 +50,13 @@ To install a single tool defined in a `.tool-versions` file run `asdf install Date: Sun, 26 Mar 2023 15:28:16 -0700 Subject: [PATCH 10/42] fix: `asdf info` show BASH_VERSION & all asdf envs (#1513) --- lib/commands/command-info.bash | 9 +++++++-- test/info_command.bats | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/commands/command-info.bash b/lib/commands/command-info.bash index 9304ce687..d4e761cf4 100644 --- a/lib/commands/command-info.bash +++ b/lib/commands/command-info.bash @@ -4,9 +4,14 @@ info_command() { printf "%s:\n%s\n\n" "OS" "$(uname -a)" - printf "%s:\n%s\n\n" "SHELL" "$($SHELL --version)" + printf "%s:\n%s\n\n" "SHELL" "$("$SHELL" --version)" + printf "%s:\n%s\n\n" "BASH VERSION" "$BASH_VERSION" printf "%s:\n%s\n\n" "ASDF VERSION" "$(asdf_version)" - printf "%s:\n%s\n\n" "ASDF ENVIRONMENT VARIABLES" "$(env | grep -E "ASDF_DIR|ASDF_DATA_DIR|ASDF_CONFIG_FILE|ASDF_DEFAULT_TOOL_VERSIONS_FILENAME")" + printf '%s\n' 'ASDF INTERNAL VARIABLES:' + printf 'ASDF_DEFAULT_TOOL_VERSIONS_FILENAME=%s\n' "${ASDF_DEFAULT_TOOL_VERSIONS_FILENAME}" + printf 'ASDF_DATA_DIR=%s\n' "${ASDF_DATA_DIR}" + printf 'ASDF_DIR=%s\n' "${ASDF_DIR}" + printf 'ASDF_CONFIG_FILE=%s\n\n' "${ASDF_CONFIG_FILE}" printf "%s:\n%s\n\n" "ASDF INSTALLED PLUGINS" "$(plugin_list_command --urls --refs)" } diff --git a/test/info_command.bats b/test/info_command.bats index f456df1e3..3a8fc05d6 100644 --- a/test/info_command.bats +++ b/test/info_command.bats @@ -25,8 +25,9 @@ teardown() { [ "$status" -eq 0 ] [[ $output == *$'OS:\n'* ]] [[ $output == *$'SHELL:\n'* ]] + [[ $output == *$'BASH VERSION:\n'* ]] [[ $output == *$'ASDF VERSION:\n'* ]] - [[ $output == *$'ASDF ENVIRONMENT VARIABLES:\n'* ]] + [[ $output == *$'ASDF INTERNAL VARIABLES:\n'* ]] [[ $output == *$'ASDF INSTALLED PLUGINS:\n'* ]] } From 13c0e2fab0e9ad4dccf72b6f5586fb32458b8709 Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Sun, 26 Mar 2023 15:31:06 -0700 Subject: [PATCH 11/42] fix: lint & style errors in `bin/asdf` (#1516) --- bin/asdf | 16 ++++++++-------- scripts/checkstyle.py | 28 ++++++++++++++-------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/bin/asdf b/bin/asdf index 666732fb4..917a42357 100755 --- a/bin/asdf +++ b/bin/asdf @@ -16,9 +16,9 @@ find_cmd() { done if [ -f "$cmd_dir/$cmd_name" ]; then - printf "%s %s\\n" "$cmd_dir/$cmd_name" "$((args_offset + 1))" + printf "%s %s\n" "$cmd_dir/$cmd_name" "$((args_offset + 1))" elif [ -f "$cmd_dir/command.bash" ]; then - printf "%s %s\\n" "$cmd_dir/command.bash" 1 + printf "%s %s\n" "$cmd_dir/command.bash" 1 fi } @@ -29,15 +29,15 @@ find_asdf_cmd() { 'exec' | 'current' | 'env' | 'global' | 'install' | 'latest' | 'local' | \ 'reshim' | 'uninstall' | 'update' | 'where' | 'which' | \ 'export-shell-version') - printf "%s %s\\n" "$asdf_cmd_dir/command-$1.bash" 2 + printf "%s %s\n" "$asdf_cmd_dir/command-$1.bash" 2 ;; '' | '--help' | '-h' | 'help') - printf "%s %s\\n" "$asdf_cmd_dir/command-help.bash" 2 + printf "%s %s\n" "$asdf_cmd_dir/command-help.bash" 2 ;; '--version' | 'version') - printf "%s %s\\n" "$asdf_cmd_dir/command-version.bash" 2 + printf "%s %s\n" "$asdf_cmd_dir/command-version.bash" 2 ;; *) @@ -55,7 +55,7 @@ find_plugin_cmd() { args_offset=${result##* } if [ -n "$ASDF_CMD_FILE" ]; then args_offset=$((args_offset + 1)) # since the first argument is the plugin name - printf "%s %s\\n" "$ASDF_CMD_FILE" "$args_offset" + printf "%s %s\n" "$ASDF_CMD_FILE" "$args_offset" fi fi } @@ -63,7 +63,7 @@ find_plugin_cmd() { asdf_cmd() { local ASDF_CMD_FILE args_offset - if [ "shell" == "$1" ]; then + if [ "shell" = "$1" ]; then printf "Shell integration is not enabled. Please ensure you source asdf in your shell setup." >&2 exit 1 fi @@ -86,7 +86,7 @@ asdf_cmd() { else local asdf_cmd_dir asdf_cmd_dir="$(asdf_dir)/lib/commands" - printf "%s\\n" "Unknown command: \`asdf ${*}\`" >&2 + printf "%s\n" "Unknown command: \`asdf ${*}\`" >&2 . "$asdf_cmd_dir/command-help.bash" >&2 return 127 fi diff --git a/scripts/checkstyle.py b/scripts/checkstyle.py index 7c0271478..56c839afa 100755 --- a/scripts/checkstyle.py +++ b/scripts/checkstyle.py @@ -8,17 +8,17 @@ # This file checks Bash and Shell scripts for violations not found with # shellcheck or existing methods. You can use it in several ways: # -# Lint all .bash, .sh, and .bats files and print out violations +# Lint all .bash, .sh, .bats files along with 'bin/asdf' and print out violations: # $ ./scripts/checkstyle.py # # The former, but also fix all violations. This must be ran until there -# are zero violations since any line can have more than one violation +# are zero violations since any line can have more than one violation: # $ ./scripts/checkstyle.py --fix # -# Lint a particular file +# Lint a particular file: # $ ./scripts/checkstyle.py ./lib/functions/installs.bash # -# Check to ensure all regexes are working as intended +# Check to ensure all regular expressions are working as intended: # $ ./scripts/checkstyle.py --internal-test-regex Rule = Dict[str, Any] @@ -35,7 +35,7 @@ class c: UNDERLINE = '\033[4m' LINK: Callable[[str, str], str] = lambda href, text: f'\033]8;;{href}\a{text}\033]8;;\a' -def utilGetStrs(line, m): +def utilGetStrs(line: Any, m: Any): return ( line[0:m.start('match')], line[m.start('match'):m.end('match')], @@ -44,22 +44,22 @@ def utilGetStrs(line, m): # Before: printf '%s\\n' '^w^' # After: printf '%s\n' '^w^' -def noDoubleBackslashFixer(line: str, m) -> str: +def noDoubleBackslashFixer(line: str, m: Any) -> str: prestr, midstr, poststr = utilGetStrs(line, m) return f'{prestr}{midstr[1:]}{poststr}' # Before: $(pwd) # After: $PWD -def noPwdCaptureFixer(line: str, m) -> str: - prestr, midstr, poststr = utilGetStrs(line, m) +def noPwdCaptureFixer(line: str, m: Any) -> str: + prestr, _, poststr = utilGetStrs(line, m) return f'{prestr}$PWD{poststr}' # Before: [ a == b ] # After: [ a = b ] -def noTestDoubleEqualsFixer(line: str, m) -> str: - prestr, midstr, poststr = utilGetStrs(line, m) +def noTestDoubleEqualsFixer(line: str, m: Any) -> str: + prestr, _, poststr = utilGetStrs(line, m) return f'{prestr}={poststr}' @@ -68,7 +68,7 @@ def noTestDoubleEqualsFixer(line: str, m) -> str: # --- # Before: function fn { ... # After fn() { ... -def noFunctionKeywordFixer(line: str, m) -> str: +def noFunctionKeywordFixer(line: str, m: Any) -> str: prestr, midstr, poststr = utilGetStrs(line, m) midstr = midstr.strip() @@ -183,14 +183,14 @@ def main(): if args.internal_test_regex: for rule in rules: for positiveMatch in rule['testPositiveMatches']: - m = re.search(rule['regex'], positiveMatch) + m: Any = re.search(rule['regex'], positiveMatch) if m is None or m.group('match') is None: print(f'{c.MAGENTA}{rule["name"]}{c.RESET}: Failed {c.CYAN}positive{c.RESET} test:') print(f'=> {positiveMatch}') print() for negativeMatch in rule['testNegativeMatches']: - m = re.search(rule['regex'], negativeMatch) + m: Any = re.search(rule['regex'], negativeMatch) if m is not None and m.group('match') is not None: print(f'{c.MAGENTA}{rule["name"]}{c.RESET}: Failed {c.YELLOW}negative{c.RESET} test:') print(f'=> {negativeMatch}') @@ -210,7 +210,7 @@ def main(): lintfile(p, rules, options) else: for file in Path.cwd().glob('**/*'): - if file.name.endswith('.bash') or file.name.endswith('.sh') or file.name.endswith('.bats'): + if file.name.endswith('.bash') or file.name.endswith('.sh') or file.name.endswith('.bats') or str(file.absolute()).endswith('bin/asdf'): if file.is_file(): lintfile(file, rules, options) From 747a55fe4a4195033762821ab1b01f8338b814fa Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Sun, 26 Mar 2023 16:18:00 -0700 Subject: [PATCH 12/42] test: skip tests for uninstalled shells when run locally (#1517) --- test/asdf_elvish.bats | 6 +++++- test/asdf_fish.bats | 2 +- test/asdf_nu.bats | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/test/asdf_elvish.bats b/test/asdf_elvish.bats index d223c7e47..68b5a4918 100644 --- a/test/asdf_elvish.bats +++ b/test/asdf_elvish.bats @@ -8,12 +8,16 @@ setup() { export XDG_DATA_HOME= export XDG_DATA_DIRS= + if ! command -v elvish &>/dev/null && [ -z "$GITHUB_ACTIONS" ]; then + skip 'Elvish not installed' + fi + local ver_major= local ver_minor= local ver_patch= IFS='.' read -r ver_major ver_minor ver_patch <<<"$(elvish -version)" - if ((ver_major == 0 && ver_minor < 18)); then + if ((ver_major == 0 && ver_minor < 18)) && [ -z "$GITHUB_ACTIONS" ]; then skip "Elvish version is not at least 0.18. Found ${ver_major}.${ver_minor}.${ver_patch}" fi } diff --git a/test/asdf_fish.bats b/test/asdf_fish.bats index 883643335..8c15f7b42 100644 --- a/test/asdf_fish.bats +++ b/test/asdf_fish.bats @@ -6,7 +6,7 @@ load test_helpers setup() { cd "$(dirname "$BATS_TEST_DIRNAME")" - if ! command -v fish; then + if ! command -v fish &>/dev/null && [ -z "$GITHUB_ACTIONS" ]; then skip "Fish is not installed" fi } diff --git a/test/asdf_nu.bats b/test/asdf_nu.bats index da16bac1a..526442449 100644 --- a/test/asdf_nu.bats +++ b/test/asdf_nu.bats @@ -6,7 +6,7 @@ load test_helpers setup() { cd "$(dirname "$BATS_TEST_DIRNAME")" - if ! command -v nu; then + if ! command -v nu &>/dev/null && [ -z "$GITHUB_ACTIONS" ]; then skip "Nu is not installed" fi From 86477ee8dea14ab63faf7132133304855a647fde Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Sun, 26 Mar 2023 17:24:16 -0700 Subject: [PATCH 13/42] fix: assign default values to all internal variables (#1518) --- bin/asdf | 13 ++++++++++ lib/functions/versions.bash | 2 +- lib/utils.bash | 47 +++++++++++++++++++------------------ 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/bin/asdf b/bin/asdf index 917a42357..16f07799a 100755 --- a/bin/asdf +++ b/bin/asdf @@ -68,6 +68,19 @@ asdf_cmd() { exit 1 fi + # Internal Variables + ASDF_DEFAULT_TOOL_VERSIONS_FILENAME=$(asdf_default_tool_versions_filename) + export ASDF_DEFAULT_TOOL_VERSIONS_FILENAME + + ASDF_CONFIG_FILE=$(asdf_config_file) + export ASDF_CONFIG_FILE + + ASDF_DATA_DIR=$(asdf_data_dir) + export ASDF_DATA_DIR + + ASDF_DIR=$(asdf_dir) + export ASDF_DIR + local result= result="$(find_asdf_cmd "$@")" ASDF_CMD_FILE=${result% *} diff --git a/lib/functions/versions.bash b/lib/functions/versions.bash index 28262f78e..76093733d 100644 --- a/lib/functions/versions.bash +++ b/lib/functions/versions.bash @@ -17,7 +17,7 @@ version_command() { local file_name local file - file_name="$(version_file_name)" + file_name="$(asdf_default_tool_versions_filename)" if [ "$cmd" = "global" ]; then file="$HOME/$file_name" diff --git a/lib/utils.bash b/lib/utils.bash index 2c856e07f..d926cd6ae 100644 --- a/lib/utils.bash +++ b/lib/utils.bash @@ -5,9 +5,6 @@ GREP_OPTIONS="--color=never" # shellcheck disable=SC2034 GREP_COLORS= -ASDF_DIR=${ASDF_DIR:-''} -ASDF_DATA_DIR=${ASDF_DATA_DIR:-''} - asdf_version() { local version git_rev version="v$(cat "$(asdf_dir)/version.txt")" @@ -19,21 +16,12 @@ asdf_version() { fi } -asdf_dir() { - if [ -z "$ASDF_DIR" ]; then - local current_script_path=${BASH_SOURCE[0]} - export ASDF_DIR - ASDF_DIR=$( - cd "$(dirname "$(dirname "$current_script_path")")" || exit - printf '%s\n' "$PWD" - ) - fi - - printf "%s\n" "$ASDF_DIR" +asdf_default_tool_versions_filename() { + printf '%s\n' "${ASDF_DEFAULT_TOOL_VERSIONS_FILENAME:-.tool-versions}" } -asdf_repository_url() { - printf "https://github.com/asdf-vm/asdf-plugins.git\n" +asdf_config_file() { + printf '%s\n' "${ASDF_CONFIG_FILE:-$HOME/.asdfrc}" } asdf_data_dir() { @@ -50,6 +38,22 @@ asdf_data_dir() { printf "%s\n" "$data_dir" } +asdf_dir() { + if [ -z "$ASDF_DIR" ]; then + local current_script_path=${BASH_SOURCE[0]} + printf '%s\n' "$( + cd -- "$(dirname "$(dirname "$current_script_path")")" || exit + printf '%s\n' "$PWD" + )" + else + printf '%s\n' "$ASDF_DIR" + fi +} + +asdf_repository_url() { + printf "https://github.com/asdf-vm/asdf-plugins.git\n" +} + get_install_path() { local plugin=$1 local install_type=$2 @@ -159,7 +163,7 @@ get_version_in_dir() { local asdf_version - file_name=$(version_file_name) + file_name=$(asdf_default_tool_versions_filename) asdf_version=$(parse_asdf_version_file "$search_path/$file_name" "$plugin_name") if [ -n "$asdf_version" ]; then @@ -178,10 +182,6 @@ get_version_in_dir() { done } -version_file_name() { - printf "%s" "${ASDF_DEFAULT_TOOL_VERSIONS_FILENAME:-.tool-versions}" -} - find_versions() { local plugin_name=$1 local search_path=$2 @@ -385,7 +385,8 @@ get_asdf_config_value_from_file() { get_asdf_config_value() { local key=$1 - local config_path=${ASDF_CONFIG_FILE:-"$HOME/.asdfrc"} + local config_path= + config_path=$(asdf_config_file) local default_config_path=${ASDF_CONFIG_DEFAULT_FILE:-"$(asdf_dir)/defaults"} local local_config_path @@ -454,7 +455,7 @@ get_plugin_source_url() { } find_tool_versions() { - find_file_upwards "$(version_file_name)" + find_file_upwards "$(asdf_default_tool_versions_filename)" } find_file_upwards() { From 6a6c539f4a21fdb863fd938edd94ac3bdced349b Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Sun, 26 Mar 2023 17:25:00 -0700 Subject: [PATCH 14/42] docs: Add Nushell installation instructions for all languages (#1519) --- docs/pt-br/guide/getting-started.md | 33 +++++++++++++++++++++++++++ docs/zh-hans/guide/getting-started.md | 33 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/docs/pt-br/guide/getting-started.md b/docs/pt-br/guide/getting-started.md index 69d902b5d..9ad55b542 100644 --- a/docs/pt-br/guide/getting-started.md +++ b/docs/pt-br/guide/getting-started.md @@ -262,6 +262,39 @@ Adicione a seguinte linha ao seu `~/.zshrc`: . /opt/asdf-vm/asdf.sh ``` +::: details Nushell & Git + +Adicione `asdf.nu` ao seu `~/.config/nushell/config.nu` através do comando: + +```shell +"\nlet-env ASDF_NU_DIR = ($env.HOME | path join '.asdf')\n source " + ($env.HOME | path join '.asdf/asdf.nu') | save --append $nu.config-path +``` + +Ao concluir atualizará automaticamente +::: + +::: details Nushell & Homebrew + +Adicione `asdf.nu` ao seu `~/.config/nushell/config.nu` através do comando: + +```shell:no-line-numbers +"\nlet-env ASDF_NU_DIR = (brew --prefix asdf | str trim | into string | path join 'libexec')\n source " + (brew --prefix asdf | into string | path join 'libexec/asdf.nu') | save --append $nu.config-path +``` + +Ao concluir atualizará automaticamente +::: + +::: details Nushell & Pacman + +Adicione `asdf.nu` ao seu `~/.config/nushell/config.nu` através do comando: + +```shell +"\nlet-env ASDF_NU_DIR = '/opt/asdf-vm/'\n source /opt/asdf-vm/asdf.nu" | save --append $nu.config-path +``` + +Ao concluir atualizará automaticamente +::: + ::: details POSIX Shell & Git Adicione a seguinte linha ao seu `~/.profile`: diff --git a/docs/zh-hans/guide/getting-started.md b/docs/zh-hans/guide/getting-started.md index f77fbb603..fdf70f420 100644 --- a/docs/zh-hans/guide/getting-started.md +++ b/docs/zh-hans/guide/getting-started.md @@ -263,6 +263,39 @@ echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc 补全功能会被放在一个对 ZSH 很友好的位置,但是 [ZSH 必须使用自动补全完成配置](https://wiki.archlinux.org/index.php/zsh#Command_completion)。 ::: +::: details Nushell & Git + +使用以下命令将 `asdf.nu` 加入到 `~/.config/nushell/config.nu` 文件中: + +```shell +"\nlet-env ASDF_NU_DIR = ($env.HOME | path join '.asdf')\n source " + ($env.HOME | path join '.asdf/asdf.nu') | save --append $nu.config-path +``` + +补全功能将会自动配置。 +::: + +::: details Nushell & Homebrew + +使用以下命令将 `asdf.nu` 加入到 `~/.config/nushell/config.nu` 文件中: + +```shell:no-line-numbers +"\nlet-env ASDF_NU_DIR = (brew --prefix asdf | str trim | into string | path join 'libexec')\n source " + (brew --prefix asdf | into string | path join 'libexec/asdf.nu') | save --append $nu.config-path +``` + +补全功能将会自动配置。 +::: + +::: details Nushell & Pacman + +使用以下命令将 `asdf.nu` 加入到 `~/.config/nushell/config.nu` 文件中: + +```shell +"\nlet-env ASDF_NU_DIR = '/opt/asdf-vm/'\n source /opt/asdf-vm/asdf.nu" | save --append $nu.config-path +``` + +补全功能将会自动配置。 +::: + ::: details POSIX Shell & Git 在 `~/.profile` 文件中加入以下内容: From b6d0ca28d5fd2b63c7da67b127e6c2a0e01b2670 Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Mon, 27 Mar 2023 23:42:55 -0700 Subject: [PATCH 15/42] fix!: do not remove items from PATH in POSIX entrypoint (#1521) --- asdf.sh | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/asdf.sh b/asdf.sh index d7dd4c7e6..cdbb1de87 100644 --- a/asdf.sh +++ b/asdf.sh @@ -47,7 +47,7 @@ if [ -z "$ASDF_DIR" ]; then fi if [ -z "$ASDF_DIR" ]; then - printf "%s\n" "asdf: Error: Source directory could not be calculated. Please set it manually before sourcing this file." >&2 + printf "%s\n" "asdf: Error: Source directory could not be calculated. Please set \$ASDF_DIR manually before sourcing this file." >&2 return 1 fi @@ -56,22 +56,20 @@ if [ ! -d "$ASDF_DIR" ]; then return 1 fi -_asdf_bin="${ASDF_DIR}/bin" +_asdf_bin="$ASDF_DIR/bin" _asdf_shims="${ASDF_DATA_DIR:-$HOME/.asdf}/shims" -# shellcheck disable=SC3060 -if [ -n "$BASH_VERSION" ] || [ -n "$ZSH_VERSION" ]; then - case ":$PATH:" in - *":${_asdf_bin}:"*) PATH="${PATH//$_asdf_bin:/}" ;; - esac - case ":$PATH:" in - *":${_asdf_shims}:"*) PATH="${PATH//$_asdf_shims:/}" ;; - esac -fi +case ":$PATH:" in + *":$_asdf_bin:"*) : ;; + *) PATH="$_asdf_bin:$PATH" ;; +esac +case ":$PATH:" in + *":$_asdf_shims:"*) : ;; + *) PATH="$_asdf_shims:$PATH" ;; +esac -PATH="${_asdf_bin}:${_asdf_shims}:$PATH" unset -v _asdf_bin _asdf_shims # shellcheck source=lib/asdf.sh -. "${ASDF_DIR}/lib/asdf.sh" +. "$ASDF_DIR/lib/asdf.sh" From 8919f4009ea233c32298911b28ceb879e2dbc675 Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Thu, 30 Mar 2023 00:27:23 -0700 Subject: [PATCH 16/42] fix!: align Fish entrypoint behaviour with other shells (#1524) --- .editorconfig | 3 +++ .github/workflows/lint.yml | 6 +++++ asdf.fish | 46 ++++++++++++--------------------- completions/asdf.fish | 52 +++++++++++++++++++------------------- lib/asdf.fish | 9 +++---- scripts/format.bash | 3 +++ scripts/shfmt.bash | 3 +++ 7 files changed, 61 insertions(+), 61 deletions(-) diff --git a/.editorconfig b/.editorconfig index 1840589a7..fe3ed6082 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,3 +9,6 @@ insert_final_newline = true [*.py] indent_size = 4 + +[*.fish] +indent_size = 4 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 177a52905..ccc659015 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -25,6 +25,12 @@ jobs: - name: Checkout code uses: actions/checkout@v3 + - name: Install Fish (for fish_indent) + run: | + sudo add-apt-repository -y ppa:fish-shell/nightly-master + sudo apt-get update + sudo apt-get -y install fish + - name: Install asdf dependencies uses: asdf-vm/actions/install@v2 diff --git a/asdf.fish b/asdf.fish index 7cef8114a..33abb95bd 100644 --- a/asdf.fish +++ b/asdf.fish @@ -1,38 +1,24 @@ -if not set -q ASDF_DIR - set -x ASDF_DIR (dirname (status -f)) +if test -z $ASDF_DIR + set ASDF_DIR (realpath (dirname (status filename))) end +set --export ASDF_DIR $ASDF_DIR -# Add asdf to PATH -# fish_add_path was added in fish 3.2, so we need a fallback for older version -if type -q fish_add_path - if test -n "$ASDF_DATA_DIR" - fish_add_path --global --move "$ASDF_DATA_DIR/shims" "$ASDF_DIR/bin" - else - fish_add_path --global --move "$HOME/.asdf/shims" "$ASDF_DIR/bin" - end +set -l _asdf_bin "$ASDF_DIR/bin" +if test -z $ASDF_DATA_DIR + set _asdf_shims "$HOME/.asdf/shims" else - set -l asdf_user_shims ( - if test -n "$ASDF_DATA_DIR" - printf "%s\n" "$ASDF_DATA_DIR/shims" - else - printf "%s\n" "$HOME/.asdf/shims" - end - ) - - set -l asdf_bin_dirs $ASDF_DIR/bin $asdf_user_shims + set _asdf_shims "$ASDF_DATA_DIR/shims" +end - for x in $asdf_bin_dirs - if test -d $x - for i in (seq 1 (count $PATH)) - if test $PATH[$i] = $x - set -e PATH[$i] - break - end - end - end - set PATH $x $PATH - end +# Do not use fish_add_path (added in Fish 3.2) because it +# potentially changes the order of items in fish_user_paths +if not contains $_asdf_bin $fish_user_paths + set --global --prepend fish_user_paths $_asdf_bin +end +if not contains $_asdf_shims $fish_user_paths + set --global --prepend fish_user_paths $_asdf_shims end +set --erase _asdf_bin _asdf_shims # Load the asdf wrapper function . $ASDF_DIR/lib/asdf.fish diff --git a/completions/asdf.fish b/completions/asdf.fish index 372ed5bc3..50b479d6a 100644 --- a/completions/asdf.fish +++ b/completions/asdf.fish @@ -31,19 +31,19 @@ function __fish_asdf_arg_at -a number end function __fish_asdf_list_versions -a plugin - asdf list $plugin 2> /dev/null | sed -e 's/^[[:space:]]*//' + asdf list $plugin 2>/dev/null | sed -e 's/^[[:space:]]*//' end function __fish_asdf_list_all -a plugin - asdf list-all $plugin 2> /dev/null + asdf list-all $plugin 2>/dev/null end function __fish_asdf_plugin_list - asdf plugin-list 2> /dev/null + asdf plugin-list 2>/dev/null end function __fish_asdf_plugin_list_all - asdf plugin-list-all 2> /dev/null + asdf plugin-list-all 2>/dev/null end function __fish_asdf_list_shims @@ -51,87 +51,87 @@ function __fish_asdf_list_shims end # update -complete -f -c asdf -n '__fish_asdf_needs_command' -a update -d "Update asdf" -complete -f -c asdf -n '__fish_asdf_using_command update; and __fish_asdf_arg_number 2' -l "head" -d "Updates to master HEAD" +complete -f -c asdf -n __fish_asdf_needs_command -a update -d "Update asdf" +complete -f -c asdf -n '__fish_asdf_using_command update; and __fish_asdf_arg_number 2' -l head -d "Updates to master HEAD" # plugin-add completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a plugin-add -d "Add git repo as plugin" +complete -f -c asdf -n __fish_asdf_needs_command -a plugin-add -d "Add git repo as plugin" complete -f -c asdf -n '__fish_asdf_using_command plugin-add; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list_all | grep -v \'*\' | awk \'{ print $1 }\')' complete -f -c asdf -n '__fish_asdf_using_command plugin-add; and __fish_asdf_arg_number 3' -a '(__fish_asdf_plugin_list_all | grep (__fish_asdf_arg_at 3) | awk \'{ print $2 }\')' complete -f -c asdf -n '__fish_asdf_using_command plugin-add; and __fish_asdf_arg_number 4' # plugin-list completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a plugin-list -d "List installed plugins" +complete -f -c asdf -n __fish_asdf_needs_command -a plugin-list -d "List installed plugins" # plugin-list-all completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a plugin-list-all -d "List all existing plugins" +complete -f -c asdf -n __fish_asdf_needs_command -a plugin-list-all -d "List all existing plugins" # plugin-remove completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a plugin-remove -d "Remove plugin and package versions" +complete -f -c asdf -n __fish_asdf_needs_command -a plugin-remove -d "Remove plugin and package versions" complete -f -c asdf -n '__fish_asdf_using_command plugin-remove; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' # plugin-update completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a plugin-update -d "Update plugin" +complete -f -c asdf -n __fish_asdf_needs_command -a plugin-update -d "Update plugin" complete -f -c asdf -n '__fish_asdf_using_command plugin-update; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' complete -f -c asdf -n '__fish_asdf_using_command plugin-update; and __fish_asdf_arg_number 2' -a --all # install completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a install -d "Install a specific version of a package" +complete -f -c asdf -n __fish_asdf_needs_command -a install -d "Install a specific version of a package" complete -f -c asdf -n '__fish_asdf_using_command install; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' complete -f -c asdf -n '__fish_asdf_using_command install; and __fish_asdf_arg_number 3' -a '(__fish_asdf_list_all (__fish_asdf_arg_at 3))' # uninstall completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a uninstall -d "Remove a specific version of a package" +complete -f -c asdf -n __fish_asdf_needs_command -a uninstall -d "Remove a specific version of a package" complete -f -c asdf -n '__fish_asdf_using_command uninstall; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' complete -f -c asdf -n '__fish_asdf_using_command uninstall; and __fish_asdf_arg_number 3' -a '(__fish_asdf_list_versions (__fish_asdf_arg_at 3))' # current completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a current -d "Display version set or being used for package" +complete -f -c asdf -n __fish_asdf_needs_command -a current -d "Display version set or being used for package" complete -f -c asdf -n '__fish_asdf_using_command current; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' # where completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a where -d "Display install path for an installed version" +complete -f -c asdf -n __fish_asdf_needs_command -a where -d "Display install path for an installed version" complete -f -c asdf -n '__fish_asdf_using_command where; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' complete -f -c asdf -n '__fish_asdf_using_command where; and __fish_asdf_arg_number 3' -a '(__fish_asdf_list_versions (__fish_asdf_arg_at 3))' # which completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a which -d "Display executable path for a command" +complete -f -c asdf -n __fish_asdf_needs_command -a which -d "Display executable path for a command" complete -f -c asdf -n '__fish_asdf_using_command which; and __fish_asdf_arg_number 2' -a '(__fish_asdf_list_shims)' # latest completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a latest -d "Show latest stable version of a package" +complete -f -c asdf -n __fish_asdf_needs_command -a latest -d "Show latest stable version of a package" complete -f -c asdf -n '__fish_asdf_using_command latest; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' complete -f -c asdf -n '__fish_asdf_using_command latest; and __fish_asdf_arg_number 2' -a --all # list completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a list -d "List installed versions of a package" +complete -f -c asdf -n __fish_asdf_needs_command -a list -d "List installed versions of a package" complete -f -c asdf -n '__fish_asdf_using_command list; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' # list-all completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a list-all -d "List all versions of a package" +complete -f -c asdf -n __fish_asdf_needs_command -a list-all -d "List all versions of a package" complete -f -c asdf -n '__fish_asdf_using_command list-all; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' # reshim completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a reshim -d "Recreate shims for version of a package" +complete -f -c asdf -n __fish_asdf_needs_command -a reshim -d "Recreate shims for version of a package" complete -f -c asdf -n '__fish_asdf_using_command reshim; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' complete -f -c asdf -n '__fish_asdf_using_command reshim; and __fish_asdf_arg_number 3' -a '(__fish_asdf_list_versions (__fish_asdf_arg_at 3))' # local completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a local -d "Set local version for a plugin" +complete -f -c asdf -n __fish_asdf_needs_command -a local -d "Set local version for a plugin" complete -f -c asdf -n '__fish_asdf_using_command local; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' complete -f -c asdf -n '__fish_asdf_using_command local; and test (count (commandline -opc)) -gt 2' -a '(__fish_asdf_list_versions (__fish_asdf_arg_at 3)) system' # global completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a global -d "Set global version for a plugin" +complete -f -c asdf -n __fish_asdf_needs_command -a global -d "Set global version for a plugin" complete -f -c asdf -n '__fish_asdf_using_command global; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' complete -f -c asdf -n '__fish_asdf_using_command global; and test (count (commandline -opc)) -gt 2' -a '(__fish_asdf_list_versions (__fish_asdf_arg_at 3)) system' # shell completion -complete -f -c asdf -n '__fish_asdf_needs_command' -a shell -d "Set version for a plugin in current shell session" +complete -f -c asdf -n __fish_asdf_needs_command -a shell -d "Set version for a plugin in current shell session" complete -f -c asdf -n '__fish_asdf_using_command shell; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' complete -f -c asdf -n '__fish_asdf_using_command shell; and test (count (commandline -opc)) -gt 2' -a '(__fish_asdf_list_versions (__fish_asdf_arg_at 3)) system' # misc -complete -f -c asdf -n '__fish_asdf_needs_command' -l "help" -d "Displays help" -complete -f -c asdf -n '__fish_asdf_needs_command' -a "info" -d "Print OS, Shell and ASDF debug information" -complete -f -c asdf -n '__fish_asdf_needs_command' -l "version" -d "Displays asdf version" +complete -f -c asdf -n __fish_asdf_needs_command -l help -d "Displays help" +complete -f -c asdf -n __fish_asdf_needs_command -a info -d "Print OS, Shell and ASDF debug information" +complete -f -c asdf -n __fish_asdf_needs_command -l version -d "Displays asdf version" diff --git a/lib/asdf.fish b/lib/asdf.fish index d14ab3897..f29b60769 100644 --- a/lib/asdf.fish +++ b/lib/asdf.fish @@ -1,15 +1,14 @@ - -# Add function wrapper so we can export variables +# The asdf function is a wrapper so we can export variables function asdf set command $argv[1] set -e argv[1] switch "$command" - case "shell" - # source commands that need to export variables + case shell + # Source commands that need to export variables. command asdf export-shell-version fish $argv | source # asdf_allow: source case '*' - # forward other commands to asdf script + # Forward other commands to asdf script. command asdf "$command" $argv end end diff --git a/scripts/format.bash b/scripts/format.bash index 1a2eae631..e9b261a18 100755 --- a/scripts/format.bash +++ b/scripts/format.bash @@ -23,3 +23,6 @@ shfmt --language-dialect bash --indent 2 --write \ # check .bats files shfmt --language-dialect bats --indent 2 --write \ test/*.bats + +# check .fish files +fish_indent --write ./**/*.fish diff --git a/scripts/shfmt.bash b/scripts/shfmt.bash index d5db82264..f9372d856 100755 --- a/scripts/shfmt.bash +++ b/scripts/shfmt.bash @@ -23,3 +23,6 @@ shfmt --language-dialect bash --indent 2 --diff \ # check .bats files shfmt --language-dialect bats --indent 2 --diff \ test/*.bats + +# check .fish files +fish_indent --check ./**/*.fish From 00fee78423de0e399f5705bb483e599e39b707c9 Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Fri, 31 Mar 2023 20:22:24 -0700 Subject: [PATCH 17/42] fix!: Remove files containing only `asdf` wrapper functions (#1525) --- asdf.fish | 16 ++++++++++++++-- asdf.sh | 19 +++++++++++++++++-- lib/asdf.fish | 14 -------------- lib/asdf.sh | 20 -------------------- scripts/shellcheck.bash | 3 +-- scripts/shfmt.bash | 4 ---- 6 files changed, 32 insertions(+), 44 deletions(-) delete mode 100644 lib/asdf.fish delete mode 100644 lib/asdf.sh diff --git a/asdf.fish b/asdf.fish index 33abb95bd..afb161dc7 100644 --- a/asdf.fish +++ b/asdf.fish @@ -20,5 +20,17 @@ if not contains $_asdf_shims $fish_user_paths end set --erase _asdf_bin _asdf_shims -# Load the asdf wrapper function -. $ASDF_DIR/lib/asdf.fish +# The asdf function is a wrapper so we can export variables +function asdf + set command $argv[1] + set -e argv[1] + + switch "$command" + case shell + # Source commands that need to export variables. + command asdf export-shell-version fish $argv | source # asdf_allow: source + case '*' + # Forward other commands to asdf script. + command asdf "$command" $argv + end +end diff --git a/asdf.sh b/asdf.sh index cdbb1de87..a19265c0a 100644 --- a/asdf.sh +++ b/asdf.sh @@ -70,6 +70,21 @@ esac unset -v _asdf_bin _asdf_shims -# shellcheck source=lib/asdf.sh -. "$ASDF_DIR/lib/asdf.sh" +# The asdf function is a wrapper so we can export variables +asdf() { + case $1 in + "shell") + if ! shift; then + printf '%s\n' 'asdf: Error: Failed to shift' >&2 + return 1 + fi + # Invoke command that needs to export variables. + eval "$(asdf export-shell-version sh "$@")" # asdf_allow: eval + ;; + *) + # Forward other commands to asdf script. + command asdf "$@" # asdf_allow: ' asdf ' + ;; + esac +} diff --git a/lib/asdf.fish b/lib/asdf.fish deleted file mode 100644 index f29b60769..000000000 --- a/lib/asdf.fish +++ /dev/null @@ -1,14 +0,0 @@ -# The asdf function is a wrapper so we can export variables -function asdf - set command $argv[1] - set -e argv[1] - - switch "$command" - case shell - # Source commands that need to export variables. - command asdf export-shell-version fish $argv | source # asdf_allow: source - case '*' - # Forward other commands to asdf script. - command asdf "$command" $argv - end -end diff --git a/lib/asdf.sh b/lib/asdf.sh deleted file mode 100644 index e5404aa86..000000000 --- a/lib/asdf.sh +++ /dev/null @@ -1,20 +0,0 @@ -# shellcheck shell=sh - -# The asdf function is a wrapper so we can export variables -asdf() { - case $1 in - "shell") - if ! shift; then - printf '%s\n' 'asdf: Error: Failed to shift' >&2 - return 1 - fi - - # Invoke command that needs to export variables. - eval "$(asdf export-shell-version sh "$@")" # asdf_allow: eval - ;; - *) - # Forward other commands to asdf script. - command asdf "$@" # asdf_allow: ' asdf ' - ;; - esac -} diff --git a/scripts/shellcheck.bash b/scripts/shellcheck.bash index ca49bd4c0..7b56f745d 100755 --- a/scripts/shellcheck.bash +++ b/scripts/shellcheck.bash @@ -4,8 +4,7 @@ set -euo pipefail # check .sh files shellcheck --shell sh --external-sources \ - asdf.sh \ - lib/*.sh + asdf.sh # check .bash files shellcheck --shell bash --external-sources \ diff --git a/scripts/shfmt.bash b/scripts/shfmt.bash index f9372d856..d42ae2057 100755 --- a/scripts/shfmt.bash +++ b/scripts/shfmt.bash @@ -2,10 +2,6 @@ set -euo pipefail -# check .sh files -shfmt --language-dialect posix --indent 2 --diff \ - lib/*.sh - # check .bash files shfmt --language-dialect bash --indent 2 --diff \ completions/*.bash \ From 213aa22378cf0ecf5b1924f1bfc4fee43338255a Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Fri, 31 Mar 2023 21:12:20 -0700 Subject: [PATCH 18/42] feat: Support PowerShell Core (#1522) --- .github/workflows/tests.yml | 4 +- asdf.ps1 | 31 ++++++ docs/guide/getting-started.md | 30 ++++++ docs/pt-br/guide/getting-started.md | 30 ++++++ docs/zh-hans/guide/getting-started.md | 30 ++++++ .../command-export-shell-version.bash | 6 ++ test/asdf_pwsh.bats | 96 +++++++++++++++++++ 7 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 asdf.ps1 create mode 100644 test/asdf_pwsh.bats diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ded80768b..aec6c696c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -59,9 +59,11 @@ jobs: - name: Install test dependencies run: | + curl -fsSLo- https://packages.microsoft.com/keys/microsoft.asc | sudo tee >/dev/null /etc/apt/trusted.gpg.d/microsoft.asc + sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-bullseye-prod bullseye main" > /etc/apt/sources.list.d/microsoft.list' sudo add-apt-repository -y ppa:fish-shell/nightly-master sudo apt-get update - sudo apt-get -y install fish curl parallel + sudo apt-get -y install fish curl parallel powershell # Create $HOME/bin mkdir -p "$HOME/bin" diff --git a/asdf.ps1 b/asdf.ps1 new file mode 100644 index 000000000..a4b405ee2 --- /dev/null +++ b/asdf.ps1 @@ -0,0 +1,31 @@ +$Env:ASDF_DIR = $PSScriptRoot + +$_asdf_bin = "$Env:ASDF_DIR/bin" +if ($null -eq $ASDF_DATA_DIR -or $ASDF_DATA_DIR -eq '') { + $_asdf_shims = "${env:HOME}/.asdf/shims" +} +else { + $_asdf_shims = "$ASDF_DATA_DIR/shims" +} + +$env:PATH = "${_asdf_bin}:${_asdf_shims}:${env:PATH}" + +if ($env:PATH -cnotlike "*${_asdf_bin}*") { + $env:PATH = "_asdf_bin:${env:PATH}" +} +if ($env:PATH -cnotlike "*${_asdf_shims}*") { + $env:PATH = "_asdf_shims:${env:PATH}" +} + +Remove-Variable -Force _asdf_bin, _asdf_shims + +function asdf { + $asdf = $(Get-Command -CommandType Application asdf).Source + + if ($args.Count -gt 0 -and $args[0] -eq 'shell') { + Invoke-Expression $(& $asdf 'export-shell-version' pwsh $args[1..($args.Count + -1)]) + } + else { + & $asdf $args + } +} diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md index 03edfaf11..38d679c18 100644 --- a/docs/guide/getting-started.md +++ b/docs/guide/getting-started.md @@ -261,6 +261,36 @@ Add the following to `~/.zshrc`: Completions are placed in a ZSH friendly location, but [ZSH must be configured to use the autocompletions](https://wiki.archlinux.org/index.php/zsh#Command_completion). ::: +::: details PowerShell Core & Git + +Add the following to `~/.config/powershell/profile.ps1`: + +```shell +. "$HOME/.asdf/asdf.ps1" +``` + +::: + +::: details PowerShell Core & Homebrew + +Add `asdf.sh` to your `~/.config/powershell/profile.ps1` with: + +```shell:no-line-numbers +echo -e "\n. \"$(brew --prefix asdf)/libexec/asdf.ps1\"" >> ~/.config/powershell/profile.ps1 +``` + +::: + +::: details PowerShell Core & Pacman + +Add the following to `~/.config/powershell/profile.ps1`: + +```shell +. /opt/asdf-vm/asdf.ps1 +``` + +::: + ::: details Nushell & Git Add `asdf.nu` to your `~/.config/nushell/config.nu` with: diff --git a/docs/pt-br/guide/getting-started.md b/docs/pt-br/guide/getting-started.md index 9ad55b542..9c9bac8e5 100644 --- a/docs/pt-br/guide/getting-started.md +++ b/docs/pt-br/guide/getting-started.md @@ -262,6 +262,36 @@ Adicione a seguinte linha ao seu `~/.zshrc`: . /opt/asdf-vm/asdf.sh ``` +::: details PowerShell Core & Git + +Adicione a seguinte linha ao seu `~/.config/powershell/profile.ps1`: + +```shell +. "$HOME/.asdf/asdf.ps1" +``` + +::: + +::: details PowerShell Core & Homebrew + +Adicione `asdf.ps1` ao seu `~/.config/powershell/profile.ps1` através do comando: + +```shell:no-line-numbers +echo -e "\n. \"$(brew --prefix asdf)/libexec/asdf.ps1\"" >> ~/.config/powershell/profile.ps1 +``` + +::: + +::: details PowerShell Core & Pacman + +Adicione a seguinte linha ao seu `~/.config/powershell/profile.ps1`: + +```shell +. /opt/asdf-vm/asdf.ps1 +``` + +::: + ::: details Nushell & Git Adicione `asdf.nu` ao seu `~/.config/nushell/config.nu` através do comando: diff --git a/docs/zh-hans/guide/getting-started.md b/docs/zh-hans/guide/getting-started.md index fdf70f420..b4b57a38c 100644 --- a/docs/zh-hans/guide/getting-started.md +++ b/docs/zh-hans/guide/getting-started.md @@ -263,6 +263,36 @@ echo -e "\n. $(brew --prefix asdf)/libexec/asdf.sh" >> ${ZDOTDIR:-~}/.zshrc 补全功能会被放在一个对 ZSH 很友好的位置,但是 [ZSH 必须使用自动补全完成配置](https://wiki.archlinux.org/index.php/zsh#Command_completion)。 ::: +::: details PowerShell Core & Git + +在 `~/.config/powershell/profile.ps1` 文件中加入以下内容: + +```shell +. "$HOME/.asdf/asdf.ps1" +``` + +::: + +::: details PowerShell Core & Homebrew + +使用以下命令将 `asdf.ps1` 加入到 `~/.config/powershell/profile.ps1` 文件中: + +```shell:no-line-numbers +echo -e "\n. \"$(brew --prefix asdf)/libexec/asdf.ps1\"" >> ~/.config/powershell/profile.ps1 +``` + +::: + +::: details PowerShell Core & Pacman + +在 `~/.config/powershell/profile.ps1` 文件中加入以下内容: + +```shell +. /opt/asdf-vm/asdf.ps1 +``` + +::: + ::: details Nushell & Git 使用以下命令将 `asdf.nu` 加入到 `~/.config/nushell/config.nu` 文件中: diff --git a/lib/commands/command-export-shell-version.bash b/lib/commands/command-export-shell-version.bash index 13b779d1b..92ace8abe 100644 --- a/lib/commands/command-export-shell-version.bash +++ b/lib/commands/command-export-shell-version.bash @@ -31,6 +31,9 @@ shell_command() { # and pass to unset-env. printf "unset-env\n%s" "$version_env_var" ;; + pwsh) + printf '%s\n' "if (\$(Test-Path Env:$version_env_var) -eq 'True') { Remove-Item Env:$version_env_var }" + ;; *) printf "unset %s\n" "$version_env_var" ;; @@ -56,6 +59,9 @@ shell_command() { # and pass to set-env. printf "set-env\n%s\n%s" "$version_env_var" "$version" ;; + pwsh) + printf '%s\n' "\$Env:$version_env_var = '$version'" + ;; *) printf "export %s=\"%s\"\n" "$version_env_var" "$version" ;; diff --git a/test/asdf_pwsh.bats b/test/asdf_pwsh.bats new file mode 100644 index 000000000..4f27d12f6 --- /dev/null +++ b/test/asdf_pwsh.bats @@ -0,0 +1,96 @@ +#!/usr/bin/env bats +# shellcheck disable=SC2164 + +load test_helpers + +setup() { + cd "$(dirname "$BATS_TEST_DIRNAME")" + + if ! command -v pwsh &>/dev/null && [ -z "$GITHUB_ACTIONS" ]; then + skip "Powershell Core is not installed" + fi +} + +cleaned_path() { + echo "$PATH" | tr ':' '\n' | grep -v "asdf" | tr '\n' ':' +} + +@test "exports ASDF_DIR" { + run pwsh -Command " + function asdf() {} # checkstyle-ignore + Remove-item Function:asdf + \$Env:ASDF_DIR = '' + \$Env:ASDF_DATA_DIR = '' + \$Env:PATH = \"$(cleaned_path)\" + + . ./asdf.ps1 + Write-Output \"\$env:ASDF_DIR\"" + + [ "$status" -eq 0 ] + [ "$output" != "" ] +} + +@test "adds asdf dirs to PATH" { + run pwsh -Command " + function asdf() {} # checkstyle-ignore + Remove-item Function:asdf + \$Env:ASDF_DIR = '' + \$Env:ASDF_DATA_DIR = '' + \$Env:PATH = \"$(cleaned_path)\" + + . ./asdf.ps1 + Write-Output \$Env:PATH" + + [ "$status" -eq 0 ] + result=$(echo "$output" | grep "asdf") + [ "$result" != "" ] +} + +@test "does not add paths to PATH more than once" { + run pwsh -Command " + function asdf() {} # checkstyle-ignore + Remove-item Function:asdf + \$Env:ASDF_DIR = '' + \$Env:ASDF_DATA_DIR = '' + \$Env:PATH = \"$(cleaned_path)\" + + . ./asdf.ps1 + . ./asdf.ps1 + Write-Output \$Env:PATH" + + [ "$status" -eq 0 ] + + result=$(echo "$output" | tr ' ' '\n' | grep "asdf" | sort | uniq -d) + [ "$result" = "" ] +} + +@test "defines the asdf function" { + run pwsh -Command " + function asdf() {} # checkstyle-ignore + Remove-item Function:asdf + \$Env:ASDF_DIR = '' + \$Env:ASDF_DATA_DIR = '' + \$Env:PATH = \"$(cleaned_path)\" + + ./ asdf.ps1 + \$(Get-Command -CommandType asdf).Name" + + [ "$status" -eq 0 ] + [[ "$output" =~ "asdf" ]] +} + +@test "function calls asdf command" { + run pwsh -Command " + function asdf() {} # checkstyle-ignore + Remove-item Function:asdf + \$Env:ASDF_DIR = '' + \$Env:ASDF_DATA_DIR = '' + \$Env:PATH = \"$(cleaned_path)\" + + . ./asdf.ps1 + asdf info" + + [ "$status" -eq 0 ] + result=$(echo "$output" | grep "ASDF INSTALLED PLUGINS:") + [ "$result" != "" ] +} From 63f422b4c7afcf53ef72002e39967eb9ca2da2a9 Mon Sep 17 00:00:00 2001 From: Ben Hicks Date: Sun, 2 Apr 2023 20:52:57 -0600 Subject: [PATCH 19/42] docs: fix `ASDF_${LANG}_VERSION` usage (#1528) --- docs/manage/versions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/manage/versions.md b/docs/manage/versions.md index 3afc0c59c..99f8f83d2 100644 --- a/docs/manage/versions.md +++ b/docs/manage/versions.md @@ -80,7 +80,7 @@ asdf local latest[:] `global` writes the version to `$HOME/.tool-versions`. -`shell` set the version to an environment variable named `ASDF_${LANG}_VERSION`, for the current shell session only. +`shell` set the version to an environment variable named `ASDF_${TOOL}_VERSION`, for the current shell session only. `local` writes the version to `$PWD/.tool-versions`, creating it if needed. From 8108ca6d7e5f34b9b9723f945a9c4b137f2e10ef Mon Sep 17 00:00:00 2001 From: James Hegedus Date: Wed, 5 Apr 2023 23:31:56 +1000 Subject: [PATCH 20/42] docs: verbose plugin create command details (#1445) --- docs/plugins/create.md | 903 +++++++++++++++++++++++++++++++++++------ 1 file changed, 770 insertions(+), 133 deletions(-) diff --git a/docs/plugins/create.md b/docs/plugins/create.md index cafc9f053..b87566fae 100644 --- a/docs/plugins/create.md +++ b/docs/plugins/create.md @@ -1,104 +1,525 @@ # Create a Plugin -## What's in a Plugin - -A plugin is a git repo, with a couple executable scripts, to support versioning another language or tool. These scripts are run when `list-all`, `install` or `uninstall` commands are run. You can set or unset env vars and do anything required to setup the environment for the tool. +A plugin is a Git repo with some executable scripts to support versioning a +language / tool. These scripts are run by asdf using specific commands to +support features such as `asdf list-all `, `asdf install ` +etc. + +## Quickstart + +There are two options to get started with creating your own plugin: + +1. use the + [asdf-vm/asdf-plugin-template](https://github.com/asdf-vm/asdf-plugin-template) + repository to + [generate](https://github.com/asdf-vm/asdf-plugin-template/generate) a plugin + repo (named `asdf-`) with default scripts implemented. Once + generated, clone the repo and run the `setup.bash` script to interactively + update the template. +2. start your own repo called `asdf-` and implement the required + scripts as listed in the documentation below. + +### Golden Rules for Plugin Scripts + +- scripts should **NOT** call other `asdf` commands +- keep your dependency list of Shell tools/commands small +- avoid non-portable tools or command flags. For example, `sort -V`. See our + asdf core + [list of banned commands](https://github.com/asdf-vm/asdf/blob/master/test/banned_commands.bats) + +## Scripts Overview + +The full list of scripts callable from asdf. + +| Script | Description | +| :---------------------------------------------------------------------------------------------------- |:-----------------------------------------------------------------| +| [bin/list-all](#bin-list-all) | List all installable versions | +| [bin/download](#bin-download) | Download source code or binary for the specified version | +| [bin/install](#bin-install) | Installs the specified version | +| [bin/latest-stable](#bin-latest-stable) | List the latest stable version of the specified tool | +| [bin/help.overview](#bin-help.overview) | Output a general description about the plugin & tool | +| [bin/help.deps](#bin-help.deps) | Output a list of dependencies per Operating System | +| [bin/help.config](#bin-help.config) | Output plugin or tool configuration information | +| [bin/help.links](#bin-help.links) | Output a list of links for the plugin or tool | +| [bin/list-bin-paths](#bin-list-bin-paths) | List relative paths to directories with binaries to create shims | +| [bin/exec-env](#bin-exec-env) | Prepare the environment for running the binaries | +| [bin/exec-path](#bin-exec-path) | Output the executable path for a version of a tool | +| [bin/uninstall](#bin-uninstall) | Uninstall a specific version of a tool | +| [bin/list-legacy-filenames](#bin-list-legacy-filenames) | Output filenames of legacy version files: `.ruby-version` | +| [bin/parse-legacy-file](#bin-parse-legacy-file) | Custom parser for legacy version files | +| [bin/post-plugin-add](#bin-post-plugin-add) | Hook to execute after a plugin has been added | +| [bin/post-plugin-update](#bin-post-plugin-update) | Hook to execute after a plugin has been updated | +| [bin/pre-plugin-remove](#bin-pre-plugin-remove) | Hook to execute before a plugin is removed | + +To see which commands invoke which scripts, see the detailed documentation for +each script. + +## Environment Variables Overview + +The full list of Environment Variables used throughout all scripts. + +| Environment Variables | Description | +| :----------------------- |:----------------------------------------------------------------------------------------| +| `ASDF_INSTALL_TYPE` | `version` or `ref` | +| `ASDF_INSTALL_VERSION` | full version number or Git Ref depending on `ASDF_INSTALL_TYPE` | +| `ASDF_INSTALL_PATH` | the path to where the tool _should_, or _has been_ installed | +| `ASDF_CONCURRENCY` | the number of cores to use when compiling the source code. Useful for setting `make -j` | +| `ASDF_DOWNLOAD_PATH` | the path to where the source code or binary was downloaded to by `bin/download` | +| `ASDF_PLUGIN_PATH` | the path the plugin was installed | +| `ASDF_PLUGIN_SOURCE_URL` | the source URL of the plugin | +| `ASDF_PLUGIN_PREV_REF` | prevous `git-ref` of the plugin repo | +| `ASDF_PLUGIN_POST_REF` | updated `git-ref` of the plugin repo | +| `ASDF_CMD_FILE` | resolves to the full path of the file being sourced | + +::: tip NOTE + +**Not all environment variables are available in all scripts.** Check the +documentation for each script below to see which env vars are available to it. + +::: ## Required Scripts -- `bin/list-all` - lists all installable versions -- `bin/download` - download source code or binary for the specified version -- `bin/install` - installs the specified version +### `bin/list-all` -## Environment Variables +**Description** -All scripts except `bin/list-all` will have access to the following env vars to act upon: +List all installable versions. -- `ASDF_INSTALL_TYPE` - `version` or `ref` -- `ASDF_INSTALL_VERSION` - if `ASDF_INSTALL_TYPE` is `version` then this will be the version number. Else it will be the git ref that is passed. Might point to a tag/commit/branch on the repo. -- `ASDF_INSTALL_PATH` - the dir where it _has been_ installed (or _should_ be installed in case of the `bin/install` script) +**Output Format** -These additional environment variables will be available to the `bin/install` script: +Must print a string with a **space-separated** list of versions. For example: -- `ASDF_CONCURRENCY` - the number of cores to use when compiling the source code. Useful for setting `make -j`. -- `ASDF_DOWNLOAD_PATH` - the path to where the source code or binary was downloaded by the `bin/download` script. +```text:no-line-numbers +1.0.1 1.0.2 1.3.0 1.4 +``` -These additional environment variables will be available to the `bin/download` script: +Newest version should be last. -- `ASDF_DOWNLOAD_PATH` - the path to where the source code or binary should be downloaded. +asdf core will print each version on its own line, potentially pushing some +versions offscreen. -#### bin/list-all +**Sorting** -Must print a string with a space-separated list of versions. Example output would be the following: +If versions are being pulled from releases page on a website it's recommended to +leave the versions in the provided order as they are often already in the +correct order. If they are in reverse order piping them through `tac` should +suffice. -```shell -1.0.1 1.0.2 1.3.0 1.4 +If sorting is unavoidable, `sort -V` is not portable, so we suggest either: + +- [using the Git sort capability](https://github.com/asdf-vm/asdf-plugin-template/blob/main/template/lib/utils.bash) + (requires Git >= `v2.18.0`) +- [writing a custom sort method](https://github.com/vic/asdf-idris/blob/master/bin/list-all#L6) + (requires `sed`, `sort` & `awk`) + +**Environment Variables available to script** + +No environment variables are provided to this script. + +**Commands that invoke this script** + +- `asdf list all [version]` +- `asdf list all nodejs`: lists all versions as returned by this script, one on + each line. +- `asdf list all nodejs 18`: lists all versions as returned by this script, one + on each line, with a filter matching any version beginning with `18` applied. + +**Call signature from asdf core** + +No parameters provided. + +```bash:no-line-numbers +"${plugin_path}/bin/list-all" +``` + +--- + +### `bin/download` + +**Description** + +Download the source code or binary for a specific version of a tool to a specified location. + +**Implementation Details** + +- The script must download the source or binary to the directory specified by `ASDF_DOWNLOAD_PATH`. +- Only the decompressed source code or binary should be placed in the `ASDF_DOWNLOAD_PATH` directory. +- On failure, no files should be placed in `ASDF_DOWNLOAD_PATH`. +- Success should exit with `0`. +- Failure should exit with a non-zero status. + +**Legacy Plugins** + +Though this script is marked as _required_ for all plugins, it is _optional_ for "legacy" plugins which predate its introduction. + +If this script is absent, asdf will assume that the `bin/install` script is present and will download **and** install the version. + +All plugins must include this script as support for legacy plugins will eventually be removed. + +**Environment Variables available to script** + +- `ASDF_INSTALL_TYPE`: `version` or `ref` +- `ASDF_INSTALL_VERSION`: + - Full version number if `ASDF_INSTALL_TYPE=version`. + - Git ref (tag/commit/branch) if `ASDF_INSTALL_TYPE=ref`. +- `ASDF_INSTALL_PATH`: The path to where the tool _has been_, or _should be_ installed. +- `ASDF_DOWNLOAD_PATH`: The path to where the source code or binary was downloaded to. + +**Commands that invoke this script** + +- `asdf install [version]` +- `asdf install latest[:version]` +- `asdf install nodejs 18.0.0`: downloads the source code or binary for Node.js + version `18.0.0` and places it in the `ASDF_DOWNLOAD_PATH` directory. Then runs the `bin/install` script. + +**Call signature from asdf core** + +No parameters provided. + +```bash:no-line-numbers +"${plugin_path}"/bin/download ``` -Note that the newest version should be listed last so it appears closer to the user's prompt. This is helpful since the `list-all` command prints each version on its own line. If there are many versions it's possible the early versions will be off screen. +--- + +### `bin/install` + +**Description** -If versions are being pulled from releases page on a website it's recommended to not sort the versions if at all possible. Often the versions are already in the correct order or, in reverse order, in which case something like `tac` should suffice. If you must sort versions manually you cannot rely on `sort -V` since it is not supported on OSX. An alternate sort function [like this is a better choice](https://github.com/vic/asdf-idris/blob/master/bin/list-all#L6). +Install a specific version of a tool to a specified location. -#### bin/download +**Implementation Details** -This script must download the source or binary, in the path contained in the `ASDF_DOWNLOAD_PATH` environment variable. If the downloaded source or binary is compressed, only the uncompressed source code or binary may be placed in the `ASDF_DOWNLOAD_PATH` directory. +- The script should install the specified version in the path `ASDF_INSTALL_PATH`. +- Shims will be created by default for any files in `$ASDF_INSTALL_PATH/bin`. This behaviour can be customised with the optional +[bin/list-bin-paths](#binlist-bin-paths) script. +- Success should exit with `0`. +- Failure should exit with a non-zero status. +- To avoid TOCTOU (Time-of-Check-to-Time-of-Use) issues, ensure the script only places files in `ASDF_INSTALL_PATH` once the build and installation of the tool is deemed a success. -The script must exit with a status of `0` when the download is successful. If the download fails the script must exit with any non-zero exit status. +**Legacy Plugins** -If possible the script should only place files in the `ASDF_DOWNLOAD_PATH`. If the download fails no files should be placed in the directory. +If the `bin/download` script is absent, this script should download **and** install the specified version. -If this script is not present asdf will assume that the `bin/install` script is present and will download and install the version. asdf only works without this script to support legacy plugins. All plugins must include this script, and eventually support for legacy plugins will be removed. +For compatibility with versions of the asdf core earlier than `0.7._` and newer than `0.8._`, check for the presence of the `ASDF_DOWNLOAD_PATH` environment +variable. If set, assume the `bin/download` script already downloaded the version, else download the source code in the `bin/install` script. -#### bin/install +**Environment Variables available to script** -This script should install the version, in the path mentioned in `ASDF_INSTALL_PATH`. By default, asdf will create shims for any files in `$ASDF_INSTALL_PATH/bin` (this can be customized with the optional [bin/list-bin-paths](#binlist-bin-paths) script). +- `ASDF_INSTALL_TYPE`: `version` or `ref` +- `ASDF_INSTALL_VERSION`: + - Full version number if `ASDF_INSTALL_TYPE=version`. + - Git ref (tag/commit/branch) if `ASDF_INSTALL_TYPE=ref`. +- `ASDF_INSTALL_PATH`: The path to where the tool _has been_, or _should be_ installed. +- `ASDF_CONCURRENCY`: The number of cores to use when compiling source code. Useful for setting flags like `make -j`. +- `ASDF_DOWNLOAD_PATH`: The path where the source code or binary was downloaded to. -The install script should exit with a status of `0` when the installation is successful. If the installation fails the script should exit with any non-zero exit status. +**Commands that invoke this script** -If possible the script should only place files in the `ASDF_INSTALL_PATH` directory once the build and installation of the tool is deemed successful by the install script. asdf [checks for the existence](https://github.com/asdf-vm/asdf/blob/242d132afbf710fe3c7ec23c68cec7bdd2c78ab5/lib/utils.sh#L44) of the `ASDF_INSTALL_PATH` directory in order to determine if that version of the tool is installed. If the `ASDF_INSTALL_PATH` directory is populated at the beginning of the installation process other asdf commands run in other terminals during the installation may consider that version of the tool installed, even when it is not fully installed. +- `asdf install` +- `asdf install ` +- `asdf install [version]` +- `asdf install latest[:version]` +- `asdf install nodejs 18.0.0`: installs Node.js version `18.0.0` in the + `ASDF_INSTALL_PATH` directory. -If you want your plugin to work with asdf version 0.7._ and earlier and version 0.8._ and newer check for the presence of the `ASDF_DOWNLOAD_PATH` environment variable. If it is not set download the source code in the bin/install callback. If it is set assume the `bin/download` script already downloaded it. +**Call signature from asdf core** + +No parameters provided. + +```bash:no-line-numbers +"${plugin_path}"/bin/install +``` ## Optional Scripts -#### bin/help scripts +### `bin/latest-stable` -This is not one callback script but rather a set of callback scripts that each print different documentation to STDOUT. The possible callback scripts are listed below. Note that `bin/help.overview` is a special case as it must be present for any help output to be displayed for the script. +**Description** -- `bin/help.overview` - This script should output a general description about the plugin and the tool being managed. No heading should be printed as asdf will print headings. Output may be free-form text but ideally only one short paragraph. This script must be present if you want asdf to provide help information for your plugin. All other help callback scripts are optional. -- `bin/help.deps` - This script should output the list of dependencies tailored to the operating system. One dependency per line. -- `bin/help.config` - This script should print any required or optional configuration that may be available for the plugin and tool. Any environment variables or other flags needed to install or compile the tool (for the users operating system when possible). Output can be free-form text. -- `bin/help.links` - This should be a list of links relevant to the plugin and tool (again, tailored to the current operating system when possible). One link per line. Lines may be in the format `: <link>` or just `<link>`. +Determine the latest stable version of a tool. If absent, the asdf core will `tail` the `bin/list-all` output which may be undesirable. -Each of these scripts should tailor their output to the current operating system. For example, when on Ubuntu the deps script could output the dependencies as apt-get packages that must be installed. The script should also tailor its output to the value of `ASDF_INSTALL_VERSION` and `ASDF_INSTALL_TYPE` when the variables are set. They are optional and will not always be set. +**Implementation Details** -The help callback script MUST NOT output any information that is already covered in the core asdf-vm documentation. General asdf usage information must not be present. +- The script should print the latest stable version of the tool to stdout. +- Non-stable or release candidate versions should be omitted. +- A filter query is provided as the first argument to the script. This should be used to filter the output by version number or tool provider. + - For instance, the output of `asdf list all ruby` from the [ruby plugin](https://github.com/asdf-vm/asdf-ruby) lists versions of Ruby from many providers: `jruby`, `rbx` & `truffleruby` amongst others. The user provided filter could be used by the plugin to filter the semver versions and/or provider. + ``` + > asdf latest ruby + 3.2.2 + > asdf latest ruby 2 + 2.7.8 + > asdf latest ruby truffleruby + truffleruby+graalvm-22.3.1 + ``` +- Success should exit with `0`. +- Failure should exit with a non-zero status. -#### bin/latest-stable +**Environment Variables available to script** -If this callback is implemented asdf will use it to determine the latest stable version of your tool instead of trying deduce it for you on its own. `asdf latest` deduces the latest version by looking at the last version printed by the `list-all` callback, after a few types of versions (like release candidate versions) are excluded from the output. This default behavior is undesirable when your plugin's `list-all` callback prints different variations of the same tool and the last version isn't the latest stable version of the variation you'd like to default to. For example with Ruby the latest stable version should be the regular implementation of Ruby (MRI), but truffleruby versions are printed last by the `list-all` callback. +- `ASDF_INSTALL_TYPE`: `version` or `ref` +- `ASDF_INSTALL_VERSION`: + - Full version number if `ASDF_INSTALL_TYPE=version`. + - Git ref (tag/commit/branch) if `ASDF_INSTALL_TYPE=ref`. +- `ASDF_INSTALL_PATH`: The path to where the tool _has been_, or _should be_ installed. -This callback is invoked with a single "filter" string as its only argument. This should be used for filter all latest stable versions. For example with Ruby, the user may choose to pass in `jruby` to select the latest stable version of `jruby`. +**Commands that invoke this script** -#### bin/list-bin-paths +- `asdf global <tool> latest`: set the global version of a tool to the latest stable version for that tool. +- `asdf local <name> latest`: set the local version of a tool to the latest stable version for that tool. +- `asdf install <tool> latest`: installs the latest version of a tool. +- `asdf latest <tool> [<version>]`: outputs the latest version of a tool based on the optional filter. +- `asdf latest --all`: outputs the latest version of all tools managed by asdf and whether they are installed. -List executables for the specified version of the tool. Must print a string with a space-separated list of dir paths that contain executables. The paths must be relative to the install path passed. Example output would be: +**Call signature from asdf core** -```shell +The script should accept a single argument, the filter query. + +```bash:no-line-numbers +"${plugin_path}"/bin/latest-stable "" +"${plugin_path}"/bin/latest-stable "$query" +``` + +--- + +### `bin/help.overview` + +**Description** + +Output a general description about the plugin and the tool being managed. + +**Implementation Details** + +- This script is required for any help output to be displayed for the plugin. +- No heading should be printed as asdf core will print headings. +- Output may be free-form text but ideally only one short paragraph. +- Must not output any information that is already covered in the core asdf-vm documentation. +- Should be tailored to the Operating System and version of the tool being installed (using optionally set Environment Variables `ASDF_INSTALL_VERSION` and `ASDF_INSTALL_TYPE`). +- Success should exit with `0`. +- Failure should exit with a non-zero status. + +**Environment Variables available to script** + +- `ASDF_INSTALL_TYPE`: `version` or `ref` +- `ASDF_INSTALL_VERSION`: + - Full version number if `ASDF_INSTALL_TYPE=version`. + - Git ref (tag/commit/branch) if `ASDF_INSTALL_TYPE=ref`. +- `ASDF_INSTALL_PATH`: The path to where the tool _has been_, or _should be_ installed. + +**Commands that invoke this script** + +- `asdf help <name> [<version>]`: Output documentation for plugin and tool + +**Call signature from asdf core** + +```bash:no-line-numbers +"${plugin_path}"/bin/help.overview +``` + +--- + +### `bin/help.deps` + +**Description** + +Output the list of dependencies tailored to the operating system. One dependency per line. + +```bash:no-line-numbers +git +curl +sed +``` + +**Implementation Details** + +- This script requires `bin/help.overview` for its output to be considered. +- Should be tailored to the Operating System and version of the tool being installed (using optionally set Environment Variables `ASDF_INSTALL_VERSION` and `ASDF_INSTALL_TYPE`). +- Success should exit with `0`. +- Failure should exit with a non-zero status. + +**Environment Variables available to script** + +- `ASDF_INSTALL_TYPE`: `version` or `ref` +- `ASDF_INSTALL_VERSION`: + - Full version number if `ASDF_INSTALL_TYPE=version`. + - Git ref (tag/commit/branch) if `ASDF_INSTALL_TYPE=ref`. +- `ASDF_INSTALL_PATH`: The path to where the tool _has been_, or _should be_ installed. + +**Commands that invoke this script** + +- `asdf help <name> [<version>]`: Output documentation for plugin and tool + +**Call signature from asdf core** + +```bash:no-line-numbers +"${plugin_path}"/bin/help.deps +``` + +--- + +### `bin/help.config` + +**Description** + +Output any required or optional configuration for the plugin and tool. For example, describe any environment variables or other flags needed to install or compile the tool. + +**Implementation Details** + +- This script requires `bin/help.overview` for its output to be considered. +- Output can be free-form text. +- Should be tailored to the Operating System and version of the tool being installed (using optionally set Environment Variables `ASDF_INSTALL_VERSION` and `ASDF_INSTALL_TYPE`). +- Success should exit with `0`. +- Failure should exit with a non-zero status. + +**Environment Variables available to script** + +- `ASDF_INSTALL_TYPE`: `version` or `ref` +- `ASDF_INSTALL_VERSION`: + - Full version number if `ASDF_INSTALL_TYPE=version`. + - Git ref (tag/commit/branch) if `ASDF_INSTALL_TYPE=ref`. +- `ASDF_INSTALL_PATH`: The path to where the tool _has been_, or _should be_ installed. + +**Commands that invoke this script** + +- `asdf help <name> [<version>]`: Output documentation for plugin and tool + +**Call signature from asdf core** + +```bash:no-line-numbers +"${plugin_path}"/bin/help.config +``` + +--- + +### `bin/help.links` + +**Description** + +Output a list of links relevant to the plugin and tool. One link per line. + +```bash:no-line-numbers +Git Repository: https://github.com/vlang/v +Documentation: https://vlang.io +``` + +**Implementation Details** + +- This script requires `bin/help.overview` for its output to be considered. +- One link per line. +- Format must be either: + - `<title>: <link>` + - or just `<link>` +- Should be tailored to the Operating System and version of the tool being installed (using optionally set Environment Variables `ASDF_INSTALL_VERSION` and `ASDF_INSTALL_TYPE`). +- Success should exit with `0`. +- Failure should exit with a non-zero status. + +**Environment Variables available to script** + +- `ASDF_INSTALL_TYPE`: `version` or `ref` +- `ASDF_INSTALL_VERSION`: + - Full version number if `ASDF_INSTALL_TYPE=version`. + - Git ref (tag/commit/branch) if `ASDF_INSTALL_TYPE=ref`. +- `ASDF_INSTALL_PATH`: The path to where the tool _has been_, or _should be_ installed. + +**Commands that invoke this script** + +- `asdf help <name> [<version>]`: Output documentation for plugin and tool + +**Call signature from asdf core** + +```bash:no-line-numbers +"${plugin_path}"/bin/help.links +``` + +--- + +### `bin/list-bin-paths` + +**Description** + +List directories containing executables for the specified version of the tool. + +**Implementation Details** + +- If this script is not present, asdf will look for binaries in the `"${ASDF_INSTALL_PATH}"/bin` directory & create shims for those. +- Output a space-separated list of paths containing executables. +- Paths must be relative to `ASDF_INSTALL_PATH`. Example output would be: + +```bash:no-line-numbers bin tools veggies ``` -This will instruct asdf to create shims for the files in `<install-path>/bin`, `<install-path>/tools` and `<install-path>/veggies` +This will instruct asdf to create shims for the files in: +- `"${ASDF_INSTALL_PATH}"/bin` +- `"${ASDF_INSTALL_PATH}"/tools` +- `"${ASDF_INSTALL_PATH}"/veggies` + +**Environment Variables available to script** + +- `ASDF_INSTALL_TYPE`: `version` or `ref` +- `ASDF_INSTALL_VERSION`: + - Full version number if `ASDF_INSTALL_TYPE=version`. + - Git ref (tag/commit/branch) if `ASDF_INSTALL_TYPE=ref`. +- `ASDF_INSTALL_PATH`: The path to where the tool _has been_, or _should be_ installed. + +**Commands that invoke this script** + +- `asdf install <tool> [version]`: initially create shims for binaries. +- `asdf reshim <tool> <version>`: recreate shims for binaries. + +**Call signature from asdf core** + +```bash:no-line-numbers +"${plugin_path}/bin/list-bin-paths" +``` + +--- + +### `bin/exec-env` + +**Description** + +Prepare the environment before executing the shims for the binaries for the tool. + +**Environment Variables available to script** + +- `ASDF_INSTALL_TYPE`: `version` or `ref` +- `ASDF_INSTALL_VERSION`: + - Full version number if `ASDF_INSTALL_TYPE=version`. + - Git ref (tag/commit/branch) if `ASDF_INSTALL_TYPE=ref`. +- `ASDF_INSTALL_PATH`: The path to where the tool _has been_, or _should be_ installed. + +**Commands that invoke this script** + +- `asdf which <command>`: Display the path to an executable +- `asdf exec <command> [args...]`: Executes the command shim for current version +- `asdf env <command> [util]`: Runs util (default: `env`) inside the environment used for command shim execution. + +**Call signature from asdf core** + +```bash:no-line-numbers +"${plugin_path}/bin/exec-env" +``` + +--- -If this script is not specified, asdf will look for the `bin` dir in an installation and create shims for those. +### `bin/exec-path` -#### bin/exec-env +Get the executable path for the specified version of the tool. Must print a +string with the relative executable path. This allows the plugin to +conditionally override the shim's specified executable path, otherwise return +the default path specified by the shim. -Setup the env to run the binaries in the package. +**Description** -#### bin/exec-path +Get the executable path for the specified version of the tool. -Get the executable path for the specified version of the tool. Must print a string with the relative executable path. This allows the plugin to conditionally override the shim's specified executable path, otherwise return the default path specified by the shim. +**Implementation Details** + +- Must print a string with the relative executable path. +- Conditionally override the shim's specified executable path, otherwise return the default path specified by the shim. ```shell Usage: @@ -111,71 +532,222 @@ Output: bin/foox ``` -#### bin/uninstall +**Environment Variables available to script** -Uninstalls a specific version of a tool. +- `ASDF_INSTALL_TYPE`: `version` or `ref` +- `ASDF_INSTALL_VERSION`: + - Full version number if `ASDF_INSTALL_TYPE=version`. + - Git ref (tag/commit/branch) if `ASDF_INSTALL_TYPE=ref`. +- `ASDF_INSTALL_PATH`: The path to where the tool _has been_, or _should be_ installed. -#### bin/list-legacy-filenames +**Commands that invoke this script** -Register additional setter files for this plugin. Must print a string with a space-separated list of filenames. +- `asdf which <command>`: Display the path to an executable +- `asdf exec <command> [args...]`: Executes the command shim for current version +- `asdf env <command> [util]`: Runs util (default: `env`) inside the environment used for command shim execution. -```shell -.ruby-version .rvmrc +**Call signature from asdf core** + +```bash:no-line-numbers +"${plugin_path}/bin/exec-path" "$install_path" "$cmd" "$relative_path" +``` + +--- + +### `bin/uninstall` + +**Description** + +Uninstall the provided version of a tool. + +**Output Format** + +Output should be sent to `stdout` or `stderr` as appropriate for the user. No output is read by subsequent execution in the core. + +**Environment Variables available to script** + +No environment variables are provided to this script. + +**Commands that invoke this script** + +- `asdf list all <name> <version>` +- `asdf uninstall nodejs 18.15.0`: Uninstalls the version `18.15.0` of nodejs, removing all shims including those installed global with `npm i -g` + +**Call signature from asdf core** + +No parameters provided. + +```bash:no-line-numbers +"${plugin_path}/bin/uninstall" +``` + +--- + +### `bin/list-legacy-filenames` + +**Description** + +List legacy configuration filenames for determining the specified version of the tool. + +**Implementation Details** + +- Output a space-separated list of filenames. + ```bash:no-line-numbers + .ruby-version .rvmrc + ``` +- Only applies for users who have enabled the `legacy_version_file` option in their `"${HOME}"/.asdfrc`. + +**Environment Variables available to script** + +- `ASDF_INSTALL_TYPE`: `version` or `ref` +- `ASDF_INSTALL_VERSION`: + - Full version number if `ASDF_INSTALL_TYPE=version`. + - Git ref (tag/commit/branch) if `ASDF_INSTALL_TYPE=ref`. +- `ASDF_INSTALL_PATH`: The path to where the tool _has been_, or _should be_ installed. + +**Commands that invoke this script** + +Any command which reads a tool version. + +**Call signature from asdf core** + +No parameters provided. + +```bash:no-line-numbers +"${plugin_path}/bin/list-legacy-filenames" ``` -Note: This will only apply for users who have enabled the `legacy_version_file` option in their `~/.asdfrc`. +--- + +### `bin/parse-legacy-file` + +**Description** + +Parse the legacy file found by asdf to determine the version of the tool. Useful to extract version numbers from files like JavaScript's `package.json` or Golangs `go.mod`. + +**Implementation Details** -#### bin/parse-legacy-file +- If not present, asdf will simply `cat` the legacy file to determine the version. +- Should be **deterministic** and always return the same exact version: + - when parsing the same legacy file. + - regardless of what is installed on the machine or whether the legacy version is valid or complete. Some legacy file formats may not be suitable. +- Output a single line with the version: + ```bash:no-line-numbers + 1.2.3 + ``` -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. Note that this script should be **deterministic** and always return the same exact version when parsing the same legacy file. The script should return the same version regardless of what is installed on the machine or whether the legacy version is valid or complete. Some legacy file formats may not be suitable. +**Environment Variables available to script** -#### bin/post-plugin-add +No environment variables specifically set before this script is called. -This can be used to run any post-installation actions after the plugin has been added to asdf. +**Commands that invoke this script** -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. +Any command which reads a tool version. -See also the related hooks: +**Call signature from asdf core** + +The script should accept a single argument, the path to the legacy file for reading its contents. + +```bash:no-line-numbers +"${plugin_path}/bin/parse-legacy-file" "$file_path" +``` + +--- + +### `bin/post-plugin-add` + +**Description** + +Execute this callback script **after** the plugin has been _added_ to asdf with `asdf plugin add <tool>`. + +See also the related command hooks: - `pre_asdf_plugin_add` - `pre_asdf_plugin_add_${plugin_name}` - `post_asdf_plugin_add` - `post_asdf_plugin_add_${plugin_name}` -#### bin/post-plugin-update +**Environment Variables available to script** + +- `ASDF_PLUGIN_PATH`: path where the plugin was installed. +- `ASDF_PLUGIN_SOURCE_URL`: URL of the plugin source. Can be a local directory path. + +**Call signature from asdf core** + +No parameters provided. + +```bash:no-line-numbers +"${plugin_path}/bin/post-plugin-add" +``` + +--- + +### `bin/post-plugin-update` -This can be used to run any post-plugin-update actions after asdf has downloaded the updated plugin +**Description** -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}`). +Execute this callback script **after** asdf has downloaded the _updated_ plugin with `asdf plugin update <tool> [<git-ref>]`. -See also the related hooks: +See also the related command 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 +**Environment Variables available to script** + +- `ASDF_PLUGIN_PATH`: path where the plugin was installed. +- `ASDF_PLUGIN_PREV_REF`: the plugin's previous git-ref +- `ASDF_PLUGIN_POST_REF`: the plugin's updated git-ref + +**Call signature from asdf core** + +No parameters provided. + +```bash:no-line-numbers +"${plugin_path}/bin/post-plugin-update" +``` -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}`). +### `bin/pre-plugin-remove` -See also the related hooks: +**Description** + +Execute this callback script **before** asdf has removed the plugin with `asdf plugin remove <tool>`. + +See also the related command 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. +**Environment Variables available to script** + +- `ASDF_PLUGIN_PATH`: path where the plugin was installed. + +**Call signature from asdf core** + +No parameters provided. + +```bash:no-line-numbers +"${plugin_path}/bin/pre-plugin-remove" +``` + +<!-- TODO: document command hooks --> +<!-- ## Command Hooks --> -It's possible for plugins to define new asdf commands by providing `lib/commands/command*.bash` scripts or executables that -will be callable using the asdf command line interface by using the plugin name as a subcommand. +## Extension Commands for asdf CLI <Badge type="danger" text="advanced" vertical="middle" /> + +It's possible for plugins to define new asdf commands by providing +`lib/commands/command*.bash` scripts or executables that will be callable using +the asdf command line interface by using the plugin name as a subcommand. For example, suppose a `foo` plugin has: -```shell +```shell:no-line-numbers foo/ lib/commands/ command.bash @@ -184,9 +756,9 @@ foo/ command-help.bash ``` -Users can now execute +Users can now execute: -```shell +```shell:no-line-numbers $ asdf foo # same as running `$ASDF_DATA_DIR/plugins/foo/lib/commands/command.bash` $ asdf foo bar # same as running `$ASDF_DATA_DIR/plugins/foo/lib/commands/command.bash bar` $ asdf foo help # same as running `$ASDF_DATA_DIR/plugins/foo/lib/commands/command-help.bash` @@ -195,69 +767,106 @@ $ asdf foo bat baz # same as running `$ASDF_DATA_DIR/plugins/foo/lib/commands/co ``` Plugin authors can use this feature to provide utilities related to their tools, -or even create plugins that are just new command extensions for asdf itself. +or even create plugins that are just new command extensions of asdf itself. -When invoked, if extension commands do not have their executable-bit set they will be -sourced as bash scripts. Also, the `$ASDF_CMD_FILE` resolves to the full path of the file being sourced. -If the executable bit is set, they are just executed and replace the asdf execution. +If the executable bit is set, the script is executed, replacing the asdf +execution. -A good example of this feature is for plugins like [`haxe`](https://github.com/asdf-community/asdf-haxe) -which provides the `asdf haxe neko-dylibs-link` to fix an issue where haxe executables expect to find -dynamic libraries relative to the executable directory. +If the executable bit is not set, asdf will source the scripts as Bash scripts. -If your plugin provides an asdf extension command, be sure to mention it in your plugin's README. +`$ASDF_CMD_FILE` resolves to the full path of the file being sourced. -## Custom shim templates +[`haxe`](https://github.com/asdf-community/asdf-haxe) is a great example of a +plugin which uses this feature. It provides the `asdf haxe neko-dylibs-link` to +fix an issue where Haxe executables expect to find dynamic libraries relative to +the executable directory. -**PLEASE use this feature only if absolutely required** +Be sure to list your asdf Extension Commands in your plugins README. -asdf allows custom shim templates. For an executable called `foo`, if there's a `shims/foo` file in the plugin, then asdf will copy that file instead of using its standard shim template. +## Custom Shim Templates <Badge type="danger" text="advanced" vertical="middle" /> -This must be used wisely. For now AFAIK, it's only being used in the Elixir plugin, because an executable is also read as an Elixir file apart from just being an executable. Which makes it not possible to use the standard bash shim. +::: warning -## Testing plugins +Please only use if **absolutely** required -`asdf` contains the `plugin-test` command to test your plugin. You can use it as follows +::: -```shell -asdf plugin test <plugin-name> <plugin-url> [--asdf-tool-version <version>] [--asdf-plugin-gitref <git-ref>] [test-command*] -``` +asdf allows custom shim templates. For an executable called `foo`, if there's a +`shims/foo` file in the plugin, then asdf will copy that file instead of using +its standard shim template. -Only the two first arguments are required. -If \__version_ is specified, the tool will be installed with that specific version. Defaults to whatever returns `asdf latest <plugin-name>`. -If _git-ref_ is specified, the plugin itself is checked out at that commit/branch/tag, useful for testing a pull-request on your plugin's CI. +**This must be used wisely.** -Rest arguments are considered the command to execute to ensure the installed tool works correctly. -Normally it would be something that takes `--version` or `--help`. -For example, to test the NodeJS plugin, we could run +As far as the asdf core team is aware, this feature is only in use in the +first-party [Elixir plugin](https://github.com/asdf-vm/asdf-elixir). This is +because an executable is also read as an Elixir file in addition to being an +executable. This makes it not possible to use the standard Bash shim. -```shell -asdf plugin test nodejs https://github.com/asdf-vm/asdf-nodejs.git node --version +## Testing + +`asdf` contains the `plugin-test` command to test your plugin: + +```shell:no-line-numbers +asdf plugin test <plugin_name> <plugin_url> [--asdf-tool-version <version>] [--asdf-plugin-gitref <git_ref>] [test_command...] ``` -We strongly recommend you test your plugin on a CI environment and make sure it works on both Linux and OSX. +- `<plugin_name>` & `<plugin_url>` are required +- If optional `[--asdf-tool-version <version>]` is specified, the tool will be + installed with that specific version. Defaults to `asdf latest <plugin-name>` +- If optional `[--asdf-plugin-gitref <git_ref>]` is specified, the plugin itself + is checked out at that commit/branch/tag. This is useful for testing a + pull-request on your plugin's CI. +- Optional parameter `[test_command...]` is the command to execute to validate + the installed tool works correctly. Typically `<tool> --version` or + `<tool> --help`. For example, to test the NodeJS plugin, we could run + ```shell:no-line-numbers + # asdf plugin test <plugin_name> <plugin_url> [test_command] + asdf plugin test nodejs https://github.com/asdf-vm/asdf-nodejs.git node --version + ``` + +::: tip Note + +We recommend testing in both Linux & macOS CI environments + +::: -#### Example GitHub Action +### GitHub Action -The [asdf-vm/actions](https://github.com/asdf-vm/actions) repo provides a GitHub Action for testing your plugins hosted on github. +The [asdf-vm/actions](https://github.com/asdf-vm/actions) repo provides a GitHub +Action for testing your plugins hosted on GitHub. A sample +`.github/workflows/test.yaml` Actions Workflow: ```yaml -steps: - - name: asdf_plugin_test - uses: asdf-vm/actions/plugin-test@v1 - with: - command: "my_tool --version" - env: - GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} # automatically provided +name: Test +on: + push: + branches: + - main + pull_request: + +jobs: + plugin_test: + name: asdf plugin test + strategy: + matrix: + os: + - ubuntu-latest + - macos-latest + runs-on: ${{ matrix.os }} + steps: + - name: asdf_plugin_test + uses: asdf-vm/actions/plugin-test@v2 + with: + command: "<MY_TOOL> --version" ``` -#### Example TravisCI config +### TravisCI Config -Here is a sample `.travis.yml` file, customize it to your needs +A sample `.travis.yml` file, customize it to your needs ```yaml language: c -script: asdf plugin test nodejs $TRAVIS_BUILD_DIR 'node --version' +script: asdf plugin test <MY_TOOL> $TRAVIS_BUILD_DIR '<MY_TOOL> --version' before_script: - git clone https://github.com/asdf-vm/asdf.git asdf - . asdf/asdf.sh @@ -266,25 +875,26 @@ os: - osx ``` -Note: -When using another CI, you will need to check what variable maps to the repo path. +::: tip NOTE -You also have the option to pass a relative path to `plugin-test`. +When using another CI you may need to pass a relative path to the plugin +location: -For example, if the test script is ran in the repo directory: `asdf plugin test nodejs . 'node --version'`. - -## GitHub API Rate Limiting - -If your plugin's `list-all` depends on accessing the GitHub API, make sure you provide an Authorization token when accessing it, otherwise your tests might fail due to rate limiting. +```shell:no-line-numbers +asdf plugin test <tool_name> <path> '<tool_command> --version' +``` -To do so, create a [new personal token](https://github.com/settings/tokens/new) with only `public_repo` access. +::: -Then on your travis.ci build settings add a _secure_ environment variable for it named something like `GITHUB_API_TOKEN`. And _DO NOT_ EVER publish your token in your code. +## API Rate Limiting -Finally, add something like the following to `bin/list-all` +If a command depends on accessing an external API, like `bin/list-all` or +`bin/latest-stable`, it may experience rate limiting during automated testing. +To mitigate this, ensure there is a code-path which provides an authentication +token via an environment variable. For example: ```shell -cmd="curl -s" +cmd="curl --silent" if [ -n "$GITHUB_API_TOKEN" ]; then cmd="$cmd -H 'Authorization: token $GITHUB_API_TOKEN'" fi @@ -292,10 +902,37 @@ fi cmd="$cmd $releases_path" ``` -## Submitting plugins to the official plugins repository +### `GITHUB_API_TOKEN` + +To utilise the `GITHUB_API_TOKEN`, create a +[new personal token](https://github.com/settings/tokens/new) with only +`public_repo` access. + +Then add this to your CI pipeline environment variables. + +::: warning + +NEVER publish your authentication tokens in your code repository + +::: + +## Plugin Shortname Index + +::: tip + +The recommended installation method for a plugin is via direct URL installation: + +```shell:no-line-numbers +# asdf plugin add <name> <git_url> + asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs +``` -`asdf` can easily install plugins by specifying the plugin repository url, e.g. `plugin add my-plugin https://github.com/user/asdf-my-plugin.git`. +::: -To make it easier on your users, you can add your plugin to the official plugins repository to have your plugin listed and easily installable using a shorter command, e.g. `asdf plugin add my-plugin`. +If the `git_url` is not provided, asdf will use the +[Shortname Index repository](https://github.com/asdf-vm/asdf-plugins) to +determine the exact `git_url` to use. -Follow the instruction at the plugins repository: [asdf-vm/asdf-plugins](https://github.com/asdf-vm/asdf-plugins). +You can add your plugin to the +[Shortname Index](https://github.com/asdf-vm/asdf-plugins) by following the +instructions in that repo. From d28b13a8c7a5f2cc99975a16fdd4e2769eab115b Mon Sep 17 00:00:00 2001 From: alexezio <35565813+alexezio@users.noreply.github.com> Date: Wed, 5 Apr 2023 21:48:13 +0800 Subject: [PATCH 21/42] test: reshim of plugins installed by path (#1287) Co-authored-by: Benchi Lian <benchi.lian@thoughtworks.com> Co-authored-by: James Hegedus <jthegedus@hey.com> --- test/reshim_command.bats | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/reshim_command.bats b/test/reshim_command.bats index 4b2bd549e..4b1db7ef5 100644 --- a/test/reshim_command.bats +++ b/test/reshim_command.bats @@ -157,3 +157,19 @@ EOM run grep -v 'borked_path_due_to_homebrew_update' "$dummy_shim" [ "$status" -eq 0 ] } + +@test "reshim should allow local path versions" { + run asdf install dummy 1.0 + + mkdir -p "$ASDF_DIR/installs/dummy/path/bin/" + touch "$ASDF_DIR/installs/dummy/path/bin/dummy" + chmod +x "$ASDF_DIR/installs/dummy/path/bin/dummy" + + run asdf reshim dummy "path:$ASDF_DIR/installs/dummy/path" + + [ "$status" -eq 0 ] + run grep "asdf-plugin: dummy 1.0" "$ASDF_DIR/shims/dummy" + [ "$status" -eq 0 ] + run grep "asdf-plugin: dummy path:$ASDF_DIR/installs/dummy" "$ASDF_DIR/shims/dummy" + [ "$status" -eq 0 ] +} From cbe57c444e258eae0fa87c8a4571cb9a7a5899ed Mon Sep 17 00:00:00 2001 From: James Hegedus <jthegedus@hey.com> Date: Thu, 6 Apr 2023 14:05:48 +1000 Subject: [PATCH 22/42] chore: bump nushell version in CI (#1530) --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index aec6c696c..bf9429b29 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,7 @@ on: env: ELVISH_VERSION: v0.19.2 - NUSHELL_VERSION: 0.77.0 + NUSHELL_VERSION: 0.78.0 jobs: detect-changes: From a1bc0e97cdcf7cccd500f6a7f800a1e6217aad59 Mon Sep 17 00:00:00 2001 From: James Hegedus <jthegedus@hey.com> Date: Thu, 6 Apr 2023 15:57:51 +1000 Subject: [PATCH 23/42] ci: pin all shell versions for Ubuntu test environment (#1531) --- .github/workflows/tests.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bf9429b29..d45730b66 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -8,7 +8,9 @@ on: env: ELVISH_VERSION: v0.19.2 + FISH_VERSION: 3.6.1 NUSHELL_VERSION: 0.78.0 + POWERSHELL_VERSION: 7.3.3 jobs: detect-changes: @@ -61,9 +63,11 @@ jobs: run: | curl -fsSLo- https://packages.microsoft.com/keys/microsoft.asc | sudo tee >/dev/null /etc/apt/trusted.gpg.d/microsoft.asc sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-bullseye-prod bullseye main" > /etc/apt/sources.list.d/microsoft.list' - sudo add-apt-repository -y ppa:fish-shell/nightly-master + sudo add-apt-repository -y ppa:fish-shell/release-3 sudo apt-get update - sudo apt-get -y install fish curl parallel powershell + sudo apt-get -y install curl parallel \ + fish="${{ env.FISH_VERSION }}-1~jammy" \ + powershell="${{ env.POWERSHELL_VERSION }}-1.deb" # Create $HOME/bin mkdir -p "$HOME/bin" @@ -106,7 +110,12 @@ jobs: fetch-depth: 0 - name: Install test dependencies - run: brew install coreutils parallel fish elvish nushell + run: | + brew install coreutils parallel \ + elvish \ + fish \ + nushell \ + powershell - name: Install bats run: | From 1bc205e8aa61287c766c673acb8f0d4f9c6ee249 Mon Sep 17 00:00:00 2001 From: Edwin Kofler <edwin@kofler.dev> Date: Mon, 10 Apr 2023 20:12:08 -0700 Subject: [PATCH 24/42] fix: enforce consistent shell redirection format (#1533) --- lib/commands/reshim.bash | 2 +- lib/functions/installs.bash | 4 +-- scripts/checkstyle.py | 68 ++++++++++++++++++++++++++++++------- 3 files changed, 59 insertions(+), 15 deletions(-) diff --git a/lib/commands/reshim.bash b/lib/commands/reshim.bash index 8a703a4d2..82bed60fb 100644 --- a/lib/commands/reshim.bash +++ b/lib/commands/reshim.bash @@ -11,7 +11,7 @@ remove_shim_for_version() { local count_installed count_installed=$(list_installed_versions "$plugin_name" | wc -l) - if ! grep -x "# asdf-plugin: $plugin_name $version" "$shim_path" >/dev/null 2>&1; then + if ! grep -x "# asdf-plugin: $plugin_name $version" "$shim_path" &>/dev/null; then return 0 fi diff --git a/lib/functions/installs.bash b/lib/functions/installs.bash index 9f85c652c..dbd403bab 100644 --- a/lib/functions/installs.bash +++ b/lib/functions/installs.bash @@ -25,9 +25,9 @@ install_command() { } get_concurrency() { - if command -v nproc >/dev/null 2>&1; then + if command -v nproc &>/dev/null; then nproc - elif command -v sysctl >/dev/null 2>&1 && sysctl hw.ncpu >/dev/null 2>&1; then + elif command -v sysctl &>/dev/null && sysctl hw.ncpu &>/dev/null; then sysctl -n hw.ncpu elif [ -f /proc/cpuinfo ]; then grep -c processor /proc/cpuinfo diff --git a/scripts/checkstyle.py b/scripts/checkstyle.py index 56c839afa..28294ea0b 100755 --- a/scripts/checkstyle.py +++ b/scripts/checkstyle.py @@ -80,17 +80,41 @@ def noFunctionKeywordFixer(line: str, m: Any) -> str: return f'{prestr}{midstr}() {poststr}' -def lintfile(filepath: Path, rules: List[Rule], options: Dict[str, Any]): - content_arr = filepath.read_text().split('\n') +# Before: >/dev/null 2>&1 +# After: &>/dev/null +# --- +# Before: 2>/dev/null 1>&2 +# After: &>/dev/null +def noVerboseRedirectionFixer(line: str, m: Any) -> str: + prestr, _, poststr = utilGetStrs(line, m) + + return f'{prestr}&>/dev/null{poststr}' + +def lintfile(file: Path, rules: List[Rule], options: Dict[str, Any]): + content_arr = file.read_text().split('\n') for line_i, line in enumerate(content_arr): if 'checkstyle-ignore' in line: continue for rule in rules: + should_run = False + if 'sh' in rule['fileTypes']: + if file.name.endswith('.sh') or str(file.absolute()).endswith('bin/asdf'): + should_run = True + if 'bash' in rule['fileTypes']: + if file.name.endswith('.bash') or file.name.endswith('.bats'): + should_run = True + + if options['verbose']: + print(f'{str(file)}: {should_run}') + + if not should_run: + continue + m = re.search(rule['regex'], line) if m is not None and m.group('match') is not None: - dir = os.path.relpath(filepath.resolve(), Path.cwd()) + dir = os.path.relpath(file.resolve(), Path.cwd()) prestr = line[0:m.start('match')] midstr = line[m.start('match'):m.end('match')] poststr = line[m.end('match'):] @@ -106,7 +130,7 @@ def lintfile(filepath: Path, rules: List[Rule], options: Dict[str, Any]): rule['found'] += 1 if options['fix']: - filepath.write_text('\n'.join(content_arr)) + file.write_text('\n'.join(content_arr)) def main(): rules: List[Rule] = [ @@ -114,6 +138,7 @@ def main(): 'name': 'no-double-backslash', 'regex': '".*?(?P<match>\\\\\\\\[abeEfnrtv\'"?xuUc]).*?(?<!\\\\)"', 'reason': 'Backslashes are only required if followed by a $, `, ", \\, or <newline>', + 'fileTypes': ['bash', 'sh'], 'fixerFn': noDoubleBackslashFixer, 'testPositiveMatches': [ 'printf "%s\\\\n" "Hai"', @@ -123,12 +148,12 @@ def main(): 'printf "%s\\n" "Hai"', 'echo -n "Hello\\n"' ], - 'found': 0 }, { 'name': 'no-pwd-capture', 'regex': '(?P<match>\\$\\(pwd\\))', 'reason': '$PWD is essentially equivalent to $(pwd) without the overhead of a subshell', + 'fileTypes': ['bash', 'sh'], 'fixerFn': noPwdCaptureFixer, 'testPositiveMatches': [ '$(pwd)' @@ -136,12 +161,12 @@ def main(): 'testNegativeMatches': [ '$PWD' ], - 'found': 0 }, { 'name': 'no-test-double-equals', 'regex': '(?<!\\[)\\[ (?:[^]]|](?=}))*?(?P<match>==).*?]', 'reason': 'Disallow double equals in places where they are not necessary for consistency', + 'fileTypes': ['bash', 'sh'], 'fixerFn': noTestDoubleEqualsFixer, 'testPositiveMatches': [ '[ a == b ]', @@ -156,12 +181,12 @@ def main(): '[[ "${lines[0]}" == \'usage: \'* ]]', '[ "${lines[0]}" = blah ]', ], - 'found': 0 }, { 'name': 'no-function-keyword', 'regex': '^[ \\t]*(?P<match>function .*?(?:\\([ \\t]*\\))?[ \\t]*){', 'reason': 'Only allow functions declared like `fn_name() {{ :; }}` for consistency (see ' + c.LINK('https://www.shellcheck.net/wiki/SC2113', 'ShellCheck SC2113') + ')', + 'fileTypes': ['bash', 'sh'], 'fixerFn': noFunctionKeywordFixer, 'testPositiveMatches': [ 'function fn() { :; }', @@ -170,13 +195,29 @@ def main(): 'testNegativeMatches': [ 'fn() { :; }', ], - 'found': 0 + }, + { + 'name': 'no-verbose-redirection', + 'regex': '(?P<match>(>/dev/null 2>&1|2>/dev/null 1>&2))', + 'reason': 'Use `&>/dev/null` instead of `>/dev/null 2>&1` or `2>/dev/null 1>&2` for consistency', + 'fileTypes': ['bash'], + 'fixerFn': noVerboseRedirectionFixer, + 'testPositiveMatches': [ + 'echo woof >/dev/null 2>&1', + 'echo woof 2>/dev/null 1>&2', + ], + 'testNegativeMatches': [ + 'echo woof &>/dev/null', + 'echo woof >&/dev/null', + ], }, ] + [rule.update({ 'found': 0 }) for rule in rules] parser = argparse.ArgumentParser() parser.add_argument('files', metavar='FILES', nargs='*') parser.add_argument('--fix', action='store_true') + parser.add_argument('--verbose', action='store_true') parser.add_argument('--internal-test-regex', action='store_true') args = parser.parse_args() @@ -199,7 +240,8 @@ def main(): return options = { - 'fix': args.fix + 'fix': args.fix, + 'verbose': args.verbose, } # parse files and print matched lints @@ -210,9 +252,11 @@ def main(): lintfile(p, rules, options) else: for file in Path.cwd().glob('**/*'): - if file.name.endswith('.bash') or file.name.endswith('.sh') or file.name.endswith('.bats') or str(file.absolute()).endswith('bin/asdf'): - if file.is_file(): - lintfile(file, rules, options) + if '.git' in str(file.absolute()): + continue + + if file.is_file(): + lintfile(file, rules, options) # print final results print(f'{c.UNDERLINE}TOTAL ISSUES{c.RESET}') From 491ef2a9f21eca25e2f2b85f0a625e4938f42e8f Mon Sep 17 00:00:00 2001 From: Edwin Kofler <edwin@kofler.dev> Date: Mon, 10 Apr 2023 20:58:58 -0700 Subject: [PATCH 25/42] test: rm useless `echo` usage in tests (#1535) --- test/latest_command.bats | 17 ++--------------- test/list_command.bats | 24 ++++++++++++------------ test/plugin_test_command.bats | 4 ---- test/shim_exec.bats | 1 - test/uninstall_command.bats | 2 +- test/update_command.bats | 4 ++-- test/utils.bats | 1 - 7 files changed, 17 insertions(+), 36 deletions(-) diff --git a/test/latest_command.bats b/test/latest_command.bats index 795327df9..9c0bd5af3 100644 --- a/test/latest_command.bats +++ b/test/latest_command.bats @@ -38,48 +38,36 @@ teardown() { #################################################### @test "[latest_command - dummy_legacy_plugin] shows latest stable version" { run asdf latest legacy-dummy - echo "status: $status" - echo "output: $output" [ "5.1.0" = "$output" ] [ "$status" -eq 0 ] } @test "[latest_command - dummy_legacy_plugin] shows latest stable version that matches the given string" { run asdf latest legacy-dummy 1 - echo "status: $status" - echo "output: $output" [ "1.1.0" = "$output" ] [ "$status" -eq 0 ] } @test "[latest_command - dummy_legacy_plugin] No stable version should return an error" { run asdf latest legacy-dummy 3 - echo "status: $status" - echo "output: $output" [ -z "$output" ] [ "$status" -eq 1 ] } @test "[latest_command - dummy_legacy_plugin] do not show latest unstable version that matches the given string" { run asdf latest legacy-dummy 4 - echo "status: $status" - echo "output: $output" [ "4.0.0" = "$output" ] [ "$status" -eq 0 ] } @test "[latest_command - dummy_legacy_plugin] do not show latest unstable version with capital characters that matches the given string" { run asdf latest legacy-dummy 5 - echo "status: $status" - echo "output: $output" [ "5.1.0" = "$output" ] [ "$status" -eq 0 ] } @test "[latest_command - dummy_legacy_plugin] an invalid version should return an error" { run asdf latest legacy-dummy 6 - echo "status: $status" - echo "output: $output" [ "No compatible versions available (legacy-dummy 6)" = "$output" ] [ "$status" -eq 1 ] } @@ -91,13 +79,12 @@ teardown() { run asdf install dummy 2.0.0 run asdf install legacy-dummy 4.0.0 run asdf latest --all - echo "output $output" - [ "$(echo -e "dummy\t2.0.0\tinstalled\nlegacy-dummy\t5.1.0\tmissing\n")" = "$output" ] + [ $'dummy\t2.0.0\tinstalled\nlegacy-dummy\t5.1.0\tmissing' = "$output" ] [ "$status" -eq 0 ] } @test "[latest_command - all plugins] not installed plugin should return missing" { run asdf latest --all - [ "$(echo -e "dummy\t2.0.0\tmissing\nlegacy-dummy\t5.1.0\tmissing\n")" = "$output" ] + [ $'dummy\t2.0.0\tmissing\nlegacy-dummy\t5.1.0\tmissing' = "$output" ] [ "$status" -eq 0 ] } diff --git a/test/list_command.bats b/test/list_command.bats index 102304659..f21f2cd1b 100644 --- a/test/list_command.bats +++ b/test/list_command.bats @@ -19,8 +19,8 @@ teardown() { run asdf install dummy 1.0.0 run asdf install dummy 1.1.0 run asdf list - [[ "$output" == *"$(echo -e "dummy\n 1.0.0\n 1.1.0")"* ]] - [[ "$output" == *"$(echo -e "dummy-broken\n No versions installed")"* ]] + [[ "$output" == *$'dummy\n 1.0.0\n 1.1.0'* ]] + [[ "$output" == *$'dummy-broken\n No versions installed'* ]] [ "$status" -eq 0 ] } @@ -31,8 +31,8 @@ teardown() { run asdf install dummy 1.1.0 run asdf list - [[ "$output" == *"$(echo -e "dummy\n 1.0.0\n *1.1.0")"* ]] - [[ "$output" == *"$(echo -e "dummy-broken\n No versions installed")"* ]] + [[ "$output" == *$'dummy\n 1.0.0\n *1.1.0'* ]] + [[ "$output" == *$'dummy-broken\n No versions installed'* ]] [ "$status" -eq 0 ] } @@ -43,10 +43,10 @@ teardown() { run asdf install dummy 1.0.0 run asdf install tummy 2.0.0 run asdf list - [[ "$output" == *"$(echo -e "dummy\n 1.0.0")"* ]] - [[ "$output" == *"$(echo -e "dummy-broken\n No versions installed")"* ]] - [[ "$output" == *"$(echo -e "mummy\n No versions installed")"* ]] - [[ "$output" == *"$(echo -e "tummy\n 2.0.0")"* ]] + [[ "$output" == *$'dummy\n 1.0.0'* ]] + [[ "$output" == *$'dummy-broken\n No versions installed'* ]] + [[ "$output" == *$'mummy\n No versions installed'* ]] + [[ "$output" == *$'tummy\n 2.0.0'* ]] [ "$status" -eq 0 ] } @@ -54,7 +54,7 @@ teardown() { run asdf install dummy 1.0.0 run asdf install dummy 1.1.0 run asdf list dummy - [ "$(echo -e " 1.0.0\n 1.1.0")" = "$output" ] + [ $' 1.0.0\n 1.1.0' = "$output" ] [ "$status" -eq 0 ] } @@ -63,7 +63,7 @@ teardown() { run asdf install dummy 1.1 run asdf install dummy 2.0 run asdf list dummy 1 - [ "$(echo -e " 1.0\n 1.1")" = "$output" ] + [ $' 1.0\n 1.1' = "$output" ] [ "$status" -eq 0 ] } @@ -77,13 +77,13 @@ teardown() { @test "list_all_command lists available versions" { run asdf list-all dummy - [ "$(echo -e "1.0.0\n1.1.0\n2.0.0")" = "$output" ] + [ $'1.0.0\n1.1.0\n2.0.0' = "$output" ] [ "$status" -eq 0 ] } @test "list_all_command with version filters available versions" { run asdf list-all dummy 1 - [ "$(echo -e "1.0.0\n1.1.0")" = "$output" ] + [ $'1.0.0\n1.1.0' = "$output" ] [ "$status" -eq 0 ] } diff --git a/test/plugin_test_command.bats b/test/plugin_test_command.bats index 1b486649d..c725450c9 100644 --- a/test/plugin_test_command.bats +++ b/test/plugin_test_command.bats @@ -25,14 +25,10 @@ teardown() { @test "plugin_test_command works with no options provided" { run asdf plugin-test dummy "${BASE_DIR}/repo-dummy" - echo "status = ${status}" - echo "output = ${output}" [ "$status" -eq 0 ] } @test "plugin_test_command works with all options provided" { run asdf plugin-test dummy "${BASE_DIR}/repo-dummy" --asdf-tool-version 1.0.0 --asdf-plugin-gitref master - echo "status = ${status}" - echo "output = ${output}" [ "$status" -eq 0 ] } diff --git a/test/shim_exec.bats b/test/shim_exec.bats index 838b1a9ef..5c6d0673e 100644 --- a/test/shim_exec.bats +++ b/test/shim_exec.bats @@ -333,7 +333,6 @@ teardown() { chmod +x "$PROJECT_DIR/sys/dummy" run env "PATH=$PATH:$PROJECT_DIR/sys" "$ASDF_DIR/shims/dummy" - echo "$status $output" [ "$output" = "$ASDF_DIR/shims/dummy" ] } diff --git a/test/uninstall_command.bats b/test/uninstall_command.bats index a55134682..c5bef1b46 100644 --- a/test/uninstall_command.bats +++ b/test/uninstall_command.bats @@ -32,7 +32,7 @@ teardown() { run asdf install dummy 1.1.0 [ "$status" -eq 0 ] mkdir -p "$ASDF_DIR/plugins/dummy/bin" - echo "echo custom uninstall" >"$ASDF_DIR/plugins/dummy/bin/uninstall" + printf '%s\n' "echo custom uninstall" >"$ASDF_DIR/plugins/dummy/bin/uninstall" chmod 755 "$ASDF_DIR/plugins/dummy/bin/uninstall" run asdf uninstall dummy 1.1.0 [ "$output" = "custom uninstall" ] diff --git a/test/update_command.bats b/test/update_command.bats index c8333673f..9e377f16c 100644 --- a/test/update_command.bats +++ b/test/update_command.bats @@ -61,14 +61,14 @@ teardown() { touch "$ASDF_DIR/asdf_updates_disabled" run asdf update [ "$status" -eq 42 ] - [ "$(echo -e "Update command disabled. Please use the package manager that you used to install asdf to upgrade asdf.")" = "$output" ] + [ $'Update command disabled. Please use the package manager that you used to install asdf to upgrade asdf.' = "$output" ] } @test "asdf update is a noop for non-git repos" { rm -rf "$ASDF_DIR/.git/" run asdf update [ "$status" -eq 42 ] - [ "$(echo -e "Update command disabled. Please use the package manager that you used to install asdf to upgrade asdf.")" = "$output" ] + [ $'Update command disabled. Please use the package manager that you used to install asdf to upgrade asdf.' = "$output" ] } @test "asdf update fails with exit code 1" { diff --git a/test/utils.bats b/test/utils.bats index 288a2e228..5e5c94f72 100644 --- a/test/utils.bats +++ b/test/utils.bats @@ -43,7 +43,6 @@ teardown() { run get_download_path foo version "1.0.0" [ "$status" -eq 0 ] download_path=${output#"$HOME/"} - echo "$download_path" [ "$download_path" = ".asdf/downloads/foo/1.0.0" ] } From 5367f1f09079070c7b47551dc453c686991564a0 Mon Sep 17 00:00:00 2001 From: James Hegedus <jthegedus@hey.com> Date: Wed, 12 Apr 2023 13:01:32 +1000 Subject: [PATCH 26/42] fix: rename internal plugin repository functions (#1537) --- lib/commands/command-plugin-list-all.bash | 2 +- lib/functions/plugins.bash | 2 +- lib/utils.bash | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/commands/command-plugin-list-all.bash b/lib/commands/command-plugin-list-all.bash index 33333e59a..232b69cd6 100644 --- a/lib/commands/command-plugin-list-all.bash +++ b/lib/commands/command-plugin-list-all.bash @@ -1,7 +1,7 @@ # -*- sh -*- plugin_list_all_command() { - initialize_or_update_repository + initialize_or_update_plugin_repository local plugins_index_path plugins_index_path="$(asdf_data_dir)/repository/plugins" diff --git a/lib/functions/plugins.bash b/lib/functions/plugins.bash index 3e2d5257f..247a22dfc 100644 --- a/lib/functions/plugins.bash +++ b/lib/functions/plugins.bash @@ -63,7 +63,7 @@ plugin_add_command() { if [ -n "$2" ]; then local source_url=$2 else - initialize_or_update_repository + initialize_or_update_plugin_repository local source_url source_url=$(get_plugin_source_url "$plugin_name") fi diff --git a/lib/utils.bash b/lib/utils.bash index d926cd6ae..dfa108bed 100644 --- a/lib/utils.bash +++ b/lib/utils.bash @@ -50,7 +50,7 @@ asdf_dir() { fi } -asdf_repository_url() { +asdf_plugin_repository_url() { printf "https://github.com/asdf-vm/asdf-plugins.git\n" } @@ -418,7 +418,7 @@ repository_needs_update() { [ "$sync_required" ] } -initialize_or_update_repository() { +initialize_or_update_plugin_repository() { local repository_url local repository_path @@ -428,7 +428,7 @@ initialize_or_update_repository() { exit 1 fi - repository_url=$(asdf_repository_url) + repository_url=$(asdf_plugin_repository_url) repository_path=$(asdf_data_dir)/repository if [ ! -d "$repository_path" ]; then @@ -436,7 +436,8 @@ initialize_or_update_repository() { git clone "$repository_url" "$repository_path" elif repository_needs_update; then printf "updating plugin repository..." - (cd "$repository_path" && git fetch && git reset --hard origin/master) + git -C "$repository_path" fetch + git -C "$repository_path" reset --hard origin/master fi mkdir -p "$(asdf_data_dir)/tmp" From 2cf2f58c3efa084502fd7710243ba6e9aff55b7b Mon Sep 17 00:00:00 2001 From: James Hegedus <jthegedus@hey.com> Date: Wed, 12 Apr 2023 13:27:24 +1000 Subject: [PATCH 27/42] chore: rm format script config for removed files (#1538) --- scripts/format.bash | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts/format.bash b/scripts/format.bash index e9b261a18..f8d4385b5 100755 --- a/scripts/format.bash +++ b/scripts/format.bash @@ -2,10 +2,6 @@ set -euo pipefail -# check .sh files -shfmt --language-dialect posix --indent 2 --write \ - lib/*.sh - # check .bash files shfmt --language-dialect bash --indent 2 --write \ completions/*.bash \ From 2dd65e0e715c4c5a6773728e836b6af04da28e08 Mon Sep 17 00:00:00 2001 From: Trevor Brown <Stratus3D@users.noreply.github.com> Date: Thu, 13 Apr 2023 10:06:25 -0400 Subject: [PATCH 28/42] chore: only ban readlink -f (#1539) --- test/banned_commands.bats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/banned_commands.bats b/test/banned_commands.bats index b947e1895..84f8bf2a9 100644 --- a/test/banned_commands.bats +++ b/test/banned_commands.bats @@ -16,8 +16,6 @@ banned_commands=( eval # realpath not available by default on OSX. realpath - # readlink on OSX behaves differently from readlink on other Unix systems - readlink # source isn't POSIX compliant. . behaves the same and is POSIX compliant # Except in fish, where . is deprecated, and will be removed in the future. source @@ -32,6 +30,8 @@ banned_commands_regex=( "grep.* -P" # Ban grep long commands as they do not work on alpine "grep[^|]+--\w{2,}" + # readlink -f on OSX behaves differently from readlink -f on other Unix systems + 'readlink.+-.*f.+["$]' # sort --sort-version isn't supported everywhere "sort.*-V" "sort.*--sort-versions" From 198ced50327b20b136cb6ec165610d37334a2962 Mon Sep 17 00:00:00 2001 From: Edwin Kofler <edwin@kofler.dev> Date: Sun, 16 Apr 2023 19:15:46 -0700 Subject: [PATCH 29/42] fix: remove leading asterick in Fish completion (#1543) --- completions/asdf.fish | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/completions/asdf.fish b/completions/asdf.fish index 50b479d6a..d871d073a 100644 --- a/completions/asdf.fish +++ b/completions/asdf.fish @@ -31,7 +31,7 @@ function __fish_asdf_arg_at -a number end function __fish_asdf_list_versions -a plugin - asdf list $plugin 2>/dev/null | sed -e 's/^[[:space:]]*//' + asdf list $plugin 2>/dev/null | string trim | string trim --left --chars '*' end function __fish_asdf_list_all -a plugin From b36ec7338654abc3773314147540dfa8297b48b8 Mon Sep 17 00:00:00 2001 From: Edwin Kofler <edwin@kofler.dev> Date: Sun, 16 Apr 2023 21:47:09 -0700 Subject: [PATCH 30/42] fix: rename internal function `asdf_tool_versions_filename` (#1544) --- bin/asdf | 2 +- lib/functions/versions.bash | 2 +- lib/utils.bash | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/asdf b/bin/asdf index 16f07799a..f2614259e 100755 --- a/bin/asdf +++ b/bin/asdf @@ -69,7 +69,7 @@ asdf_cmd() { fi # Internal Variables - ASDF_DEFAULT_TOOL_VERSIONS_FILENAME=$(asdf_default_tool_versions_filename) + ASDF_DEFAULT_TOOL_VERSIONS_FILENAME=$(asdf_tool_versions_filename) export ASDF_DEFAULT_TOOL_VERSIONS_FILENAME ASDF_CONFIG_FILE=$(asdf_config_file) diff --git a/lib/functions/versions.bash b/lib/functions/versions.bash index 76093733d..e3e873ab7 100644 --- a/lib/functions/versions.bash +++ b/lib/functions/versions.bash @@ -17,7 +17,7 @@ version_command() { local file_name local file - file_name="$(asdf_default_tool_versions_filename)" + file_name="$(asdf_tool_versions_filename)" if [ "$cmd" = "global" ]; then file="$HOME/$file_name" diff --git a/lib/utils.bash b/lib/utils.bash index dfa108bed..c52470b3d 100644 --- a/lib/utils.bash +++ b/lib/utils.bash @@ -16,7 +16,7 @@ asdf_version() { fi } -asdf_default_tool_versions_filename() { +asdf_tool_versions_filename() { printf '%s\n' "${ASDF_DEFAULT_TOOL_VERSIONS_FILENAME:-.tool-versions}" } @@ -163,7 +163,7 @@ get_version_in_dir() { local asdf_version - file_name=$(asdf_default_tool_versions_filename) + file_name=$(asdf_tool_versions_filename) asdf_version=$(parse_asdf_version_file "$search_path/$file_name" "$plugin_name") if [ -n "$asdf_version" ]; then @@ -456,7 +456,7 @@ get_plugin_source_url() { } find_tool_versions() { - find_file_upwards "$(asdf_default_tool_versions_filename)" + find_file_upwards "$(asdf_tool_versions_filename)" } find_file_upwards() { From f273612155188f62cf8daf584d5581cd4214daf4 Mon Sep 17 00:00:00 2001 From: Edwin Kofler <edwin@kofler.dev> Date: Sun, 16 Apr 2023 21:51:06 -0700 Subject: [PATCH 31/42] fix: improve readability of the non-set `nullglob` guard (#1545) --- lib/commands/command-plugin-remove.bash | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/commands/command-plugin-remove.bash b/lib/commands/command-plugin-remove.bash index 6441c665e..7b959bdf7 100644 --- a/lib/commands/command-plugin-remove.bash +++ b/lib/commands/command-plugin-remove.bash @@ -21,16 +21,13 @@ plugin_remove_command() { rm -rf "$(asdf_data_dir)/installs/${plugin_name}" rm -rf "$(asdf_data_dir)/downloads/${plugin_name}" - local is_nullglob_disabled= - shopt -q nullglob || is_nullglob_disabled=yes - shopt -s nullglob for f in "$(asdf_data_dir)"/shims/*; do - if grep -q "asdf-plugin: ${plugin_name}" "$f"; then - rm -f "$f" + if [ -f "$f" ]; then # nullglob may not be set + if grep -q "asdf-plugin: ${plugin_name}" "$f"; then + rm -f "$f" + fi fi done - [ "$is_nullglob_disabled" = 'yes' ] && shopt -u nullglob - unset -v is_nullglob_disabled asdf_run_hook "post_asdf_plugin_remove" "$plugin_name" asdf_run_hook "post_asdf_plugin_remove_${plugin_name}" From a1e858d2542691adabf9b066add86f16e759a90c Mon Sep 17 00:00:00 2001 From: Veniamin Krol <153412+vkrol@users.noreply.github.com> Date: Tue, 18 Apr 2023 16:15:15 +0200 Subject: [PATCH 32/42] docs: fix uninstall instructions for Fish Shell (#1547) --- docs/manage/core.md | 4 ++-- docs/pt-br/manage/core.md | 4 ++-- docs/zh-hans/manage/core.md | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/manage/core.md b/docs/manage/core.md index 65e61e920..970a62d90 100644 --- a/docs/manage/core.md +++ b/docs/manage/core.md @@ -221,7 +221,7 @@ rm -rf ~/.config/fish/completions/asdf.fish 2. Remove the `$HOME/.asdf` dir: ```shell:no-line-numbers -rm -rf "${ASDF_DATA_DIR:-$HOME/.asdf}" +rm -rf (string join : -- $ASDF_DATA_DIR $HOME/.asdf) ``` 3. Run this command to remove all `asdf` config files: @@ -271,7 +271,7 @@ pacman -Rs asdf-vm 3. Remove the `$HOME/.asdf` dir: ```shell:no-line-numbers -rm -rf "${ASDF_DATA_DIR:-$HOME/.asdf}" +rm -rf (string join : -- $ASDF_DATA_DIR $HOME/.asdf) ``` 4. Run this command to remove all `asdf` config files: diff --git a/docs/pt-br/manage/core.md b/docs/pt-br/manage/core.md index 0e39f36e7..a456e3530 100644 --- a/docs/pt-br/manage/core.md +++ b/docs/pt-br/manage/core.md @@ -223,7 +223,7 @@ rm -rf ~/.config/fish/completions/asdf.fish 2. Remova o diretório `$HOME/.asdf`: ```shell -rm -rf "${ASDF_DATA_DIR:-$HOME/.asdf}" +rm -rf (string join : -- $ASDF_DATA_DIR $HOME/.asdf) ``` 3. Execute o comando para remover todos os arquivos de configurações do `asdf`: @@ -273,7 +273,7 @@ pacman -Rs asdf-vm 3. Remova o diretório `$HOME/.asdf`: ```shell -rm -rf "${ASDF_DATA_DIR:-$HOME/.asdf}" +rm -rf (string join : -- $ASDF_DATA_DIR $HOME/.asdf) ``` 4. Execute o comando para remover todos os arquivos de configurações do `asdf`: diff --git a/docs/zh-hans/manage/core.md b/docs/zh-hans/manage/core.md index 82c5c2601..6eb0292ac 100644 --- a/docs/zh-hans/manage/core.md +++ b/docs/zh-hans/manage/core.md @@ -221,7 +221,7 @@ rm -rf ~/.config/fish/completions/asdf.fish 2. 移除 `$HOME/.asdf` 目录: ```shell:no-line-numbers -rm -rf "${ASDF_DATA_DIR:-$HOME/.asdf}" +rm -rf (string join : -- $ASDF_DATA_DIR $HOME/.asdf) ``` 3. 执行以下命令移除 `asdf` 所有配置文件: @@ -271,7 +271,7 @@ pacman -Rs asdf-vm 3. 移除 `$HOME/.asdf` 目录: ```shell:no-line-numbers -rm -rf "${ASDF_DATA_DIR:-$HOME/.asdf}" +rm -rf (string join : -- $ASDF_DATA_DIR $HOME/.asdf) ``` 4. 执行以下命令移除 `asdf` 所有配置文件: From 684f4f058f24cc418f77825a59a22bacd16a9bee Mon Sep 17 00:00:00 2001 From: Edwin Kofler <edwin@kofler.dev> Date: Wed, 19 Apr 2023 06:45:51 -0700 Subject: [PATCH 33/42] feat: Support configurable `ASDF_CONCURRENCY` (#1532) Co-authored-by: James Hegedus <jthegedus@hey.com> --- defaults | 1 + docs/manage/configuration.md | 56 ++++++++++++++++++++++++++++++------ lib/functions/installs.bash | 26 ++++++++++++----- test/install_command.bats | 19 ++++++++++++ 4 files changed, 87 insertions(+), 15 deletions(-) diff --git a/defaults b/defaults index 382278058..abd3428b7 100644 --- a/defaults +++ b/defaults @@ -5,3 +5,4 @@ use_release_candidates = no always_keep_download = no plugin_repository_last_check_duration = 60 disable_plugin_short_name_repository = no +concurrency = auto diff --git a/docs/manage/configuration.md b/docs/manage/configuration.md index 2e714b90d..225a49c47 100644 --- a/docs/manage/configuration.md +++ b/docs/manage/configuration.md @@ -134,45 +134,85 @@ Disabling the plugin short-name repository does not remove plugins previously in ::: +### `concurrency` + +The default number of cores to use during compilation. + +| Options | Description | +| :------ | :--------------------------------------------------------------------------------------------------- | +| integer | Number of cores to use when compiling the source code | +| `auto` | Calculate the number of cores using `nproc`, then `sysctl hw.ncpu`, then `/proc/cpuinfo` or else `1` | + +Note: the environment variable `ASDF_CONCURRENCY` take precedence if set. + ## Environment Variables Setting environment variables varies depending on your system and Shell. Default locations depend upon your installation location and method (Git clone, Homebrew, AUR). Environment variables should generally be set before sourcing `asdf.sh`/`asdf.fish` etc. For Elvish set above `use asdf`. -The following examples assume: - -- an installation to `$HOME/.asdf` -- a Bash Shell +The following describe usage with a Bash Shell. ### `ASDF_CONFIG_FILE` Path to the `.asdfrc` configuration file. Can be set to any location. Must be an absolute path. -- Default: `$HOME/.asdfrc` +- If Unset: `$HOME/.asdfrc` will be used. - Usage: `export ASDF_CONFIG_FILE=/home/john_doe/.config/asdf/.asdfrc` ### `ASDF_DEFAULT_TOOL_VERSIONS_FILENAME` The filename of the file storing the tool names and versions. Can be any valid filename. Typically, you should not set this value unless you want to ignore `.tool-versions` files. -- Default: `.tool-versions` +- If Unset: `.tool-versions` will be used. - Usage: `export ASDF_DEFAULT_TOOL_VERSIONS_FILENAME=tool_versions` ### `ASDF_DIR` The location of `asdf` core scripts. Can be set to any location. Must be an absolute path. -- Default: `$HOME/.asdf` (always the parent directory of the `bin/asdf` executable) +- If Unset: the parent directory of the `bin/asdf` executable is used. - Usage: `export ASDF_DIR=/home/john_doe/.config/asdf` ### `ASDF_DATA_DIR` The location where `asdf` will install plugins, shims and tool versions. Can be set to any location. Must be an absolute path. -- Default: `$HOME/.asdf` +- If Unset: `$HOME/.asdf` if it exists, or else the value of `ASDF_DIR` - Usage: `export ASDF_DATA_DIR=/home/john_doe/.asdf` +### `ASDF_CONCURRENCY` + +Number of cores to use when compiling the source code. If set, this value takes precedence over the asdf config `concurrency` value. + +- If Unset: the asdf config `concurrency` value is used. +- Usage: `export ASDF_CONCURRENCY=32` + +## Full Configuration Example + +Following a simple asdf setup with: + +- a Bash Shell +- an installation location of `$HOME/.asdf` +- installed via Git +- NO environment variables set +- NO custom `.asdfrc` file + +would result in the following outcomes: + +| Configuration | Value | Calculated by | +| :------------------------------------ | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | +| config file location | `$HOME/.asdfrc` | `ASDF_CONFIG_FILE` is empty, so use `$HOME/.asdfrc` | +| default tool versions filename | `.tool-versions` | `ASDF_DEFAULT_TOOL_VERSIONS_FILENAME` is empty, so use `.tool-versions` | +| asdf dir | `$HOME/.asdf` | `ASDF_DIR` is empty, so use parent dir of `bin/asdf` | +| asdf data dir | `$HOME/.asdf` | `ASDF_DATA_DIR` is empty so use `$HOME/.asdf` as `$HOME` exists. | +| concurrency | `auto` | `ASDF_CONCURRENCY` is empty, so rely on `concurrency` value from the [default configuration](https://github.com/asdf-vm/asdf/blob/master/defaults) | +| legacy_version_file | `no` | No custom `.asdfrc`, so use the [default configuration](https://github.com/asdf-vm/asdf/blob/master/defaults) | +| use_release_candidates | `no` | No custom `.asdfrc`, so use the [default configuration](https://github.com/asdf-vm/asdf/blob/master/defaults) | +| always_keep_download | `no` | No custom `.asdfrc`, so use the [default configuration](https://github.com/asdf-vm/asdf/blob/master/defaults) | +| plugin_repository_last_check_duration | `60` | No custom `.asdfrc`, so use the [default configuration](https://github.com/asdf-vm/asdf/blob/master/defaults) | +| disable_plugin_short_name_repository | `no` | No custom `.asdfrc`, so use the [default configuration](https://github.com/asdf-vm/asdf/blob/master/defaults) | + ## Internal Configuration Users should not worry about this section as it describes configuration internal to `asdf` useful for Package Managers and integrators. diff --git a/lib/functions/installs.bash b/lib/functions/installs.bash index dbd403bab..76d4b5f42 100644 --- a/lib/functions/installs.bash +++ b/lib/functions/installs.bash @@ -25,15 +25,27 @@ install_command() { } get_concurrency() { - if command -v nproc &>/dev/null; then - nproc - elif command -v sysctl &>/dev/null && sysctl hw.ncpu &>/dev/null; then - sysctl -n hw.ncpu - elif [ -f /proc/cpuinfo ]; then - grep -c processor /proc/cpuinfo + local asdf_concurrency= + + if [ -n "$ASDF_CONCURRENCY" ]; then + asdf_concurrency="$ASDF_CONCURRENCY" else - printf "1\n" + asdf_concurrency=$(get_asdf_config_value 'concurrency') + fi + + if [ "$asdf_concurrency" = 'auto' ]; then + if command -v nproc &>/dev/null; then + asdf_concurrency=$(nproc) + elif command -v sysctl &>/dev/null && sysctl hw.ncpu &>/dev/null; then + asdf_concurrency=$(sysctl -n hw.ncpu) + elif [ -f /proc/cpuinfo ]; then + asdf_concurrency=$(grep -c processor /proc/cpuinfo) + else + asdf_concurrency="1" + fi fi + + printf "%s\n" "$asdf_concurrency" } install_one_local_tool() { diff --git a/test/install_command.bats b/test/install_command.bats index dd90aa629..bd945cbe9 100644 --- a/test/install_command.bats +++ b/test/install_command.bats @@ -52,6 +52,25 @@ teardown() { [ "$status" -eq 0 ] } +@test "install_command set ASDF_CONCURRENCY via env var" { + ASDF_CONCURRENCY=-1 run asdf install dummy 1.0.0 + [ "$status" -eq 0 ] + [ -f "$ASDF_DIR/installs/dummy/1.0.0/env" ] + run grep ASDF_CONCURRENCY=-1 "$ASDF_DIR/installs/dummy/1.0.0/env" + [ "$status" -eq 0 ] +} + +@test "install_command set ASDF_CONCURRENCY via asdfrc" { + cat >"$HOME/.asdfrc" <<-'EOM' + concurrency = -2 +EOM + run asdf install dummy 1.0.0 + [ "$status" -eq 0 ] + [ -f "$ASDF_DIR/installs/dummy/1.0.0/env" ] + run grep ASDF_CONCURRENCY=-2 "$ASDF_DIR/installs/dummy/1.0.0/env" + [ "$status" -eq 0 ] +} + @test "install_command without arguments should work in directory containing whitespace" { WHITESPACE_DIR="$PROJECT_DIR/whitespace\ dir" mkdir -p "$WHITESPACE_DIR" From 6b2ebf575ff98d3970b518de04238d30804a40d1 Mon Sep 17 00:00:00 2001 From: Edwin Kofler <edwin@kofler.dev> Date: Sun, 28 May 2023 06:06:23 -0700 Subject: [PATCH 34/42] fix: Typo in POSIX entrypoint (#1562) --- asdf.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/asdf.sh b/asdf.sh index a19265c0a..aadb43f3e 100644 --- a/asdf.sh +++ b/asdf.sh @@ -10,7 +10,7 @@ export ASDF_DIR="${ASDF_DIR:-}" if [ -z "$ASDF_DIR" ]; then if [ -n "$BASH_VERSION" ]; then # Use BASH_SOURCE[0] to obtain the relative path to this source'd file. Since it's - # a relative path, 'cd' to its dirname and use '$PWD" to obtain the fullpath. + # a relative path, 'cd' to its dirname and use '$PWD' to obtain the fullpath. # Use 'builtin cd' to ensure user-defined 'cd()' functions aren't called. # Use variable '_asdf_old_dir' to avoid using subshells. From 8e2aa5d726d75d86bbbd1c39f1e137a5d5666a56 Mon Sep 17 00:00:00 2001 From: James Hegedus <jthegedus@hey.com> Date: Sun, 28 May 2023 23:10:57 +1000 Subject: [PATCH 35/42] ci: custom release PR sections & titles (#1548) --- .github/workflows/release.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 68211ded9..e3fc771fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,6 +14,12 @@ jobs: with: release-type: simple bump-minor-pre-major: true # remove this to enable breaking changes causing 1.0.0 tag + changelog-types: | + [ + { "type": "feat", "section": "Features", "hidden": false }, + { "type": "fix", "section": "Patches", "hidden": false }, + { "type": "docs", "section": "Documentation", "hidden": false } + ] extra-files: | SECURITY.md docs/guide/getting-started.md From 097f7733d67aaf8d0dca1c793407babbdf6f8394 Mon Sep 17 00:00:00 2001 From: Edwin Kofler <edwin@kofler.dev> Date: Sun, 28 May 2023 06:36:53 -0700 Subject: [PATCH 36/42] fix: warn if `.tool-versions` or asdfrc contains carriage returns (#1561) --- lib/utils.bash | 13 +++++++++++++ test/utils.bats | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/lib/utils.bash b/lib/utils.bash index c52470b3d..8eae18fcb 100644 --- a/lib/utils.bash +++ b/lib/utils.bash @@ -373,6 +373,8 @@ get_asdf_config_value_from_file() { return 1 fi + util_validate_no_carriage_returns "$config_path" + local result result=$(grep -E "^\s*$key\s*=\s*" "$config_path" | head | sed -e 's/^[^=]*= *//' -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') if [ -n "$result" ]; then @@ -465,6 +467,8 @@ find_file_upwards() { search_path=$PWD while [ "$search_path" != "/" ]; do if [ -f "$search_path/$name" ]; then + util_validate_no_carriage_returns "$search_path/$name" + printf "%s\n" "${search_path}/$name" return 0 fi @@ -863,6 +867,15 @@ util_resolve_user_path() { fi } +# @description Check if a file contains carriage returns. If it does, print a warning. +util_validate_no_carriage_returns() { + local file_path="$1" + + if grep -qr $'\r' "$file_path"; then + printf '%s\n' "asdf: Warning: File $file_path contains carriage returns. Please remove them." >&2 + fi +} + get_plugin_remote_url() { local plugin_name="$1" local plugin_path diff --git a/test/utils.bats b/test/utils.bats index 5e5c94f72..39f29ebac 100644 --- a/test/utils.bats +++ b/test/utils.bats @@ -460,3 +460,16 @@ EOF [ "$status" -eq 0 ] [ "$output" = "$message" ] } + +@test "prints warning if .tool-versions file has carriage returns" { + ASDF_CONFIG_FILE="$BATS_TEST_TMPDIR/asdfrc" + cat >"$ASDF_CONFIG_FILE" <<<$'key2 = value2\r' + + [[ "$(get_asdf_config_value "key1" 2>&1)" = *"contains carriage returns"* ]] +} + +@test "prints if asdfrc config file has carriage returns" { + cat >".tool-versions" <<<$'nodejs 19.6.0\r' + + [[ "$(find_tool_versions 2>&1)" = *"contains carriage returns"* ]] +} From d8ce35357f961118c90d58d78972283fedbf1e83 Mon Sep 17 00:00:00 2001 From: James Hegedus <jthegedus@hey.com> Date: Wed, 31 May 2023 18:19:34 +1000 Subject: [PATCH 37/42] chore: unify lint/fix scripts (#1549) --- .github/workflows/lint.yml | 61 +++------- .github/workflows/tests.yml | 86 ++------------ docs/contribute/core.md | 11 +- scripts/format.bash | 24 ---- scripts/install_dependencies.bash | 77 +++++++++++++ scripts/lint.bash | 180 ++++++++++++++++++++++++++++++ scripts/shellcheck.bash | 24 ---- scripts/shfmt.bash | 24 ---- scripts/test.bash | 9 ++ 9 files changed, 297 insertions(+), 199 deletions(-) delete mode 100755 scripts/format.bash create mode 100755 scripts/install_dependencies.bash create mode 100755 scripts/lint.bash delete mode 100755 scripts/shellcheck.bash delete mode 100755 scripts/shfmt.bash diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ccc659015..6727f4c3b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -6,61 +6,26 @@ on: - master pull_request: -jobs: - shellcheck: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Install asdf dependencies - uses: asdf-vm/actions/install@v2 - - - name: Run ShellCheck - run: scripts/shellcheck.bash - - shellfmt: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 +env: + PYTHON_MIN_VERSION: "3.7.13" - - name: Install Fish (for fish_indent) - run: | - sudo add-apt-repository -y ppa:fish-shell/nightly-master - sudo apt-get update - sudo apt-get -y install fish - - - name: Install asdf dependencies - uses: asdf-vm/actions/install@v2 - - - name: List file to shfmt - run: shfmt -f . - - - name: Run shfmt - run: scripts/shfmt.bash - - checkstyle-py: +jobs: + asdf: runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Install Python - uses: actions/setup-python@v4 + - uses: actions/checkout@v3 + - uses: asdf-vm/actions/install@v2 + - uses: actions/setup-python@v4 with: - python-version: "3.7.13" + python-version: ${{ env.PYTHON_MIN_VERSION }} + - run: scripts/install_dependencies.bash + - run: scripts/lint.bash --check - - name: Run checkstyle.py - run: scripts/checkstyle.py - - actionlint: + actions: runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@v3 - + - uses: actions/checkout@v3 - name: Check workflow files - uses: docker://rhysd/actionlint:1.6.23 + uses: docker://rhysd/actionlint:1.6.24 with: args: -color diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d45730b66..ec5931d5e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -6,12 +6,6 @@ on: - master pull_request: -env: - ELVISH_VERSION: v0.19.2 - FISH_VERSION: 3.6.1 - NUSHELL_VERSION: 0.78.0 - POWERSHELL_VERSION: 7.3.3 - jobs: detect-changes: runs-on: ubuntu-latest @@ -22,11 +16,9 @@ jobs: documentation: ${{ steps.filter.outputs.documentation }} cli: ${{ steps.filter.outputs.cli }} steps: - - name: Checkout code - uses: actions/checkout@v3 + - uses: actions/checkout@v3 with: fetch-depth: 0 - - uses: dorny/paths-filter@v2 id: filter with: @@ -34,7 +26,6 @@ jobs: documentation: - '.github/workflows/**' - 'docs/**' - - '.tool-versions' cli: - '.github/workflows/**' - 'bin/**' @@ -42,10 +33,9 @@ jobs: - 'scripts/**' - 'test/**' - '.tool-versions' - - 'asdf.elv' - - 'asdf.fish' - - 'asdf.nu' - - 'asdf.sh' + - 'asdf.*' + - 'defaults' + - 'help.txt' ubuntu: needs: detect-changes @@ -54,46 +44,11 @@ jobs: if: ${{ needs.detect-changes.outputs.cli == 'true' }} runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@v3 + - uses: actions/checkout@v3 with: fetch-depth: 0 - - - name: Install test dependencies - run: | - curl -fsSLo- https://packages.microsoft.com/keys/microsoft.asc | sudo tee >/dev/null /etc/apt/trusted.gpg.d/microsoft.asc - sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-bullseye-prod bullseye main" > /etc/apt/sources.list.d/microsoft.list' - sudo add-apt-repository -y ppa:fish-shell/release-3 - sudo apt-get update - sudo apt-get -y install curl parallel \ - fish="${{ env.FISH_VERSION }}-1~jammy" \ - powershell="${{ env.POWERSHELL_VERSION }}-1.deb" - - # Create $HOME/bin - mkdir -p "$HOME/bin" - - # Download elvish binary and add to path - curl https://dl.elv.sh/linux-amd64/elvish-${{ env.ELVISH_VERSION }}.tar.gz -o elvish-${{ env.ELVISH_VERSION }}.tar.gz - tar xzf elvish-${{ env.ELVISH_VERSION }}.tar.gz - rm elvish-${{ env.ELVISH_VERSION }}.tar.gz - mv elvish-${{ env.ELVISH_VERSION }} "$HOME/bin/elvish" - - # Download nushell binary and add to path - curl -L https://github.com/nushell/nushell/releases/download/${{ env.NUSHELL_VERSION }}/nu-${{ env.NUSHELL_VERSION }}-x86_64-unknown-linux-gnu.tar.gz -o nu-${{ env.NUSHELL_VERSION }}-x86_64-unknown-linux-gnu.tar.gz - tar xzf nu-${{ env.NUSHELL_VERSION }}-x86_64-unknown-linux-gnu.tar.gz - rm nu-${{ env.NUSHELL_VERSION }}-x86_64-unknown-linux-gnu.tar.gz - mv nu-${{ env.NUSHELL_VERSION }}-x86_64-unknown-linux-gnu/* "$HOME/bin" - - # Add $HOME/bin to path - echo "$HOME/bin" >>"$GITHUB_PATH" - - - name: Install bats - run: | - git clone --depth 1 --branch "v$(grep -Eo "^\\s*bats\\s*.*$" ".tool-versions" | cut -d ' ' -f2-)" https://github.com/bats-core/bats-core.git "$HOME/bats-core" - echo "$HOME/bats-core/bin" >>"$GITHUB_PATH" - - - name: Run tests - run: scripts/test.bash + - run: scripts/install_dependencies.bash + - run: scripts/test.bash env: GITHUB_API_TOKEN: ${{ github.token }} @@ -104,26 +59,11 @@ jobs: if: ${{ needs.detect-changes.outputs.cli == 'true' }} runs-on: macos-latest steps: - - name: Checkout code - uses: actions/checkout@v3 + - uses: actions/checkout@v3 with: fetch-depth: 0 - - - name: Install test dependencies - run: | - brew install coreutils parallel \ - elvish \ - fish \ - nushell \ - powershell - - - name: Install bats - run: | - git clone --depth 1 --branch "v$(grep -Eo "^\\s*bats\\s*.*$" ".tool-versions" | cut -d ' ' -f2-)" https://github.com/bats-core/bats-core.git "$HOME/bats-core" - echo "$HOME/bats-core/bin" >>"$GITHUB_PATH" - - - name: Run tests - run: scripts/test.bash + - run: scripts/install_dependencies.bash + - run: scripts/test.bash env: GITHUB_API_TOKEN: ${{ github.token }} @@ -141,13 +81,11 @@ jobs: fetch-depth: 0 # only run steps past here if changes to docs/** directory - - name: Setup Node.js - uses: actions/setup-node@v3 + - uses: actions/setup-node@v3 with: node-version: "18" - - name: Cache dependencies - uses: actions/cache@v3 + - uses: actions/cache@v3 id: npm-cache with: path: | diff --git a/docs/contribute/core.md b/docs/contribute/core.md index 76201e2d7..046f195fd 100644 --- a/docs/contribute/core.md +++ b/docs/contribute/core.md @@ -40,14 +40,15 @@ If you want to try out your changes without making change to your installed `asd It is best to format, lint and test your code locally before you commit or push to the remote. Use the following scripts/commands: ```shell:no-line-numbers -# Shellcheck -./scripts/shellcheck.bash +# Lint +./scripts/lint.bash --check -# Format -./scripts/shfmt.bash +# Fix & Format +./scripts/lint.bash --fix # Test: all tests -bats test/ +./scripts/test.bash + # Test: for specific command bats test/list_commands.bash ``` diff --git a/scripts/format.bash b/scripts/format.bash deleted file mode 100755 index f8d4385b5..000000000 --- a/scripts/format.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# check .bash files -shfmt --language-dialect bash --indent 2 --write \ - completions/*.bash \ - bin/asdf \ - bin/private/asdf-exec \ - lib/utils.bash \ - lib/commands/*.bash \ - lib/functions/*.bash \ - scripts/*.bash \ - test/test_helpers.bash \ - test/fixtures/dummy_broken_plugin/bin/* \ - test/fixtures/dummy_legacy_plugin/bin/* \ - test/fixtures/dummy_plugin/bin/* - -# check .bats files -shfmt --language-dialect bats --indent 2 --write \ - test/*.bats - -# check .fish files -fish_indent --write ./**/*.fish diff --git a/scripts/install_dependencies.bash b/scripts/install_dependencies.bash new file mode 100755 index 000000000..f8c6ecf50 --- /dev/null +++ b/scripts/install_dependencies.bash @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +set -euo pipefail +IFS=$'\n\t' + +### Used env vars set by default in GitHub Actions +# docs: https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables +# GITHUB_ACTIONS +# RUNNER_OS + +if [ -z "$GITHUB_ACTIONS" ]; then + printf "%s\n" "GITHUB_ACTIONS is not set. This script is only intended to be run in GitHub Actions. Exiting." + exit 1 +fi + +if [ -z "$RUNNER_OS" ]; then + printf "%s\n" "RUNNER_OS is not set. This script is only intended to be run in GitHub Actions. Exiting." + exit 1 +fi + +### Set environment variables for tracking versions +# Elvish +elvish_semver="v0.19.2" +# Fish +fish_semver="3.6.1" +fish_apt_semver="${fish_semver}-1~jammy" +# Nushell +nushell_semver="0.78.0" +# Powershell +powershell_semver="7.3.3" +powershell_apt_semver="${powershell_semver}-1.deb" + +### Install dependencies on Linux +if [ "$RUNNER_OS" = "Linux" ]; then + printf "%s\n" "Installing dependencies on Linux" + + curl -fsSLo- https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc >/dev/null + sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-bullseye-prod bullseye main" > /etc/apt/sources.list.d/microsoft.list' + sudo add-apt-repository -y ppa:fish-shell/release-3 + sudo apt-get update + sudo apt-get -y install curl parallel \ + fish="${fish_apt_semver}" \ + powershell="${powershell_apt_semver}" + + # Create $HOME/bin + mkdir -p "$HOME/bin" + + # Download elvish binary and add to path + curl https://dl.elv.sh/linux-amd64/elvish-${elvish_semver}.tar.gz -o elvish-${elvish_semver}.tar.gz + tar xzf elvish-${elvish_semver}.tar.gz + rm elvish-${elvish_semver}.tar.gz + mv elvish-${elvish_semver} "$HOME/bin/elvish" + + # Download nushell binary and add to path + curl -L https://github.com/nushell/nushell/releases/download/${nushell_semver}/nu-${nushell_semver}-x86_64-unknown-linux-gnu.tar.gz -o nu-${nushell_semver}-x86_64-unknown-linux-gnu.tar.gz + tar xzf nu-${nushell_semver}-x86_64-unknown-linux-gnu.tar.gz + rm nu-${nushell_semver}-x86_64-unknown-linux-gnu.tar.gz + mv nu-${nushell_semver}-x86_64-unknown-linux-gnu/* "$HOME/bin" + + # Add $HOME/bin to path (add Elvish & Nushell to path) + echo "$HOME/bin" >>"$GITHUB_PATH" +fi + +### Install dependencies on macOS +if [ "$RUNNER_OS" = "macOS" ]; then + printf "%s\n" "Installing dependencies on macOS" + brew install coreutils parallel \ + elvish \ + fish \ + nushell \ + powershell +fi + +### Install bats-core +printf "%s\n" "Installing bats-core" +git clone --depth 1 --branch "v$(grep -Eo "^\\s*bats\\s*.*$" ".tool-versions" | cut -d ' ' -f2-)" https://github.com/bats-core/bats-core.git "$HOME/bats-core" +echo "$HOME/bats-core/bin" >>"$GITHUB_PATH" diff --git a/scripts/lint.bash b/scripts/lint.bash new file mode 100755 index 000000000..392d36b69 --- /dev/null +++ b/scripts/lint.bash @@ -0,0 +1,180 @@ +#!/usr/bin/env bash + +set -euo pipefail +IFS=$'\n\t' + +usage() { + printf "%s\n" "Lint script for the asdf codebase. Must be executed from the" + printf "%s\n\n" "repository root directory." + printf "%s\n\n" "Usage: scripts/lint.bash [options]" + printf "%s\n" "Options:" + printf "%s\n" " -c, --check Error if any issues are found" + printf "%s\n" " -f, --fix Automatically fix issues if possible" + printf "%s\n" " -h, --help Display this help message" +} + +run_shfmt_stylecheck() { + local shfmt_flag="" + if [ "$1" = "fix" ]; then + shfmt_flag="--write" + else + shfmt_flag="--diff" + fi + + printf "%s\n" "[INFO] Checking .bash with shfmt" + shfmt --language-dialect bash --indent 2 "${shfmt_flag}" \ + completions/*.bash \ + bin/asdf \ + bin/private/asdf-exec \ + lib/utils.bash \ + lib/commands/*.bash \ + lib/functions/*.bash \ + scripts/*.bash \ + test/test_helpers.bash \ + test/fixtures/dummy_broken_plugin/bin/* \ + test/fixtures/dummy_legacy_plugin/bin/* \ + test/fixtures/dummy_plugin/bin/* + + printf "%s\n" "[INFO] Checking .bats with shfmt" + shfmt --language-dialect bats --indent 2 "${shfmt_flag}" \ + test/*.bats +} + +run_shellcheck_linter() { + printf "%s\n" "[INFO] Checking .sh files with Shellcheck" + shellcheck --shell sh --external-sources \ + asdf.sh + + printf "%s\n" "[INFO] Checking .bash files with Shellcheck" + shellcheck --shell bash --external-sources \ + completions/*.bash \ + bin/asdf \ + bin/private/asdf-exec \ + lib/utils.bash \ + lib/commands/*.bash \ + lib/functions/*.bash \ + scripts/*.bash \ + test/test_helpers.bash \ + test/fixtures/dummy_broken_plugin/bin/* \ + test/fixtures/dummy_legacy_plugin/bin/* \ + test/fixtures/dummy_plugin/bin/* + + printf "%s\n" "[INFO] Checking .bats files with Shellcheck" + shellcheck --shell bats --external-source \ + test/*.bats +} + +run_custom_python_stylecheck() { + local github_actions=${GITHUB_ACTIONS:-} + local flag= + + if [ "$1" = "fix" ]; then + flag="--fix" + fi + + if [ -n "$github_actions" ] && ! command -v python3 &>/dev/null; then + # fail if CI and no python3 + printf "%s\n" "[ERROR] Detected execution in GitHub Actions but python3 was not found. This is required during CI linting." + exit 1 + fi + + if ! command -v python3 &>/dev/null; then + # skip if local and no python3 + printf "%s\n" "[WARNING] python3 not found. Skipping Custom Python Script." + else + printf "%s\n" "[INFO] Checking files with Custom Python Script." + "${0%/*}/checkstyle.py" "${flag}" + fi + +} + +# TODO: there is no elvish linter/formatter yet +# see https://github.com/elves/elvish/issues/1651 +#run_elvish_linter() { +# printf "%s\n" "[WARNING] elvish linter/formatter not found, skipping for now." +#} + +run_fish_linter() { + local github_actions=${GITHUB_ACTIONS:-} + local flag= + + if [ "$1" = "fix" ]; then + flag="--write" + else + flag="--check" + fi + + if [ -n "$github_actions" ] && ! command -v fish_indent &>/dev/null; then + # fail if CI and no fish_ident + printf "%s\n" "[ERROR] Detected execution in GitHub Actions but fish_indent was not found. This is required during CI linting." + exit 1 + fi + + if ! command -v fish_indent &>/dev/null; then + # skip if local and no fish_ident + printf "%s\n" "[WARNING] fish_indent not found. Skipping .fish files." + else + printf "%s\n" "[INFO] Checking .fish files with fish_indent" + fish_indent "${flag}" ./**/*.fish + fi +} + +# TODO: there is no nushell linter/formatter yet +#run_nushell_linter() { +# printf "%s\n" "[WARNING] nushell linter/formatter not found, skipping for now." +#} + +# TODO: select powershell linter/formatter & setup installation in CI +#run_powershell_linter() { +# printf "%s\n" "[WARNING] powershell linter/formatter not found, skipping for now." +#} + +repo_root=$(git rev-parse --show-toplevel) +if [ "$repo_root" != "$PWD" ]; then + printf "%s\n" "[ERROR] This scripts requires execution from the repository root directory." + printf "\t%s\t%s\n" "Repo root dir:" "$repo_root" + printf "\t%s\t%s\n\n" "Current dir:" "$PWD" + printf "%s\n" "See usage details with -h or --help." + exit 1 +fi + +if [ $# -eq 0 ]; then + printf "%s\n" "[ERROR] At least one option required." + printf "=%.0s" {1..60} + printf "\n" + usage + exit 1 +fi + +mode= +case "$1" in +-h | --help) + usage + exit 0 + ;; +-c | --check) + mode="check" + ;; +-f | --fix) + mode="fix" + ;; +*) + printf "%s\n" "[ERROR] Invalid flag: $1" + printf "=%.0s" {1..60} + printf "\n" + usage + exit 1 + ;; +esac + +printf "%s\"%s\"\n" "[INFO] Executing with mode: " "$mode" + +run_shfmt_stylecheck "$mode" +run_custom_python_stylecheck "$mode" +run_shellcheck_linter "$mode" +run_fish_linter "$mode" +#run_elvish_linter "$mode" +#run_nushell_linter "$mode" +#run_powershell_linter "$mode" + +printf "%s\n" "[INFO] Success!" diff --git a/scripts/shellcheck.bash b/scripts/shellcheck.bash deleted file mode 100755 index 7b56f745d..000000000 --- a/scripts/shellcheck.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# check .sh files -shellcheck --shell sh --external-sources \ - asdf.sh - -# check .bash files -shellcheck --shell bash --external-sources \ - completions/*.bash \ - bin/asdf \ - bin/private/asdf-exec \ - lib/utils.bash \ - lib/commands/*.bash \ - lib/functions/*.bash \ - scripts/*.bash \ - test/test_helpers.bash \ - test/fixtures/dummy_broken_plugin/bin/* \ - test/fixtures/dummy_legacy_plugin/bin/* \ - test/fixtures/dummy_plugin/bin/* - -shellcheck --shell bats --external-source \ - test/*.bats diff --git a/scripts/shfmt.bash b/scripts/shfmt.bash deleted file mode 100755 index d42ae2057..000000000 --- a/scripts/shfmt.bash +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# check .bash files -shfmt --language-dialect bash --indent 2 --diff \ - completions/*.bash \ - bin/asdf \ - bin/private/asdf-exec \ - lib/utils.bash \ - lib/commands/*.bash \ - lib/functions/*.bash \ - scripts/*.bash \ - test/test_helpers.bash \ - test/fixtures/dummy_broken_plugin/bin/* \ - test/fixtures/dummy_legacy_plugin/bin/* \ - test/fixtures/dummy_plugin/bin/* - -# check .bats files -shfmt --language-dialect bats --indent 2 --diff \ - test/*.bats - -# check .fish files -fish_indent --check ./**/*.fish diff --git a/scripts/test.bash b/scripts/test.bash index 5e361fdd9..13148590f 100755 --- a/scripts/test.bash +++ b/scripts/test.bash @@ -1,6 +1,15 @@ #!/usr/bin/env bash set -euo pipefail +IFS=$'\n\t' + +repo_root=$(git rev-parse --show-toplevel) +if [ "$repo_root" != "$PWD" ]; then + printf "%s\n" "[ERROR] This scripts requires execution from the repository root directory." + printf "\t%s\t%s\n" "Repo root dir:" "$repo_root" + printf "\t%s\t%s\n\n" "Current dir:" "$PWD" + exit 1 +fi test_directory="test" bats_options=(--timing --print-output-on-failure) From 99623d7eac0fe17e330a950c71b7ba378f656b2c Mon Sep 17 00:00:00 2001 From: Yuri Pieters <MageJohn@users.noreply.github.com> Date: Wed, 31 May 2023 09:29:50 +0100 Subject: [PATCH 38/42] fix: support `asdf shim-versions` completions in fish & bash (#1554) authored-by: Yuri Pieters <yuri.pieters@anaplan.com> --- completions/asdf.bash | 15 ++++++++++++--- completions/asdf.fish | 6 +++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/completions/asdf.bash b/completions/asdf.bash index b66c5e030..f828e9db5 100644 --- a/completions/asdf.bash +++ b/completions/asdf.bash @@ -1,3 +1,12 @@ +_asdf_list_shims() ( + # this function runs in a subshell so shopt is scoped + shopt -s nullglob # globs that don't match should disappear + shopt -u failglob # globs that don't match shouldn't fail + for shim in "${ASDF_DATA_DIR:-$HOME/.asdf}"/shims/*; do + basename "$shim" + done +) + _asdf() { local cur cur=${COMP_WORDS[COMP_CWORD]} @@ -71,13 +80,13 @@ _asdf() { # shellcheck disable=SC2207 COMPREPLY=($(compgen -W "--all" -- "$cur")) ;; - which) + which | shim-versions) # shellcheck disable=SC2207 - COMPREPLY=($(compgen -c -- "$cur")) + COMPREPLY=($(compgen -W "$(_asdf_list_shims)" -- "$cur")) ;; plugin-list | plugin-list-all | info) ;; *) - local cmds='current global help install latest list list-all local plugin-add plugin-list plugin-list-all plugin-remove plugin-update reshim shell uninstall update where which info' + local cmds='current global help install latest list list-all local plugin-add plugin-list plugin-list-all plugin-remove plugin-update reshim shim-versions shell uninstall update where which info' # shellcheck disable=SC2207 COMPREPLY=($(compgen -W "$cmds" -- "$cur")) ;; diff --git a/completions/asdf.fish b/completions/asdf.fish index d871d073a..a309bf49d 100644 --- a/completions/asdf.fish +++ b/completions/asdf.fish @@ -47,7 +47,7 @@ function __fish_asdf_plugin_list_all end function __fish_asdf_list_shims - ls $asdf_data_dir/shims + path basename $asdf_data_dir/shims/* end # update @@ -116,6 +116,10 @@ complete -f -c asdf -n __fish_asdf_needs_command -a reshim -d "Recreate shims fo complete -f -c asdf -n '__fish_asdf_using_command reshim; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' complete -f -c asdf -n '__fish_asdf_using_command reshim; and __fish_asdf_arg_number 3' -a '(__fish_asdf_list_versions (__fish_asdf_arg_at 3))' +# shim-versions completion +complete -f -c asdf -n __fish_asdf_needs_command -a shim-versions -d "List the plugins and versions that provide a command" +complete -f -c asdf -n '__fish_asdf_using_command shim-versions; and __fish_asdf_arg_number 2' -a '(__fish_asdf_list_shims)' + # local completion complete -f -c asdf -n __fish_asdf_needs_command -a local -d "Set local version for a plugin" complete -f -c asdf -n '__fish_asdf_using_command local; and __fish_asdf_arg_number 2' -a '(__fish_asdf_plugin_list)' From d6185a21207e0ac45e69499883dad5e2b585c1b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Rozlach?= <2124609+vespian@users.noreply.github.com> Date: Wed, 31 May 2023 10:39:55 +0200 Subject: [PATCH 39/42] fix: create install directory with `mkdir -p` (#1563) Co-authored-by: James Hegedus <jthegedus@hey.com> --- lib/functions/installs.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/functions/installs.bash b/lib/functions/installs.bash index 76d4b5f42..721ae50c4 100644 --- a/lib/functions/installs.bash +++ b/lib/functions/installs.bash @@ -207,7 +207,7 @@ install_tool_version() { export ASDF_INSTALL_PATH=$install_path # shellcheck disable=SC2030 export ASDF_DOWNLOAD_PATH=$download_path - mkdir "$download_path" + mkdir -p "$download_path" asdf_run_hook "pre_asdf_download_${plugin_name}" "$full_version" "${plugin_path}"/bin/download ) From 297c37672a4456347b098cded9b25d594318ef40 Mon Sep 17 00:00:00 2001 From: Edwin Kofler <edwin@kofler.dev> Date: Sun, 4 Jun 2023 19:48:30 -0700 Subject: [PATCH 40/42] ci: add ShellCheck directives to find sourced files (#1571) --- bin/asdf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/asdf b/bin/asdf index f2614259e..452f24877 100755 --- a/bin/asdf +++ b/bin/asdf @@ -95,11 +95,13 @@ asdf_cmd() { exec "$ASDF_CMD_FILE" "${@:${args_offset}}" elif [ -f "$ASDF_CMD_FILE" ]; then set -- "${@:${args_offset}}" + # shellcheck source=/dev/null . "$ASDF_CMD_FILE" else local asdf_cmd_dir asdf_cmd_dir="$(asdf_dir)/lib/commands" printf "%s\n" "Unknown command: \`asdf ${*}\`" >&2 + # shellcheck source=lib/commands/command-help.bash . "$asdf_cmd_dir/command-help.bash" >&2 return 127 fi From 5b7d0fea0a10681d89dd7bf4010e0a39e6696841 Mon Sep 17 00:00:00 2001 From: Edwin Kofler <edwin@kofler.dev> Date: Thu, 8 Jun 2023 17:31:07 -0700 Subject: [PATCH 41/42] fix: Introduce `ASDF_FORCE_PREPEND` variable on POSIX entrypoint (#1560) --- asdf.sh | 54 +++++++++++++++++++++++++++++++++++ docs/guide/getting-started.md | 8 +++++- docs/manage/configuration.md | 9 ++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/asdf.sh b/asdf.sh index aadb43f3e..1f8d2b56d 100644 --- a/asdf.sh +++ b/asdf.sh @@ -59,6 +59,60 @@ fi _asdf_bin="$ASDF_DIR/bin" _asdf_shims="${ASDF_DATA_DIR:-$HOME/.asdf}/shims" +_asdf_should_prepend=no +if [ -n "${ASDF_FORCE_PREPEND+x}" ]; then + _asdf_should_prepend=$ASDF_FORCE_PREPEND +else + # If ASDF_FORCE_PREPEND is not set, then prepend by default on macOS + # to workaround `path_helper`. + if [ -n "$BASH_VERSION" ] || [ -n "$ZSH_VERSION" ]; then + # shellcheck disable=SC3028 + case $OSTYPE in + darwin*) _asdf_should_prepend=yes ;; + esac + else + if ! _asdf_output=$(uname); then + printf "%s\n" "asdf: Error: Failed to execute 'uname'" >&2 + return 1 + fi + if [ "$_asdf_output" = 'Darwin' ]; then + _asdf_should_prepend=yes + fi + unset -v _asdf_output + fi +fi + +# If prepending is enabled, remove any existing instances of asdf from PATH so +# the prepending done after is always at the frontmost part of the PATH. +if [ "$_asdf_should_prepend" = 'yes' ]; then + if [ -n "$BASH_VERSION" ] || [ -n "$ZSH_VERSION" ]; then + # shellcheck disable=SC3060 + case ":$PATH:" in + *":${_asdf_bin}:"*) PATH=${PATH//$_asdf_bin:/} ;; + esac + # shellcheck disable=SC3060 + case ":$PATH:" in + *":${_asdf_shims}:"*) PATH=${PATH//$_asdf_shims:/} ;; + esac + else + _path=${PATH}: + _new_path= + while [ -n "$_path" ]; do + _part=${_path%%:*} + _path=${_path#*:} + + if [ "$_part" = "$_asdf_bin" ] || [ "$_part" = "$_asdf_shims" ]; then + continue + fi + + _new_path="$_new_path${_new_path:+:}$_part" + done + PATH=$_new_path + unset -v _path _new_path _part + fi +fi +unset -v _asdf_should_prepend + case ":$PATH:" in *":$_asdf_bin:"*) : ;; *) PATH="$_asdf_bin:$PATH" ;; diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md index 38d679c18..f6e91b93f 100644 --- a/docs/guide/getting-started.md +++ b/docs/guide/getting-started.md @@ -51,7 +51,9 @@ We highly recommend using the official `git` method. ## 3. Install asdf -There are many different combinations of Shells, OSs & Installation methods all of which affect the configuration here. Expand the selection below that best matches your system: +There are many different combinations of Shells, OSs & Installation methods all of which affect the configuration here. Expand the selection below that best matches your system. + +**macOS users, be sure to read the warning about `path_helper` at the end of this section.** ::: details Bash & Git @@ -359,6 +361,10 @@ export ASDF_DIR="/opt/asdf-vm" `asdf` scripts need to be sourced **after** you have set your `$PATH` and **after** you have sourced your framework (oh-my-zsh etc). +::: warning +On macOS, starting a Bash or Zsh shell automatically calls a utility called `path_helper`. `path_helper` can rearrange items in `PATH` (and `MANPATH`), causing inconsistent behavior for tools that require specific ordering. To workaround this, `asdf` on macOS defaults to forcily adding its `PATH`-entries to the front (taking highest priority). This is controllable with the `ASDF_FORCE_PREPEND` variable.`. +::: + Restart your shell so that `PATH` changes take effect. Opening a new terminal tab will usually do it. ## Core Installation Complete! diff --git a/docs/manage/configuration.md b/docs/manage/configuration.md index 225a49c47..1ec7d83ed 100644 --- a/docs/manage/configuration.md +++ b/docs/manage/configuration.md @@ -188,6 +188,15 @@ Number of cores to use when compiling the source code. If set, this value takes - If Unset: the asdf config `concurrency` value is used. - Usage: `export ASDF_CONCURRENCY=32` +### `ASDF_FORCE_PREPEND` + +Whether or not to prepend the `asdf` shims and path directories to the front-most (highest-priority) part of the `PATH`. + +- If Unset: On macOS, defaults to `yes`; but on other systems, defaults to `no` +- If `yes`: Force `asdf` directories to the front of the `PATH` +- If set to any string _other_ than `yes`: Do _not_ force `asdf` directories to the front of the `PATH` +- Usage: `ASDF_FORCE_PREPEND=no . "<path-to-asdf-directory>/asdf.sh"` + ## Full Configuration Example Following a simple asdf setup with: From 816195d615427b033a7426a4fb4d7fac4cf2d791 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Jun 2023 02:37:41 +1000 Subject: [PATCH 42/42] chore(master): release 0.12.0 (#1506) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 49 +++++++++++++++++++++++++++ SECURITY.md | 2 +- docs/guide/getting-started.md | 2 +- docs/pt-br/guide/getting-started.md | 2 +- docs/zh-hans/guide/getting-started.md | 2 +- version.txt | 2 +- 6 files changed, 54 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96633bbf4..7de85e536 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,54 @@ # Changelog +## [0.12.0](https://github.com/asdf-vm/asdf/compare/v0.11.3...v0.12.0) (2023-06-09) + + +### ⚠ BREAKING CHANGES + +* Remove files containing only `asdf` wrapper functions ([#1525](https://github.com/asdf-vm/asdf/issues/1525)) +* align Fish entrypoint behaviour with other shells ([#1524](https://github.com/asdf-vm/asdf/issues/1524)) +* do not remove items from PATH in POSIX entrypoint ([#1521](https://github.com/asdf-vm/asdf/issues/1521)) +* rework POSIX entrypoint for greater shell support ([#1480](https://github.com/asdf-vm/asdf/issues/1480)) + +### Features + +* Support configurable `ASDF_CONCURRENCY` ([#1532](https://github.com/asdf-vm/asdf/issues/1532)) ([684f4f0](https://github.com/asdf-vm/asdf/commit/684f4f058f24cc418f77825a59a22bacd16a9bee)) +* Support PowerShell Core ([#1522](https://github.com/asdf-vm/asdf/issues/1522)) ([213aa22](https://github.com/asdf-vm/asdf/commit/213aa22378cf0ecf5b1924f1bfc4fee43338255a)) + + +### Documentation + +* Add Nushell installation instructions for all languages ([#1519](https://github.com/asdf-vm/asdf/issues/1519)) ([6a6c539](https://github.com/asdf-vm/asdf/commit/6a6c539f4a21fdb863fd938edd94ac3bdced349b)) +* fix `ASDF_${LANG}_VERSION` usage ([#1528](https://github.com/asdf-vm/asdf/issues/1528)) ([63f422b](https://github.com/asdf-vm/asdf/commit/63f422b4c7afcf53ef72002e39967eb9ca2da2a9)) +* fix Nushell-Homebrew setup instructions ([#1495](https://github.com/asdf-vm/asdf/issues/1495)) ([49e541a](https://github.com/asdf-vm/asdf/commit/49e541a29ff7a2f35917a4544a8b9adbc02bb1b4)) +* fix uninstall instructions for Fish Shell ([#1547](https://github.com/asdf-vm/asdf/issues/1547)) ([a1e858d](https://github.com/asdf-vm/asdf/commit/a1e858d2542691adabf9b066add86f16e759a90c)) +* Improve wording of env vars section ([#1514](https://github.com/asdf-vm/asdf/issues/1514)) ([ec3eb2d](https://github.com/asdf-vm/asdf/commit/ec3eb2d64f0531be86d10e1202a92f6b7820e294)) +* verbose plugin create command details ([#1445](https://github.com/asdf-vm/asdf/issues/1445)) ([8108ca6](https://github.com/asdf-vm/asdf/commit/8108ca6d7e5f34b9b9723f945a9c4b137f2e10ef)) + + +### Patches + +* `asdf info` show BASH_VERSION & all asdf envs ([#1513](https://github.com/asdf-vm/asdf/issues/1513)) ([a1b5eee](https://github.com/asdf-vm/asdf/commit/a1b5eeec1caf605c0e4c80748703b9e227b57aeb)) +* align Fish entrypoint behaviour with other shells ([#1524](https://github.com/asdf-vm/asdf/issues/1524)) ([8919f40](https://github.com/asdf-vm/asdf/commit/8919f4009ea233c32298911b28ceb879e2dbc675)) +* assign default values to all internal variables ([#1518](https://github.com/asdf-vm/asdf/issues/1518)) ([86477ee](https://github.com/asdf-vm/asdf/commit/86477ee8dea14ab63faf7132133304855a647fde)) +* Better handling with paths that include spaces ([#1485](https://github.com/asdf-vm/asdf/issues/1485)) ([bbcbddc](https://github.com/asdf-vm/asdf/commit/bbcbddcdd4ffa0f49c3772b66d87331420fa5727)) +* create install directory with `mkdir -p` ([#1563](https://github.com/asdf-vm/asdf/issues/1563)) ([d6185a2](https://github.com/asdf-vm/asdf/commit/d6185a21207e0ac45e69499883dad5e2b585c1b6)) +* do not remove items from PATH in POSIX entrypoint ([#1521](https://github.com/asdf-vm/asdf/issues/1521)) ([b6d0ca2](https://github.com/asdf-vm/asdf/commit/b6d0ca28d5fd2b63c7da67b127e6c2a0e01b2670)) +* enforce consistent shell redirection format ([#1533](https://github.com/asdf-vm/asdf/issues/1533)) ([1bc205e](https://github.com/asdf-vm/asdf/commit/1bc205e8aa61287c766c673acb8f0d4f9c6ee249)) +* improve readability of the non-set `nullglob` guard ([#1545](https://github.com/asdf-vm/asdf/issues/1545)) ([f273612](https://github.com/asdf-vm/asdf/commit/f273612155188f62cf8daf584d5581cd4214daf4)) +* Introduce `ASDF_FORCE_PREPEND` variable on POSIX entrypoint ([#1560](https://github.com/asdf-vm/asdf/issues/1560)) ([5b7d0fe](https://github.com/asdf-vm/asdf/commit/5b7d0fea0a10681d89dd7bf4010e0a39e6696841)) +* lint & style errors in `bin/asdf` ([#1516](https://github.com/asdf-vm/asdf/issues/1516)) ([13c0e2f](https://github.com/asdf-vm/asdf/commit/13c0e2fab0e9ad4dccf72b6f5586fb32458b8709)) +* Nushell plugin list --urls ([#1507](https://github.com/asdf-vm/asdf/issues/1507)) ([9363fb2](https://github.com/asdf-vm/asdf/commit/9363fb2f72e7fa08d3580b22d465af48a7d37031)) +* nushell plugin list all ([#1501](https://github.com/asdf-vm/asdf/issues/1501)) ([#1502](https://github.com/asdf-vm/asdf/issues/1502)) ([c5b8b3c](https://github.com/asdf-vm/asdf/commit/c5b8b3c128b48e1531f6d03d2083435f413a4738)) +* Remove files containing only `asdf` wrapper functions ([#1525](https://github.com/asdf-vm/asdf/issues/1525)) ([00fee78](https://github.com/asdf-vm/asdf/commit/00fee78423de0e399f5705bb483e599e39b707c9)) +* remove leading asterick in Fish completion ([#1543](https://github.com/asdf-vm/asdf/issues/1543)) ([198ced5](https://github.com/asdf-vm/asdf/commit/198ced50327b20b136cb6ec165610d37334a2962)) +* rename internal function `asdf_tool_versions_filename` ([#1544](https://github.com/asdf-vm/asdf/issues/1544)) ([b36ec73](https://github.com/asdf-vm/asdf/commit/b36ec7338654abc3773314147540dfa8297b48b8)) +* rename internal plugin repository functions ([#1537](https://github.com/asdf-vm/asdf/issues/1537)) ([5367f1f](https://github.com/asdf-vm/asdf/commit/5367f1f09079070c7b47551dc453c686991564a0)) +* rework POSIX entrypoint for greater shell support ([#1480](https://github.com/asdf-vm/asdf/issues/1480)) ([3379af8](https://github.com/asdf-vm/asdf/commit/3379af845ed2e281703bc0e9e4f388a7845edc2a)) +* support `asdf shim-versions` completions in fish & bash ([#1554](https://github.com/asdf-vm/asdf/issues/1554)) ([99623d7](https://github.com/asdf-vm/asdf/commit/99623d7eac0fe17e330a950c71b7ba378f656b2c)) +* Typo in POSIX entrypoint ([#1562](https://github.com/asdf-vm/asdf/issues/1562)) ([6b2ebf5](https://github.com/asdf-vm/asdf/commit/6b2ebf575ff98d3970b518de04238d30804a40d1)) +* warn if `.tool-versions` or asdfrc contains carriage returns ([#1561](https://github.com/asdf-vm/asdf/issues/1561)) ([097f773](https://github.com/asdf-vm/asdf/commit/097f7733d67aaf8d0dca1c793407babbdf6f8394)) + ## [0.11.3](https://github.com/asdf-vm/asdf/compare/v0.11.2...v0.11.3) (2023-03-16) diff --git a/SECURITY.md b/SECURITY.md index d5923ebed..4f2555eef 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -9,7 +9,7 @@ not covered under this security policy.** <!-- x-release-please-start-version --> ``` -0.11.3 +0.12.0 ``` <!-- x-release-please-end --> diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md index f6e91b93f..1a75744e1 100644 --- a/docs/guide/getting-started.md +++ b/docs/guide/getting-started.md @@ -35,7 +35,7 @@ asdf primarily requires `git` & `curl`. Here is a _non-exhaustive_ list of comma <!-- x-release-please-start-version --> ```shell:no-line-numbers -git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.11.3 +git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.12.0 ``` <!-- x-release-please-end --> diff --git a/docs/pt-br/guide/getting-started.md b/docs/pt-br/guide/getting-started.md index 9c9bac8e5..26b712493 100644 --- a/docs/pt-br/guide/getting-started.md +++ b/docs/pt-br/guide/getting-started.md @@ -39,7 +39,7 @@ asdf primarily requires `git` & `curl`. Here is a _non-exhaustive_ list of comma <!-- x-release-please-start-version --> ```shell:no-line-numbers -git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.11.3 +git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.12.0 ``` <!-- x-release-please-end --> diff --git a/docs/zh-hans/guide/getting-started.md b/docs/zh-hans/guide/getting-started.md index b4b57a38c..ea3f55f09 100644 --- a/docs/zh-hans/guide/getting-started.md +++ b/docs/zh-hans/guide/getting-started.md @@ -35,7 +35,7 @@ asdf primarily requires `git` & `curl`. Here is a _non-exhaustive_ list of comma <!-- x-release-please-start-version --> ```shell:no-line-numbers -git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.11.3 +git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.12.0 ``` <!-- x-release-please-end --> diff --git a/version.txt b/version.txt index 1a96df19c..ac454c6a1 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.11.3 +0.12.0