Merge pull request #601 from asdf-vm/commands

Subcommand CLI support.
This commit is contained in:
Victor Borja 2019-11-27 12:39:31 -06:00 committed by GitHub
commit 4eede63b53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 551 additions and 503 deletions

View File

@ -4,6 +4,17 @@
Features
* Subcommand CLI support.
Users familiar with sub-command aware tools like `git` can now
use `asdf` commands in the same way. For example:
`asdf plugin list all` is equivalent to `asdf plugin-list-all`
This is also the case for plugin extension commands, where the
plugin name is an asdf main subcommand. ie. Having a `foo` plugin
you can invoke: `asdf foo bar`
* Make `asdf plugin test` use the new `asdf latest` command. (#541)
If a plugin version is not given explicitly, we use `asdf latest` to
@ -16,18 +27,8 @@ Features
* Add support for asdf extension commands.
When a plugin provides custom executables or bash-scripts under its `bin/` directory,
it's now possible to invoke them with:
```shell
asdf nodejs import-release-team-keyring
# instead of people having to know where the executable is installed:
~/.asdf/plugins/nodejs/bin/import-release-team-keyring
```
As in nodejs case, plugin authors can use this feature to provide utilities,
or people can create plugins that are just extensions to asdf itself.
Plugins can provide `bin/command*` scripts or executables that will
be callable using the asdf command line interface.
See `docs/plugins-create.md` for more info.

View File

@ -20,17 +20,5 @@ for x in $asdf_bin_dirs
set PATH $x $PATH
end
# Add function wrapper so we can export variables
function asdf
set command $argv[1]
set -e argv[1]
switch "$command"
case "shell"
# eval commands that need to export variables
source (env ASDF_SHELL=fish asdf "sh-$command" $argv | psub)
case '*'
# forward other commands to asdf script
command asdf "$command" $argv
end
end
# Load the asdf wrapper function
source $ASDF_DIR/lib/asdf.fish

21
asdf.sh
View File

@ -30,24 +30,9 @@ ASDF_USER_SHIMS="${ASDF_DATA_DIR:-$HOME/.asdf}/shims"
PATH="${ASDF_BIN}:$PATH"
PATH="${ASDF_USER_SHIMS}:$PATH"
# Add function wrapper so we can export variables
asdf() {
local command
command="$1"
if [ "$#" -gt 0 ]; then
shift
fi
case "$command" in
"shell")
# eval commands that need to export variables
eval "$(asdf "sh-$command" "$@")";;
*)
# forward other commands to asdf script
command asdf "$command" "$@";;
esac
}
# shellcheck source=lib/asdf.sh
# Load the asdf wrapper function
. "${ASDF_DIR}/lib/asdf.sh"
if [ -n "$ZSH_VERSION" ]; then
autoload -U bashcompinit

195
bin/asdf
View File

@ -3,136 +3,85 @@
# shellcheck source=lib/utils.sh
source "$(dirname "$(dirname "$0")")/lib/utils.sh"
load_cmd() {
for cmd in "$@"; do
# shellcheck disable=SC1091
source "$(dirname "$(dirname "$0")")/lib/commands/$cmd.sh"
find_cmd() {
local cmd_dir="$1"
shift
local cmd_name
local args_offset="$#"
cmd_name="command-$(echo "${@:1:${args_offset}}" | tr ' ' '-')"
while [ ! -f "$cmd_dir/$cmd_name" ] && [ "$args_offset" -gt 0 ]; do
args_offset=$((args_offset-1))
cmd_name="command-$(echo "${@:1:${args_offset}}" | tr ' ' '-')"
done
if [ -f "$cmd_dir/$cmd_name" ]; then
echo "$cmd_dir/$cmd_name" "$((args_offset+1))"
elif [ -f "$cmd_dir/command" ]; then
echo "$cmd_dir/command" 1
fi
}
show_help() {
load_cmd "help"
help_command
find_asdf_cmd() {
local asdf_cmd_dir
asdf_cmd_dir="$(asdf_dir)/lib/commands"
case "$1" in
('exec' | 'current' | 'env' | 'global' | 'install' | 'latest' | 'list' | 'local' |\
'reshim' | 'uninstall' | 'update' | 'where' | 'which' |\
'export-shell-version')
echo "$asdf_cmd_dir/command-$1" 2
;;
('' | '--help' | '-h' | 'help')
echo "$asdf_cmd_dir/command-help" 2
;;
('--version' | 'version')
echo "$asdf_cmd_dir/command-version" 2
;;
(*)
find_cmd "$asdf_cmd_dir" "$@"
;;
esac
}
cmd_args=("${@:2}")
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")/bin" "${@:2}")"
if [ -n "$ASDF_CMD_FILE" ]; then
args_offset=$((args_offset+1)) # since the first argument is the plugin name
echo "$ASDF_CMD_FILE" "$args_offset"
fi
fi
}
case "$1" in
asdf_cmd() {
local ASDF_CMD_FILE args_offset
"exec")
load_cmd "shim-exec"
shim_exec_command "${cmd_args[@]}";;
if [ "shell" == "$1" ]; then
echo "Shell integration is not enabled. Please ensure you source asdf in your shell setup." >&2
exit 1;
fi
"env")
load_cmd "shim-env"
shim_env_command "${cmd_args[@]}";;
IFS=' ' read -r ASDF_CMD_FILE args_offset <<<"$(find_asdf_cmd "$@")"
if [ -z "$ASDF_CMD_FILE" ]; then
IFS=' ' read -r ASDF_CMD_FILE args_offset <<<"$(find_plugin_cmd "$@")"
fi
"where")
load_cmd "where"
where_command "${cmd_args[@]}";;
if [ -x "$ASDF_CMD_FILE" ]; then
exec "$ASDF_CMD_FILE" "${@:${args_offset}}"
elif [ -f "$ASDF_CMD_FILE" ]; then
set -- "${@:${args_offset}}"
source "$ASDF_CMD_FILE"
else
local asdf_cmd_dir
asdf_cmd_dir="$(asdf_dir)/lib/commands"
echo "Unknown command: \`asdf ${*}\`" >&2
source "$asdf_cmd_dir/command-help" >&2
return 127
fi
}
"which")
load_cmd "which"
which_command "${cmd_args[@]}";;
"update")
load_cmd "update"
update_command "${cmd_args[@]}";;
"install")
load_cmd "install" "reshim"
install_command "${cmd_args[@]}";;
"uninstall")
load_cmd "uninstall" "reshim"
uninstall_command "${cmd_args[@]}";;
"current")
load_cmd "current" "plugin-list"
current_command "${cmd_args[@]}";;
"sh-shell")
load_cmd "version_commands"
shell_command "${cmd_args[@]}";;
"shell")
echo "Shell integration is not enabled. Please ensure you source asdf in your shell setup."
exit 1;;
"local")
load_cmd "version_commands"
local_command "${cmd_args[@]}";;
"global")
load_cmd "version_commands"
global_command "${cmd_args[@]}";;
"latest")
load_cmd "latest"
latest_command "${cmd_args[@]}";;
"list")
load_cmd "list"
list_command "${cmd_args[@]}";;
"list-all")
load_cmd "list-all"
list_all_command "${cmd_args[@]}";;
"reshim")
load_cmd "reshim"
reshim_command "${cmd_args[@]}";;
"plugin-add")
load_cmd "plugin-add"
plugin_add_command "${cmd_args[@]}";;
"plugin-list")
load_cmd "plugin-list"
plugin_list_command "${cmd_args[@]}";;
"plugin-list-all")
load_cmd "plugin-list-all"
plugin_list_all_command "${cmd_args[@]}";;
"plugin-update")
load_cmd "plugin-update"
plugin_update_command "${cmd_args[@]}";;
"plugin-remove")
load_cmd "plugin-remove"
plugin_remove_command "${cmd_args[@]}";;
# Undocumented commands for development
"plugin-push")
load_cmd "plugin-push"
plugin_push_command "${cmd_args[@]}";;
"plugin-test")
load_cmd "plugin-test"
plugin_test_command "${cmd_args[@]}";;
"shim-versions")
load_cmd "shim_versions"
shim_versions_command "${cmd_args[@]}";;
"--version")
asdf_version "${cmd_args[@]}";;
"--help")
show_help;;
"help")
show_help;;
"")
show_help;;
*)
load_cmd "plugin-extension-command"
plugin_extension_command "$@" # returns only on command not found
echo "Unknown asdf command: \`${*}\`" >&2
show_help >&2
exit 1;;
esac
asdf_cmd "$@"

