Merge pull request #669 from asdf-vm/tb/keep-source

Keep Source
This commit is contained in:
Trevor Brown 2020-05-14 09:24:48 -04:00 committed by GitHub
commit a7252e687a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 253 additions and 3 deletions

View File

@ -42,6 +42,7 @@ legacy_version_file = yes
- `legacy_version_file` - defaults to `no`. If set to yes it will cause plugins that support this feature to read the version files used by other version managers (e.g. `.ruby-version` in the case of Ruby's `rbenv`).
- `use_release_candidates` - defaults to `no`. If set to yes it will cause the `asdf update` command to upgrade to the latest release candidate release instead of the latest semantic version.
- `always_keep_download` - defaults to `no`. If set to `yes` it will cause `asdf install` always keep the source code or binary it downloads. If set to `no` the source code or binary downloaded by `asdf install` will be deleted after successful installation.
## Environment Variables

View File

@ -5,17 +5,25 @@ A plugin is a git repo, with a couple executable scripts, to support versioning
## 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
## Environment Variables
All scripts except `bin/list-all` will have access to the following env vars to act upon:
- `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 the it _has been_ installed (or _should_ be installed in case of the `bin/install` script)
These additional environment variables the `bin/install` script will also have accesss to:
These additional environment variables will be available to the `bin/install` script:
- `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.
These additional environment variables will be available to the `bin/download` script:
- `ASDF_DOWNLOAD_PATH` - the path to where the source code or binary should be downloaded.
#### bin/list-all
@ -29,6 +37,16 @@ Note that the newest version should be listed last so it appears closer to the u
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).
#### bin/download
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 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.
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 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.
#### bin/install
This script should install the version, in the path mentioned in `ASDF_INSTALL_PATH`.

View File

