diff --git a/.gitignore b/.gitignore index 8b254c4..a02b3bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ ruby-build +ruby-build-source diff --git a/README.md b/README.md index b730da7..7e3a584 100644 --- a/README.md +++ b/README.md @@ -27,15 +27,17 @@ RUBY_APPLY_PATCHES=$'dir/1.patch\n2.patch\nhttp://example.com/3.patch' asdf inst RUBY_APPLY_PATCHES=$(curl -s https://raw.githubusercontent.com/rvm/rvm/master/patchsets/ruby/2.1.1/railsexpress) asdf install ruby 2.1.1 ``` -> [!NOTE] -> This plugin does not automatically fetch new Ruby versions. Running `asdf plugin update ruby` will update asdf-ruby and ensure the latest versions of Ruby are available to install. If the desired ruby version is still not showing up see the below [Troubleshooting](https://github.com/asdf-vm/asdf-ruby?tab=readme-ov-file#troubleshooting) section. +By default asdf-ruby automatically fetches the latest release of ruby-build, so new Ruby versions are available as soon as ruby-build supports them. -By default asdf-ruby uses a recent release of ruby-build, however instead you can choose your own branch/tag through the `ASDF_RUBY_BUILD_VERSION` variable: +You can pin to a specific ruby-build version/branch/tag with the `ASDF_RUBY_BUILD_VERSION` environment variable: ``` -ASDF_RUBY_BUILD_VERSION=master asdf install ruby 2.6.4 +ASDF_RUBY_BUILD_VERSION=v20240101 asdf install ruby 3.3.0 +ASDF_RUBY_BUILD_VERSION=master asdf install ruby 3.3.0 ``` +Set `ASDF_RUBY_SKIP_RUBY_BUILD_UPDATE=1` to skip the network check and reuse whatever ruby-build refs are already cached locally. + ## Default gems asdf-ruby can automatically install a set of default gems right after @@ -68,7 +70,7 @@ note that you might have to change `.ruby-version` to include full version (e.g. ## Troubleshooting > [!NOTE] -> The most common issue reported for this plugin is a missing Ruby version. If you are not seeing a recent Ruby version in the list of available Ruby versions it's likely due to having an older version of this plugin. Run `asdf plugin update ruby` to get the most recent list of Ruby versions. If it is still not showing up then this plugin's `RUBY_BUILD_VERSION` in lib/utils.sh likely needs updated with the latest ruby-build release https://github.com/rbenv/ruby-build/releases. Please check for an existing PR before submitting a new one. If there is not one, please fork the repo and submit one. If this plugin's ruby-build needs updated, you can workaround it with `ASDF_RUBY_BUILD_VERSION`. A note in the above [Use](https://github.com/asdf-vm/asdf-ruby?tab=readme-ov-file#use) section describes how to do this. +> If you are not seeing a recent Ruby version, check ruby-build's releases at https://github.com/rbenv/ruby-build/releases to see if it's been added yet. If you are moving to asdf-ruby from another Ruby version manager, it is recommended to completely uninstall the old Ruby version manager before installing asdf-ruby. diff --git a/lib/utils.sh b/lib/utils.sh index b3ffec8..f0034d9 100644 --- a/lib/utils.sh +++ b/lib/utils.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash -RUBY_BUILD_VERSION="${ASDF_RUBY_BUILD_VERSION:-v20260503}" -RUBY_BUILD_TAG="$RUBY_BUILD_VERSION" +RUBY_BUILD_REPOSITORY="https://github.com/rbenv/ruby-build.git" echoerr() { echo >&2 -e "\033[0;31m$1\033[0m" @@ -17,54 +16,98 @@ ensure_ruby_build_setup() { } ensure_ruby_build_installed() { - local current_ruby_build_version - - if [ ! -f "$(ruby_build_path)" ]; then - download_ruby_build - else - current_ruby_build_version="$("$(ruby_build_path)" --version | cut -d ' ' -f2)" - # If ruby-build version does not start with 'v', - # add 'v' to beginning of version - # shellcheck disable=SC2086 - if [ ${current_ruby_build_version:0:1} != "v" ]; then - current_ruby_build_version="v$current_ruby_build_version" - fi - if [ "$current_ruby_build_version" != "$RUBY_BUILD_VERSION" ]; then - # If the ruby-build directory already exists and the version does not - # match, remove it and download the correct version - rm -rf "$(ruby_build_dir)" - download_ruby_build + local source_dir target_ref + source_dir="$(ruby_build_source_dir)" + + if ! ensure_ruby_build_source "$source_dir"; then + if [ -f "$(ruby_build_path)" ]; then + echoerr "Warning: Could not access ruby-build source; using existing installation." + return 0 fi + errorexit "Failed to clone ruby-build. Check your network connection." + fi + + target_ref="$(resolve_ruby_build_ref "$source_dir")" || + errorexit "Could not determine ruby-build version." + + if needs_install "$target_ref"; then + install_ruby_build "$source_dir" "$target_ref" + fi +} + +# Maintain a persistent clone of ruby-build. Cheap `git fetch` on each install +# keeps tag list current; set ASDF_RUBY_SKIP_RUBY_BUILD_UPDATE=1 to bypass. +ensure_ruby_build_source() { + local source_dir="$1" + + if [ ! -d "$source_dir/.git" ]; then + echoerr "Cloning ruby-build..." + rm -rf "$source_dir" + git clone "$RUBY_BUILD_REPOSITORY" "$source_dir" >/dev/null 2>&1 || return 1 + return 0 + fi + + if [ -n "${ASDF_RUBY_SKIP_RUBY_BUILD_UPDATE:-}" ]; then + return 0 fi + + git -C "$source_dir" fetch --tags --prune origin >/dev/null 2>&1 || + echoerr "Warning: Could not update ruby-build, using cached refs." + return 0 } -download_ruby_build() { - # Print to stderr so asdf doesn't assume this string is a list of versions - echoerr "Downloading ruby-build..." - # shellcheck disable=SC2155 - local build_dir="$(ruby_build_source_dir)" +# Pick the ref to check out: explicit env var > latest release tag. +resolve_ruby_build_ref() { + local source_dir="$1" - # Remove directory in case it still exists from last download - rm -rf "$build_dir" + if [ -n "${ASDF_RUBY_BUILD_VERSION:-}" ]; then + echo "$ASDF_RUBY_BUILD_VERSION" + return 0 + fi - # Clone down and checkout the correct ruby-build version - git clone https://github.com/rbenv/ruby-build.git "$build_dir" >/dev/null 2>&1 - ( - cd "$build_dir" || exit - git checkout "$RUBY_BUILD_TAG" >/dev/null 2>&1 - ) + local latest + latest="$(git -C "$source_dir" tag --list 'v*' --sort=-v:refname | head -1)" + if [ -n "$latest" ]; then + echo "$latest" + return 0 + fi + return 1 +} - # Install in the ruby-build dir - PREFIX="$(ruby_build_dir)" "$build_dir/install.sh" +needs_install() { + local target_ref="$1" installed_version + [ ! -f "$(ruby_build_path)" ] && return 0 - # Remove ruby-build source dir - rm -rf "$build_dir" + installed_version="$("$(ruby_build_path)" --version | cut -d ' ' -f2)" + if [ "${installed_version:0:1}" != "v" ]; then + installed_version="v$installed_version" + fi + [ "$installed_version" != "$target_ref" ] +} + +install_ruby_build() { + local source_dir="$1" ref="$2" + echoerr "Installing ruby-build ${ref}..." + + local checkout_ref="$ref" + if git -C "$source_dir" show-ref --verify --quiet "refs/remotes/origin/$ref"; then + checkout_ref="origin/$ref" + fi + git -C "$source_dir" checkout --detach "$checkout_ref" >/dev/null 2>&1 || + errorexit "Failed to checkout ruby-build ref ${ref}." + + rm -rf "$(ruby_build_dir)" + local install_dir + install_dir="$(cd "$(asdf_ruby_plugin_path)" && pwd)/ruby-build" + PREFIX="$install_dir" "$source_dir/install.sh" || + errorexit "Failed to install ruby-build." } asdf_ruby_plugin_path() { # shellcheck disable=SC2005 echo "$(dirname "$(dirname "$0")")" } + ruby_build_dir() { echo "$(asdf_ruby_plugin_path)/ruby-build" }