View File

@ -2,14 +2,14 @@
| Command | Effect |
| ------------------------------------ | ------------------------------------------------------------ |
| `asdf plugin-add <name> [<git-url>]` | Add a plugin from the plugin repo OR, add a Git repo |
| `asdf plugin add <name> [<git-url>]` | Add a plugin from the plugin repo OR, add a Git repo |
| | ...as a plugin by specifying the name and repo url |
| `asdf plugin-list` | List installed plugins |
| `asdf plugin-list --urls` | List installed plugins with repository URLs |
| `asdf plugin-list-all` | List plugins registered on asdf-plugins repository with URLs |
| `asdf plugin-remove <name>` | Remove plugin and package versions |
| `asdf plugin-update <name>` | Update plugin |
| `asdf plugin-update --all` | Update all plugins |
| `asdf plugin list` | List installed plugins |
| `asdf plugin list --urls` | List installed plugins with repository URLs |
| `asdf plugin list-all` | List plugins registered on asdf-plugins repository with URLs |
| `asdf plugin remove <name>` | Remove plugin and package versions |
| `asdf plugin update <name>` | Update plugin |
| `asdf plugin update --all` | Update all plugins |
## Manage Packages
@ -28,7 +28,7 @@
| `asdf global <name> <version>` | Set the package global version |
| `asdf latest <name> [<version>]` | Show latest stable version of a package |
| `asdf list <name>` | List installed versions of a package |
| `asdf list-all <name> [<version>]` | List all versions of a package and optionally filter the returned versions |
| `asdf list all <name> [<version>]` | List all versions of a package and optionally filter the returned versions |
## Utils

View File

@ -7,30 +7,30 @@ See [Creating Plugins](plugins-create) for the super-simple API for supporting m
## Add
```shell
asdf plugin-add <name>
# asdf plugin-add erlang
asdf plugin add <name>
# asdf plugin add erlang
```
If the plugin you want to install is not part of the plugins repository, you
can add it using its repository URL:
```shell
asdf plugin-add <name> <git-url>
# asdf plugin-add elm https://github.com/vic/asdf-elm
asdf plugin add <name> <git-url>
# asdf plugin add elm https://github.com/vic/asdf-elm
```
## List Installed
```shell
asdf plugin-list
# asdf plugin-list
asdf plugin list
# asdf plugin list
# java
# nodejs
```
```shell
asdf plugin-list --urls
# asdf plugin-list
asdf plugin list --urls
# asdf plugin list
# java https://github.com/skotchpine/asdf-java.git
# nodejs https://github.com/asdf-vm/asdf-nodejs.git
```
@ -38,19 +38,19 @@ asdf plugin-list --urls
## Update
```shell
asdf plugin-update --all
asdf plugin update --all
```
If you want to update a specific package, just say so.
```shell
asdf plugin-update <name>
# asdf plugin-update erlang
asdf plugin update <name>
# asdf plugin update erlang
```
## Remove
```bash
asdf plugin-remove <name>
# asdf plugin-remove erlang
asdf plugin remove <name>
# asdf plugin remove erlang
```

View File