@ -15,14 +15,15 @@ handle_cancel() {
install_command() {
local plugin_name=$1
local full_version=$2
local extra_args="${*:3}"
if [ "$plugin_name" = "" ] && [ "$full_version" = "" ]; then
install_local_tool_versions
install_local_tool_versions "$extra_args"
elif [[ $# -eq 1 ]]; then
display_error "You must specify a name and a version to install"
exit 1
else
install_tool_version "$plugin_name" "$full_version"
install_tool_version "$plugin_name" "$full_version" "$extra_args"
fi
}
@ -80,10 +81,25 @@ install_local_tool_versions() {
install_tool_version() {
local plugin_name=$1
local full_version=$2
local flags=$3
local keep_download
local plugin_path
plugin_path=$(get_plugin_path "$plugin_name")
check_if_plugin_exists "$plugin_name"
for flag in $flags; do
case "$flag" in
"--keep-download")
keep_download=true
shift
;;
*)
shift
;;
esac
done
if [ "$full_version" = "system" ]; then
return
fi
@ -106,6 +122,8 @@ install_tool_version() {
local install_path
install_path=$(get_install_path "$plugin_name" "$install_type" "$version")
local download_path
download_path=$(get_download_path "$plugin_name" "$install_type" "$version")
local concurrency
concurrency=$(get_concurrency)
trap 'handle_cancel $install_path' INT
@ -113,10 +131,35 @@ install_tool_version() {
if [ -d "$install_path" ]; then
echo "$plugin_name $full_version is already installed"
else
if [ -f "${plugin_path}/bin/download" ]; then
# Not a legacy plugin
# Run the download script
(
# shellcheck disable=SC2030
export ASDF_INSTALL_TYPE=$install_type
# shellcheck disable=SC2030
export ASDF_INSTALL_VERSION=$version
# shellcheck disable=SC2030
export ASDF_INSTALL_PATH=$install_path
# shellcheck disable=SC2030
export ASDF_DOWNLOAD_PATH=$download_path
mkdir "$download_path"
asdf_run_hook "pre_asdf_download_${plugin_name}" "$full_version"
bash "${plugin_path}"/bin/download
)
fi
(
# shellcheck disable=SC2031
export ASDF_INSTALL_TYPE=$install_type
# shellcheck disable=SC2031
export ASDF_INSTALL_VERSION=$version
# shellcheck disable=SC2031
export ASDF_INSTALL_PATH=$install_path
# shellcheck disable=SC2031
export ASDF_DOWNLOAD_PATH=$download_path
# shellcheck disable=SC2031
export ASDF_CONCURRENCY=$concurrency
mkdir "$install_path"
asdf_run_hook "pre_asdf_install_${plugin_name}" "$full_version"
@ -125,7 +168,14 @@ install_tool_version() {
local exit_code=$?
if [ $exit_code -eq 0 ]; then
# Remove download directory if --keep-download flag or always_keep_download config setting are not set
always_keep_download=$(get_asdf_config_value "always_keep_download")
if [ ! "$keep_download" = "true" ] && [ ! "$always_keep_download" = "yes" ] && [ -d "$download_path" ]; then
rm -r "$download_path"
fi
asdf reshim "$plugin_name" "$full_version"
asdf_run_hook "post_asdf_install_${plugin_name}" "$full_version"
else
handle_failure "$install_path"

View File

@ -19,6 +19,7 @@ plugin_remove_command() {
rm -rf "$plugin_path"
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

View File

@ -67,6 +67,25 @@ get_install_path() {
fi
}
get_download_path() {
local plugin=$1
local install_type=$2
local version=$3
local download_dir
download_dir="$(asdf_data_dir)/downloads"
mkdir -p "${download_dir}/${plugin}"
if [ "$install_type" = "version" ]; then
echo "${download_dir}/${plugin}/${version}"
elif [ "$install_type" = "path" ]; then
return
else
echo "${download_dir}/${plugin}/${install_type}-${version}"
fi
}
list_installed_versions() {
local plugin_name=$1
local plugin_path

View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
get_legacy_version() {
current_directory=$1
version_file="$current_directory/.dummy-version"
if [ -f "$version_file" ]; then
cat "$version_file"
fi
}
get_legacy_version "$1"

View File

@ -0,0 +1,17 @@
#!/usr/bin/env bash
mkdir -p "$ASDF_INSTALL_PATH"
env >"$ASDF_INSTALL_PATH/env"
echo "$ASDF_INSTALL_VERSION" >"$ASDF_INSTALL_PATH/version"
# create the dummy executable
mkdir -p "$ASDF_INSTALL_PATH/bin"
cat <<EOF >"$ASDF_INSTALL_PATH/bin/dummy"
echo This is Dummy ${ASDF_INSTALL_VERSION}! \$2 \$1
EOF
chmod +x "$ASDF_INSTALL_PATH/bin/dummy"
mkdir -p "$ASDF_INSTALL_PATH/bin/subdir"
cat <<EOF >"$ASDF_INSTALL_PATH/bin/subdir/other_bin"
echo This is Other Bin ${ASDF_INSTALL_VERSION}! \$2 \$1
EOF
chmod +x "$ASDF_INSTALL_PATH/bin/subdir/other_bin"

View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
versions_list=(1.0 1.1 2.0)
echo "${versions_list[@]}"

View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
echo ".dummy-version .dummyrc"

View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
# shellcheck disable=SC2020
tr <"$1" -d "dummy-"

3
test/fixtures/dummy_plugin/bin/download vendored Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
exit 0

View File

@ -4,6 +4,7 @@ load test_helpers
setup() {
setup_asdf_dir
install_dummy_legacy_plugin
install_dummy_plugin
PROJECT_DIR=$HOME/project
@ -20,6 +21,12 @@ teardown() {
[ $(cat $ASDF_DIR/installs/dummy/1.1/version) = "1.1" ]
}
@test "install_command installs the correct version for plugins without download script" {
run asdf install legacy-dummy 1.1
[ "$status" -eq 0 ]
[ $(cat $ASDF_DIR/installs/legacy-dummy/1.1/version) = "1.1" ]
}
@test "install_command without arguments installs even if the user is terrible and does not use newlines" {
cd $PROJECT_DIR
echo -n 'dummy 1.2' > ".tool-versions"
@ -56,6 +63,14 @@ teardown() {
[ "$status" -eq 0 ]
}
@test "install_command should create a shim with asdf-plugin metadata for plugins without download script" {
run asdf install legacy-dummy 1.0
[ "$status" -eq 0 ]
[ -f $ASDF_DIR/installs/legacy-dummy/1.0/env ]
run grep "asdf-plugin: legacy-dummy 1.0" $ASDF_DIR/shims/dummy
[ "$status" -eq 0 ]
}
@test "install_command on two versions should create a shim with asdf-plugin metadata" {
run asdf install dummy 1.1
[ "$status" -eq 0 ]
@ -200,3 +215,26 @@ EOM
[ "$status" -eq 0 ]
[ $(cat $ASDF_DIR/installs/dummy/1.1/version) = "1.1" ]
}
@test "install_command deletes the download directory" {
run asdf install dummy 1.1
[ "$status" -eq 0 ]
[ ! -d $ASDF_DIR/downloads/dummy/1.1 ]
[ $(cat $ASDF_DIR/installs/dummy/1.1/version) = "1.1" ]
}
@test "install_command keeps the download directory when --keep-download flag is provided" {
run asdf install dummy 1.1 --keep-download
[ "$status" -eq 0 ]
[ -d $ASDF_DIR/downloads/dummy/1.1 ]
[ $(cat $ASDF_DIR/installs/dummy/1.1/version) = "1.1" ]
}
@test "install_command keeps the download directory when always_keep_download setting is true" {
echo 'always_keep_download = yes' > $HOME/.asdfrc
run asdf install dummy 1.1
echo $output
[ "$status" -eq 0 ]
[ -d $ASDF_DIR/downloads/dummy/1.1 ]
[ $(cat $ASDF_DIR/installs/dummy/1.1/version) = "1.1" ]
}

View File

@ -0,0 +1,29 @@
#!/usr/bin/env bats
load test_helpers
setup() {
setup_asdf_dir
install_dummy_plugin
}
teardown() {
clean_asdf_dir
}
@test "plugin_remove command removes the plugin directory" {
run asdf install dummy 1.0
[ "$status" -eq 0 ]
[ -d "$ASDF_DIR/downloads/dummy" ]
run asdf plugin-remove "dummy"
[ "$status" -eq 0 ]
[ ! -d "$ASDF_DIR/downloads/dummy" ]
}
@test "plugin_remove command fails if the plugin doesn't exist" {
run asdf plugin-remove "does-not-exist"
[ "$status" -eq 1 ]
echo "$output" | grep "No such plugin: does-not-exist"
}

View File

@ -27,6 +27,12 @@ install_mock_plugin() {
cp -r "$BATS_TEST_DIRNAME/fixtures/dummy_plugin" "$location/plugins/$plugin_name"
}
install_mock_legacy_plugin() {
local plugin_name=$1
local location="${2:-$ASDF_DIR}"
cp -r "$BATS_TEST_DIRNAME/fixtures/dummy_legacy_plugin" "$location/plugins/$plugin_name"
}
install_mock_plugin_repo() {
local plugin_name=$1
local location="${BASE_DIR}/repo-${plugin_name}"
@ -49,6 +55,10 @@ install_dummy_plugin() {
install_mock_plugin "dummy"
}
install_dummy_legacy_plugin() {
install_mock_legacy_plugin "legacy-dummy"
}
install_dummy_version() {
install_mock_plugin_version "dummy" "$1"
}

View File

@ -18,6 +18,47 @@ teardown() {
clean_asdf_dir
}
@test "get_install_path should output version path when version is provided" {
run get_install_path foo version "1.0.0"
[ "$status" -eq 0 ]
install_path=${output#$HOME/}
[ "$install_path" = ".asdf/installs/foo/1.0.0" ]
}
@test "get_install_path should output custom path when custom install type is provided" {
run get_install_path foo custom "1.0.0"
[ "$status" -eq 0 ]
install_path=${output#$HOME/}
[ "$install_path" = ".asdf/installs/foo/custom-1.0.0" ]
}
@test "get_install_path should output path when path version is provided" {
run get_install_path foo path "/some/path"
[ "$status" -eq 0 ]
[ "$output" = "/some/path" ]
}
@test "get_download_path should output version path when version is provided" {
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" ]
}
@test "get_download_path should output custom path when custom download type is provided" {
run get_download_path foo custom "1.0.0"
[ "$status" -eq 0 ]
download_path=${output#$HOME/}
[ "$download_path" = ".asdf/downloads/foo/custom-1.0.0" ]
}
@test "get_download_path should output nothing when path version is provided" {
run get_download_path foo path "/some/path"
[ "$status" -eq 0 ]
[ "$output" = "" ]
}
@test "check_if_version_exists should exit with 1 if plugin does not exist" {
run check_if_version_exists "inexistent" "1.0.0"
[ "$status" -eq 1 ]