@ -31,15 +31,15 @@ asdf list <name>
## List All Available Versions
```shell
asdf list-all <name>
# asdf list-all erlang
asdf list all <name>
# asdf list all erlang
```
Limit versions to those that begin with a given string.
```shell
asdf list-all <name> <version>
# asdf list-all erlang 17
asdf list all <name> <version>
# asdf list all erlang 17
```
## Show Latest Stable Version
@ -105,9 +105,9 @@ asdf uninstall <name> <version>
When asdf-vm installs a package it creates shims for every executable program in that package in a `$ASDF_DATA_DIR/shims` directory (default `~/.asdf/shims`). This directory being on the `$PATH` (by means of `asdf.sh` or `asdf.fish`) is how the installed programs are made available in the environment.
The shims themselves are really simple wrappers that `exec` a helper program `asdf-exec` passing it the name of the plugin and path to the executable in the installed package that the shim is wrapping.
The shims themselves are really simple wrappers that `exec` a helper program `asdf exec` passing it the name of the plugin and path to the executable in the installed package that the shim is wrapping.
The `asdf-exec` helper determines the version of tha package to use (as specified in `.tool-versions` file, selected by `asdf local ...` or `asdf global ...`), the final path to the executable in the package installation directory (this can be manipulated by the `exec-path` callback in the plugin) and the environment to execute in (also provided by the plugin - `exec-env` script), and finally it executes it.
The `asdf exec` helper determines the version of tha package to use (as specified in `.tool-versions` file, selected by `asdf local ...` or `asdf global ...`), the final path to the executable in the package installation directory (this can be manipulated by the `exec-path` callback in the plugin) and the environment to execute in (also provided by the plugin - `exec-env` script), and finally it executes it.
!> Note that because this system uses `exec` calls, any scripts in the package that are meant to be sourced by the shell instead of executed need to be accessed directly instead of via the shim wrapper. The two asdf-vm commands: `which` and `where` can help with this by returning the path to the installed package:

View File

@ -88,22 +88,44 @@ Note: This will only apply for users who have enabled the `legacy_version_file`
This can be used to further parse the legacy file found by asdf. If `parse-legacy-file` isn't implemented, asdf will simply cat the file to determine the version. The script will be passed the file path as its first argument.
## asdf extension commands
## Extension commands for asdf CLI.
It's possible for plugins to define new asdf commands. This way plugins can extend asdf capabilities or expose utilities related to their managed tool.
It's possible for plugins to define new asdf commands by providing `bin/command*` scripts or executables that will
be callable using the asdf command line interface by using the plugin name as a subcommand.
For example, a `foo` plugin might expose the command `asdf foo bar` by providing an executable file at `bin/bar`.
If `bin/bar` is a file but has no executable bit set, then its considered a source-able bash script, and will be sourced
with all the functions in `$ASDF_DIR/lib/utils.sh` already loaded.
The executable for `asdf foo` itself should be placed in `bin/default-command`
For example, suppose a `foo` plugin has:
A good example of this feature is the `nodejs` plugin, where people must import the release team keyring before
installing a nodejs version. People can execute the following command without having to know where exactly is the plugin located.
```bash
asdf nodejs import-release-team-keyring
```shell
foo/
bin/
command
command-bat
command-bat-man
command-help
```
Users can now execute
```shell
$ asdf foo # same as running `$ASDF_DATA_DIR/plugins/foo/bin/command`
$ asdf foo bar # same as running `$ASDF_DATA_DIR/plugins/foo/bin/command bar`
$ asdf foo help # same as running `$ASDF_DATA_DIR/plugins/foo/bin/command-help`
$ asdf foo bat man # same as running `$ASDF_DATA_DIR/plugins/foo/bin/command-bat-man`
$ asdf foo bat baz # same as running `$ASDF_DATA_DIR/plugins/foo/bin/command-bat baz`
```
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.
When `command*` files exists but have no executable bit set, they are considered to be
bash scripts and will be sourced having all the functions from `$ASDF_DIR/lib/utils.sh`
available. 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.
A good example of this feature is for plugins like `nodejs`, where people must import the release team keyring before
installing a nodejs version. Authors can provide a handy extension command for this without users
having to know where exactly is the plugin was installed.
If your plugin provides an asdf extension command, be sure to mention about it on your plugin's README.
## Custom shim templates
@ -119,13 +141,13 @@ This must be used wisely. For now AFAIK, it's only being used in the Elixir plug
`asdf` contains the `plugin-test` command to test your plugin. You can use it as follows
```sh
asdf plugin-test <plugin-name> <plugin-url> [test-command] [--asdf-tool-version version]
asdf plugin test <plugin-name> <plugin-url> [test-command] [--asdf-tool-version version]
```
The two first arguments are required. The second two arguments are optional. The third is a command can also be passed to check it runs correctly. For example to test the NodeJS plugin, we could run
```sh
asdf plugin-test nodejs https://github.com/asdf-vm/asdf-nodejs.git 'node --version'
asdf plugin test nodejs https://github.com/asdf-vm/asdf-nodejs.git 'node --version'
```
The fourth is a tool version that can be specified if you want the test to install a specific version of the tool. This can be useful if not all versions are compatible with all the operating systems you are testing on. If you do not specify a version the last version in the `list-all` output will be used.
@ -136,7 +158,7 @@ Here is 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 nodejs $TRAVIS_BUILD_DIR 'node --version'
before_script:
- git clone https://github.com/asdf-vm/asdf.git asdf
- . asdf/asdf.sh
@ -150,7 +172,7 @@ When using another CI, you will need to check what variable maps to the repo pat
You also have the option to pass a relative path to `plugin-test`.
For example, if the test script is ran in the repo directory: `asdf plugin-test nodejs . 'node --version'`.
For example, if the test script is ran in the repo directory: `asdf plugin test nodejs . 'node --version'`.
## GitHub API Rate Limiting

View File

@ -1,12 +1,12 @@
MANAGE PLUGINS
asdf plugin-add <name> [<git-url>] Add a plugin from the plugin repo OR, add a Git repo
asdf plugin add <name> [<git-url>] Add a plugin from the plugin repo OR, add a Git repo
as a plugin by specifying the name and repo url
asdf plugin-list List installed plugins
asdf plugin-list --urls List installed plugins with repository URLs
asdf plugin-list-all List plugins registered on asdf-plugins repository with URLs
asdf plugin-remove <name> Remove plugin and package versions
asdf plugin-update <name> Update plugin
asdf plugin-update --all Update all plugins
asdf plugin list List installed plugins
asdf plugin list --urls List installed plugins with repository URLs
asdf plugin list all List plugins registered on asdf-plugins repository with URLs
asdf plugin remove <name> Remove plugin and package versions
asdf plugin update <name> Update plugin
asdf plugin update --all Update all plugins
MANAGE PACKAGES
@ -22,7 +22,7 @@ MANAGE PACKAGES
asdf local <name> <version> Set the package local version
asdf global <name> <version> Set the package global version
asdf list <name> List installed versions of a package
asdf list-all <name> List all versions of a package
asdf list all <name> List all versions of a package
UTILS

15
lib/asdf.fish Normal file
View File

@ -0,0 +1,15 @@
# Add function 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
source (asdf export-shell-version fish $argv | psub)
case '*'
# forward other commands to asdf script
command asdf "$command" $argv
end
end

18
lib/asdf.sh Normal file
View File

@ -0,0 +1,18 @@
# 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
"shell")
# commands that need to export variables
command e"val" "$(asdf export-shell-version sh "$@")";;
*)
# forward other commands to asdf script
command asdf "$command" "$@";;
esac
}

View File

@ -1,3 +1,5 @@
# -*- sh -*-
plugin_current_command() {
local plugin_name=$1
@ -28,7 +30,7 @@ plugin_current_command() {
current_command() {
if [ $# -eq 0 ]; then
for plugin in $(plugin_list_command); do
for plugin in $(asdf plugin list); do
printf "%-15s%s\\n" "$plugin" "$(plugin_current_command "$plugin")" >&2
done
else
@ -55,3 +57,5 @@ check_for_deprecated_plugin() {
echo ""
fi
}
current_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
shim_env_command() {
local shim_name="$1"
local env_cmd="${2}"
@ -18,3 +20,5 @@ shim_env_command() {
with_shim_executable "$shim_name" shim_env || exit $?
}
shim_env_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
shim_exec_command() {
local shim_name
shim_name=$(basename "$1")
@ -28,3 +30,5 @@ shim_exec_command() {
with_shim_executable "$shim_name" exec_shim || exit $?
}
shim_exec_command "$@"

View File

@ -0,0 +1,38 @@
# -*- sh -*-
# Output from this command must be executable shell code
shell_command() {
local asdf_shell="$1"
shift
if [ "$#" -lt "2" ]; then
echo "Usage: asdf shell <name> {<version>|--unset}" >&2
echo 'false'
exit 1
fi
local plugin=$1
local version=$2
local upcase_name
upcase_name=$(echo "$plugin" | tr '[:lower:]-' '[:upper:]_')
local version_env_var="ASDF_${upcase_name}_VERSION"
if [ "$version" = "--unset" ]; then
echo "unset $version_env_var"
exit 0
fi
if ! (check_if_version_exists "$plugin" "$version"); then
echo 'false'
exit 1
fi
case "$asdf_shell" in
fish )
echo "set -gx $version_env_var \"$version\"";;
* )
echo "export $version_env_var=\"$version\"";;
esac
}
shell_command "$@"

View File

@ -0,0 +1,5 @@
# -*- sh -*-
# shellcheck source=lib/commands/version_commands.sh
source "$(dirname "$ASDF_CMD_FILE")/version_commands.sh"
version_command global "$@"

View File

@ -1,5 +1,9 @@
# -*- sh -*-
help_command () {
echo "version: $(asdf_version)"
echo ""
cat "$(asdf_dir)/help.txt"
}
help_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
handle_failure() {
local install_path="$1"
rm -rf "$install_path"
@ -95,9 +97,8 @@ install_tool_version() {
local install_type="version"
if [ "${version_info[0]}" = "latest" ]; then
load_cmd "latest"
local version
version=$(latest_command "$plugin_name" "${version_info[1]}")
version=$(asdf latest "$plugin_name" "${version_info[1]}")
full_version=$version
else
local version="${version_info[0]}"
@ -126,10 +127,12 @@ install_tool_version() {
local exit_code=$?
if [ $exit_code -eq 0 ]; then
reshim_command "$plugin_name" "$full_version"
asdf reshim "$plugin_name" "$full_version"
asdf_run_hook "post_asdf_install_${plugin_name}" "$full_version"
else
handle_failure "$install_path"
fi
fi
}
install_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
latest_command() {
DEFAULT_QUERY="[0-9]"
@ -7,10 +9,11 @@ latest_command() {
[[ -z $query ]] && query="$DEFAULT_QUERY"
# pattern from xxenv-latest (https://github.com/momo-lab/xxenv-latest)
load_cmd "list-all"
list_all_command "$plugin_name" "$query" \
asdf list-all "$plugin_name" "$query" \
| grep -vE "(^Available versions:|-src|-dev|-latest|-stm|[-\.]rc|-alpha|-beta|[-\.]pre|-next|(a|b|c)[0-9]+|snapshot|master)" \
| sed 's/^\s\+//' \
| sort --version-sort \
| tail -1
}
latest_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
list_command() {
local plugin_name=$1
@ -32,3 +34,5 @@ display_installed_versions() {
display_error 'No versions installed'
fi
}
list_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
list_all_command() {
local plugin_name=$1
local query=$2
@ -22,3 +24,5 @@ list_all_command() {
echo "${version}"
done
}
list_all_command "$@"

View File

@ -0,0 +1,33 @@
# -*- sh -*-
# shellcheck source=lib/commands/version_commands.sh
source "$(dirname "$ASDF_CMD_FILE")/version_commands.sh"
local_command() {
local parent=false
local positional=()
while [[ $# -gt 0 ]]
do
case $1 in
-p|--parent)
parent="true"
shift # past value
;;
*)
positional+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
set -- "${positional[@]}" # restore positional parameters
if [ $parent = true ]; then
version_command local-tree "$@"
else
version_command local "$@"
fi
}
local_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
plugin_add_command() {
if [[ $# -lt 1 || $# -gt 2 ]]; then
display_error "usage: asdf plugin-add <name> [<git-url>]"
@ -33,3 +35,5 @@ plugin_add_command() {
fi
fi
}
plugin_add_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
plugin_list_command() {
local flag=$1
@ -31,3 +33,5 @@ plugin_list_command() {
fi
}
plugin_list_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
plugin_list_all_command() {
initialize_or_update_repository
@ -21,3 +23,5 @@ plugin_list_all_command() {
printf "%s%s\\n" "error: index of plugins not found at " "$plugins_index_path"
fi
}
plugin_list_all_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
plugin_push_command() {
local plugin_name=$1
if [ "$plugin_name" = "--all" ]; then
@ -13,3 +15,5 @@ plugin_push_command() {
(cd "$plugin_path" && git push)
fi
}
plugin_push_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
plugin_remove_command() {
local plugin_name=$1
check_if_plugin_exists "$plugin_name"
@ -10,3 +12,5 @@ plugin_remove_command() {
grep -l "asdf-plugin: ${plugin_name}" "$(asdf_data_dir)"/shims/* 2>/dev/null | xargs rm -f
}
plugin_remove_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
plugin_test_command() {
local plugin_name=$1
@ -151,3 +153,5 @@ plugin_test_command() {
rm -rf "$TEST_DIR"
exit $exit_code
}
plugin_test_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
plugin_update_command() {
if [ "$#" -ne 1 ]; then
display_error "usage: asdf plugin-update {<name> | --all}"
@ -18,3 +20,5 @@ plugin_update_command() {
(cd "$plugin_path" && git pull)
fi
}
plugin_update_command "$@"

132
lib/commands/command-reshim Normal file
View File

@ -0,0 +1,132 @@
# -*- sh -*-
# shellcheck source=lib/commands/reshim.sh
source "$(dirname "$ASDF_CMD_FILE")/reshim.sh"
reshim_command() {
local plugin_name=$1
local full_version=$2
if [ -z "$plugin_name" ]; then
local plugins_path
plugins_path=$(get_plugin_path)
if ls "$plugins_path" &> /dev/null; then
for plugin_path in "$plugins_path"/* ; do
plugin_name=$(basename "$plugin_path")
reshim_command "$plugin_name"
done
fi
return 0
fi
check_if_plugin_exists "$plugin_name"
ensure_shims_dir
if [ "$full_version" != "" ]; then
# generate for the whole package version
asdf_run_hook "pre_asdf_reshim_$plugin_name" "$full_version_name"
generate_shims_for_version "$plugin_name" "$full_version"
asdf_run_hook "post_asdf_reshim_$plugin_name" "$full_version"
else
# generate for all versions of the package
local plugin_installs_path
plugin_installs_path="$(asdf_data_dir)/installs/${plugin_name}"
for install in "${plugin_installs_path}"/*/; do
local full_version_name
full_version_name=$(basename "$install" | sed 's/ref\-/ref\:/')
asdf_run_hook "pre_asdf_reshim_$plugin_name" "$full_version_name"
generate_shims_for_version "$plugin_name" "$full_version_name"
remove_obsolete_shims "$plugin_name" "$full_version_name"
asdf_run_hook "post_asdf_reshim_$plugin_name" "$full_version_name"
done
fi
}
ensure_shims_dir() {
# Create shims dir if doesn't exist
if [ ! -d "$(asdf_data_dir)/shims" ]; then
mkdir "$(asdf_data_dir)/shims"
fi
}
write_shim_script() {
local plugin_name=$1
local version=$2
local executable_path=$3
if ! is_executable "$executable_path"; then
return 0
fi
local executable_name
executable_name=$(basename "$executable_path")
local shim_path
shim_path="$(asdf_data_dir)/shims/$executable_name"
if [ -f "$shim_path" ]; then
if ! grep -x "# asdf-plugin: ${plugin_name} ${version}" "$shim_path" >/dev/null; then
sed -i.bak -e "s/exec /# asdf-plugin: ${plugin_name} ${version}\\"$'\n''exec /' "$shim_path"
rm "$shim_path".bak
fi
else
cat <<EOF > "$shim_path"
#!/usr/bin/env bash
# asdf-plugin: ${plugin_name} ${version}
exec $(asdf_dir)/bin/asdf exec "${executable_name}" "\$@"
EOF
fi
chmod +x "$shim_path"
}
generate_shim_for_executable() {
local plugin_name=$1
local executable=$2
check_if_plugin_exists "$plugin_name"
local version
IFS=':' read -r -a version_info <<< "$full_version"
if [ "${version_info[0]}" = "ref" ]; then
version="${version_info[1]}"
else
version="${version_info[0]}"
fi
write_shim_script "$plugin_name" "$version" "$executable"
}
generate_shims_for_version() {
local plugin_name=$1
local full_version=$2
for executable_path in $(plugin_executables "$plugin_name" "$full_version"); do
write_shim_script "$plugin_name" "$full_version" "$executable_path"
done
}
remove_obsolete_shims() {
local plugin_name=$1
local full_version=$2
local shims
shims=$(plugin_shims "$plugin_name" "$full_version" | xargs -IX basename X | sort)
local exec_names
exec_names=$(plugin_executables "$plugin_name" "$full_version" | xargs -IX basename X | sort)
local obsolete_shims
obsolete_shims=$(comm -23 <(echo "$shims") <(echo "$exec_names"))
for shim_name in $obsolete_shims; do
remove_shim_for_version "$plugin_name" "$full_version" "$shim_name"
done
}
reshim_command "$@"

View File

@ -1,4 +1,8 @@
# -*- sh -*-
shim_versions_command() {
local shim_name=$1
shim_plugin_versions "$shim_name"
}
shim_versions_command "$@"

View File

@ -1,3 +1,8 @@
# -*- sh -*-
# shellcheck source=lib/commands/reshim.sh
source "$(dirname "$ASDF_CMD_FILE")/reshim.sh"
uninstall_command() {
local plugin_name=$1
local full_version=$2
@ -39,3 +44,14 @@ uninstall_command() {
asdf_run_hook "post_asdf_uninstall_${plugin_name}" "$full_version"
}
remove_shims_for_version() {
local plugin_name=$1
local full_version=$2
for shim_path in $(plugin_shims "$plugin_name" "$full_version"); do
remove_shim_for_version "$plugin_name" "$full_version" "$shim_path"
done
}
uninstall_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
update_command() {
local update_to_head=$1
@ -46,3 +48,5 @@ sort_versions() {
sed 'h; s/[+-]/./g; s/.p\([[:digit:]]\)/.z\1/; s/$/.z/; G; s/\n/ /' | \
LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5n | awk '{print $2}'
}
update_command "$@"

View File

@ -0,0 +1,2 @@
# -*- sh -*-
asdf_version

View File

@ -1,3 +1,5 @@
# -*- sh -*-
where_command() {
local plugin_name=$1
local full_version=$2
@ -41,3 +43,5 @@ where_command() {
fi
fi
}
where_command "$@"

View File

@ -1,3 +1,5 @@
# -*- sh -*-
which_command() {
local shim_name
shim_name=$(basename "$1")
@ -23,3 +25,5 @@ which_command() {
with_shim_executable "$shim_name" print_exec || exit 1
}
which_command "$@"

View File

@ -1,23 +0,0 @@
plugin_extension_command() {
local plugin_bin_dir plugin_cmd
plugin_bin_dir="$(get_plugin_path "$1")/bin"
if test -d "$plugin_bin_dir"; then
if test -f "$plugin_bin_dir/$2"; then
plugin_cmd="$plugin_bin_dir/$2"
shift # consume plugin name
shift # and command name
elif test -f "$plugin_bin_dir/default-command"; then
plugin_cmd="$plugin_bin_dir/default-command"
shift # only consume plugin name
fi
if test -x "$plugin_cmd"; then
exec "$plugin_cmd" "$@"
elif test -f "$plugin_cmd"; then
# shellcheck disable=SC1090 # Cant follow non constant source
source "$plugin_cmd"
exit $?
fi
fi
}

View File

@ -1,128 +1,3 @@
reshim_command() {
local plugin_name=$1
local full_version=$2
if [ -z "$plugin_name" ]; then
local plugins_path
plugins_path=$(get_plugin_path)
if ls "$plugins_path" &> /dev/null; then
for plugin_path in "$plugins_path"/* ; do
plugin_name=$(basename "$plugin_path")
reshim_command "$plugin_name"
done
fi
return 0
fi
check_if_plugin_exists "$plugin_name"
ensure_shims_dir
if [ "$full_version" != "" ]; then
# generate for the whole package version
asdf_run_hook "pre_asdf_reshim_$plugin_name" "$full_version_name"
generate_shims_for_version "$plugin_name" "$full_version"
asdf_run_hook "post_asdf_reshim_$plugin_name" "$full_version"
else
# generate for all versions of the package
local plugin_installs_path
plugin_installs_path="$(asdf_data_dir)/installs/${plugin_name}"
for install in "${plugin_installs_path}"/*/; do
local full_version_name
full_version_name=$(basename "$install" | sed 's/ref\-/ref\:/')
asdf_run_hook "pre_asdf_reshim_$plugin_name" "$full_version_name"
generate_shims_for_version "$plugin_name" "$full_version_name"
remove_obsolete_shims "$plugin_name" "$full_version_name"
asdf_run_hook "post_asdf_reshim_$plugin_name" "$full_version_name"
done
fi
}
ensure_shims_dir() {
# Create shims dir if doesn't exist
if [ ! -d "$(asdf_data_dir)/shims" ]; then
mkdir "$(asdf_data_dir)/shims"
fi
}
write_shim_script() {
local plugin_name=$1
local version=$2
local executable_path=$3
if ! is_executable "$executable_path"; then
return 0
fi
local executable_name
executable_name=$(basename "$executable_path")
local shim_path
shim_path="$(asdf_data_dir)/shims/$executable_name"
if [ -f "$shim_path" ]; then
if ! grep -x "# asdf-plugin: ${plugin_name} ${version}" "$shim_path" >/dev/null; then
sed -i.bak -e "s/exec /# asdf-plugin: ${plugin_name} ${version}\\"$'\n''exec /' "$shim_path"
rm "$shim_path".bak
fi
else
cat <<EOF > "$shim_path"
#!/usr/bin/env bash
# asdf-plugin: ${plugin_name} ${version}
exec $(asdf_dir)/bin/asdf exec "${executable_name}" "\$@"
EOF
fi
chmod +x "$shim_path"
}
generate_shim_for_executable() {
local plugin_name=$1
local executable=$2
check_if_plugin_exists "$plugin_name"
local version
IFS=':' read -r -a version_info <<< "$full_version"
if [ "${version_info[0]}" = "ref" ]; then
version="${version_info[1]}"
else
version="${version_info[0]}"
fi
write_shim_script "$plugin_name" "$version" "$executable"
}
generate_shims_for_version() {
local plugin_name=$1
local full_version=$2
for executable_path in $(plugin_executables "$plugin_name" "$full_version"); do
write_shim_script "$plugin_name" "$full_version" "$executable_path"
done
}
remove_obsolete_shims() {
local plugin_name=$1
local full_version=$2
local shims
shims=$(plugin_shims "$plugin_name" "$full_version" | xargs -IX basename X | sort)
local exec_names
exec_names=$(plugin_executables "$plugin_name" "$full_version" | xargs -IX basename X | sort)
local obsolete_shims
obsolete_shims=$(comm -23 <(echo "$shims") <(echo "$exec_names"))
for shim_name in $obsolete_shims; do
remove_shim_for_version "$plugin_name" "$full_version" "$shim_name"
done
}
remove_shim_for_version() {
local plugin_name=$1
@ -149,11 +24,3 @@ remove_shim_for_version() {
rm "$shim_path"
fi
}
remove_shims_for_version() {
local plugin_name=$1
local full_version=$2
for shim_path in $(plugin_shims "$plugin_name" "$full_version"); do
remove_shim_for_version "$plugin_name" "$full_version" "$shim_path"
done
}

View File

@ -1,3 +1,5 @@
# -*- sh -*-
version_command() {
local cmd=$1
local plugin=$2
@ -43,69 +45,3 @@ version_command() {
echo "$plugin ${versions[*]}" >> "$file"
fi
}
local_command() {
local parent=false
local positional=()
while [[ $# -gt 0 ]]
do
case $1 in
-p|--parent)
parent="true"
shift # past value
;;
*)
positional+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
set -- "${positional[@]}" # restore positional parameters
if [ $parent = true ]; then
# shellcheck disable=2068
version_command "local-tree" $@
else
# shellcheck disable=2068
version_command "local" $@
fi
}
global_command() {
# shellcheck disable=2068
version_command "global" $@
}
# Output from this command must be executable shell code
shell_command() {
if [ "$#" -lt "2" ]; then
echo "Usage: asdf shell <name> {<version>|--unset}" >&2
echo 'false'
exit 1
fi
local plugin=$1
local version=$2
local upcase_name
upcase_name=$(echo "$plugin" | tr '[:lower:]-' '[:upper:]_')
local version_env_var="ASDF_${upcase_name}_VERSION"
if [ "$version" = "--unset" ]; then
echo "unset $version_env_var"
exit 0
fi
if ! (check_if_version_exists "$plugin" "$version"); then
echo 'false'
exit 1
fi
case $ASDF_SHELL in
fish )
echo "set -gx $version_env_var \"$version\"";;
* )
echo "export $version_env_var=\"$version\"";;
esac
}

View File

@ -2,7 +2,7 @@
exec shellcheck -s bash -x \
asdf.sh lint.sh release/tag.sh \
bin/asdf bin/private/asdf-exec \
lib/utils.sh lib/commands/*.sh \
lib/utils.sh lib/commands/* \
completions/*.bash \
test/test_helpers.bash \
test/fixtures/dummy_plugin/bin/*

View File

@ -15,11 +15,11 @@ teardown() {
plugin_path="$(get_plugin_path dummy)"
# this plugin defines a new `asdf dummy foo` command
cat <<'EOF' > "$plugin_path/bin/foo"
cat <<'EOF' > "$plugin_path/bin/command-foo"
#!/usr/bin/env bash
echo this is an executable $*
EOF
chmod +x "$plugin_path/bin/foo"
chmod +x "$plugin_path/bin/command-foo"
expected="this is an executable bar"
@ -32,7 +32,7 @@ EOF
plugin_path="$(get_plugin_path dummy)"
# this plugin defines a new `asdf dummy foo` command
echo 'echo sourced script has asdf utils $(get_plugin_path dummy) $*' > "$plugin_path/bin/foo"
echo 'echo sourced script has asdf utils $(get_plugin_path dummy) $*' > "$plugin_path/bin/command-foo"
expected="sourced script has asdf utils $plugin_path bar"
@ -45,11 +45,11 @@ EOF
plugin_path="$(get_plugin_path dummy)"
# this plugin defines a new `asdf dummy` command
cat <<'EOF' > "$plugin_path/bin/default-command"
cat <<'EOF' > "$plugin_path/bin/command"
#!/usr/bin/env bash
echo hello
EOF
chmod +x "$plugin_path/bin/default-command"
chmod +x "$plugin_path/bin/command"
expected="hello"
@ -62,11 +62,11 @@ EOF
plugin_path="$(get_plugin_path dummy)"
# this plugin defines a new `asdf dummy` command
cat <<'EOF' > "$plugin_path/bin/default-command"
cat <<'EOF' > "$plugin_path/bin/command"
#!/usr/bin/env bash
echo hello $*
EOF
chmod +x "$plugin_path/bin/default-command"
chmod +x "$plugin_path/bin/command"
expected="hello world"

View File

@ -2,10 +2,6 @@
load test_helpers
. $(dirname $BATS_TEST_DIRNAME)/lib/commands/shim_versions.sh
. $(dirname $BATS_TEST_DIRNAME)/lib/commands/reshim.sh
. $(dirname $BATS_TEST_DIRNAME)/lib/commands/install.sh
setup() {
setup_asdf_dir
install_dummy_plugin

View File

@ -59,4 +59,3 @@ setup_repo() {
cp -r "$BATS_TEST_DIRNAME/fixtures/dummy_plugins_repo" "$ASDF_DIR/repository"
touch "$(asdf_dir)/tmp/repo-updated"
}

View File

@ -2,10 +2,6 @@
load test_helpers
. $(dirname $BATS_TEST_DIRNAME)/lib/commands/reshim.sh
. $(dirname $BATS_TEST_DIRNAME)/lib/commands/install.sh
. $(dirname $BATS_TEST_DIRNAME)/lib/commands/uninstall.sh
setup() {
setup_asdf_dir
install_dummy_plugin

View File

@ -2,17 +2,21 @@
load test_helpers
. $(dirname "$BATS_TEST_DIRNAME")/lib/commands/update.sh
setup() {
setup_asdf_dir
install_dummy_plugin
BASE_DIR=$(mktemp -dt asdf.XXXX)
HOME=$BASE_DIR/home
ASDF_DIR=$HOME/.asdf
git clone -o local "$(dirname "$BATS_TEST_DIRNAME")" "$ASDF_DIR"
git --git-dir "$ASDF_DIR/.git" remote add origin https://github.com/asdf-vm/asdf.git
mkdir -p "$ASDF_DIR/plugins"
mkdir -p "$ASDF_DIR/installs"
mkdir -p "$ASDF_DIR/shims"
mkdir -p "$ASDF_DIR/tmp"
ASDF_BIN="$ASDF_DIR/bin"
(
cd $ASDF_DIR
git init
git remote add origin https://github.com/asdf-vm/asdf.git
)
# shellcheck disable=SC2031
PATH=$ASDF_BIN:$ASDF_DIR/shims:$PATH
install_dummy_plugin
PROJECT_DIR=$HOME/project
mkdir $PROJECT_DIR
@ -22,69 +26,69 @@ teardown() {
clean_asdf_dir
}
@test "update_command --head should checkout the master branch" {
run update_command --head
@test "asdf update --head should checkout the master branch" {
run asdf update --head
[ "$status" -eq 0 ]
cd $ASDF_DIR
[ $(git rev-parse --abbrev-ref HEAD) = "master" ]
}
@test "update_command should checkout the latest non-RC tag" {
@test "asdf update should checkout the latest non-RC tag" {
local tag=$(git tag | grep -vi "rc" | head -1)
run update_command
run asdf update
[ "$status" -eq 0 ]
cd $ASDF_DIR
echo $(git tag) | grep $tag
[ "$status" -eq 0 ]
}
@test "update_command should checkout the latest tag when configured with use_release_candidates = yes" {
@test "asdf update should checkout the latest tag when configured with use_release_candidates = yes" {
local tag=$(git tag | head -1)
export ASDF_CONFIG_DEFAULT_FILE=$BATS_TMPDIR/asdfrc_defaults
echo "use_release_candidates = yes" > $ASDF_CONFIG_DEFAULT_FILE
run update_command
run asdf update
[ "$status" -eq 0 ]
cd $ASDF_DIR
echo $(git tag) | grep $tag
[ "$status" -eq 0 ]
}
@test "update_command is a noop for non-git repos" {
@test "asdf update is a noop for non-git repos" {
(cd $ASDF_DIR && rm -r .git/)
run update_command
run asdf update
[ "$status" -eq 1 ]
[ "$(echo -e "Update command disabled. Please use the package manager that you used to install asdf to upgrade asdf.")" == "$output" ]
}
@test "update_command should not remove plugin versions" {
@test "asdf update should not remove plugin versions" {
run asdf install dummy 1.1
[ "$status" -eq 0 ]
[ $(cat $ASDF_DIR/installs/dummy/1.1/version) = "1.1" ]
run update_command
run asdf update
[ "$status" -eq 0 ]
[ -f $ASDF_DIR/installs/dummy/1.1/version ]
run update_command --head
run asdf update --head
[ "$status" -eq 0 ]
[ -f $ASDF_DIR/installs/dummy/1.1/version ]
}
@test "update_command should not remove plugins" {
@test "asdf update should not remove plugins" {
# dummy plugin is already installed
run update_command
run asdf update
[ "$status" -eq 0 ]
[ -d $ASDF_DIR/plugins/dummy ]
run update_command --head
run asdf update --head
[ "$status" -eq 0 ]
[ -d $ASDF_DIR/plugins/dummy ]
}
@test "update_command should not remove shims" {
@test "asdf update should not remove shims" {
run asdf install dummy 1.1
[ -f $ASDF_DIR/shims/dummy ]
run update_command
run asdf update
[ "$status" -eq 0 ]
[ -f $ASDF_DIR/shims/dummy ]
run update_command --head
run asdf update --head
[ "$status" -eq 0 ]
[ -f $ASDF_DIR/shims/dummy ]
}

View File

@ -10,6 +10,8 @@ setup() {
PROJECT_DIR=$HOME/project
mkdir -p $PROJECT_DIR
cd $HOME
}
teardown() {

View File

@ -2,8 +2,6 @@
load test_helpers
. $(dirname $BATS_TEST_DIRNAME)/lib/commands/version_commands.sh
setup() {
setup_asdf_dir
install_dummy_plugin
@ -261,26 +259,26 @@ teardown() {
[ "$output" = "Shell integration is not enabled. Please ensure you source asdf in your shell setup." ]
}
@test "sh-shell should emit an error when plugin does not exist" {
run asdf sh-shell "nonexistent" "1.0.0"
@test "export-shell-version should emit an error when plugin does not exist" {
run asdf export-shell-version sh "nonexistent" "1.0.0"
[ "$status" -eq 1 ]
[ "$output" = $'No such plugin: nonexistent\nfalse' ]
}
@test "sh-shell should emit an error when version does not exist" {
run asdf sh-shell "dummy" "nonexistent"
@test "export-shell-version should emit an error when version does not exist" {
run asdf export-shell-version sh "dummy" "nonexistent"
[ "$status" -eq 1 ]
[ "$output" = $'version nonexistent is not installed for dummy\nfalse' ]
}
@test "sh-shell should export version if it exists" {
run asdf sh-shell "dummy" "1.1.0"
@test "export-shell-version should export version if it exists" {
run asdf export-shell-version sh "dummy" "1.1.0"
[ "$status" -eq 0 ]
[ "$output" = "export ASDF_DUMMY_VERSION=\"1.1.0\"" ]
}
@test "sh-shell should use set when shell is fish" {
ASDF_SHELL=fish run asdf sh-shell "dummy" "1.1.0"
@test "export-shell-version should use set when shell is fish" {
run asdf export-shell-version fish "dummy" "1.1.0"
[ "$status" -eq 0 ]
[ "$output" = "set -gx ASDF_DUMMY_VERSION \"1.1.0\"" ]
}

View File

@ -2,8 +2,6 @@
load test_helpers
. $(dirname $BATS_TEST_DIRNAME)/lib/commands/where.sh
function setup() {
setup_asdf_dir
install_dummy_plugin

View File

@ -2,9 +2,6 @@
load test_helpers
. $(dirname $BATS_TEST_DIRNAME)/lib/commands/which.sh
. $(dirname $BATS_TEST_DIRNAME)/lib/commands/install.sh
setup() {
setup_asdf_dir
install_dummy_plugin