A tool to find out what the earliest version that your project supports is!
#!/usr/bin/env bash | |
# With revisions from @parasyte for macOS compatibility | |
# Requires bash >= 5 (mapfile) | |
if [[ "$1" == "--keep-versions" ]]; then | |
keep_versions="1" | |
fi | |
purple="\e[0;35m" | |
reset="\e[0m" | |
releases_url="https://raw.githubusercontent.com/rust-lang/rust/master/RELEASES.md" | |
mapfile -t versions < <(curl -s "$releases_url" \ | |
| grep -v alpha \ | |
| egrep -o '^Version [1-9][0-9.]+' \ | |
| cut -d\ -f2) | |
# Before that, we have to use `cargo build` | |
checkindex=$(echo ${versions[@]/1.15.0//} | cut -d/ -f1 | wc -w | tr -d ' ') | |
n_versions=${#versions[@]} | |
echo -e "${purple}We know of ${reset}${n_versions}${purple} stable Rust versions." | |
mapfile -t priors < <(rustup toolchain list \ | |
| egrep -o '^[0-9.]+') | |
echo -e "There are ${reset}${#priors[@]}${purple} past versions explicitly installed here." | |
current=$(rustc --version | cut -d\ -f2) | |
curindex=$(echo ${versions[@]/$current//} | cut -d/ -f1 | wc -w | tr -d ' ') | |
if [[ $curindex == 0 ]]; then | |
echo -e "You are on the latest stable: ${reset}${current}${purple}." | |
elif [[ $curindex == $n_versions ]]; then | |
echo -e "You are not currently on a stable: ${reset}${current}${purple}" \ | |
"(latest is ${reset}${versions[0]}${purple})." | |
else | |
echo -e "You are not on the latest stable: ${reset}${current}${purple}" \ | |
"(latest is ${reset}${versions[0]}${purple})." | |
fi | |
# Exaggerated (+2) from theoretical given observations | |
est_steps=$(echo "l($n_versions - 1)/l(2) + 3" | bc -l | cut -d. -f1) | |
echo | |
echo "Now going to binary search over Rust versions to find the earliest one" \ | |
"which compiles your project. We do this by repeatedly installing and checking" \ | |
$(if [[ -z "$keep_versions" ]]; then | |
echo -e "then uninstalling Rust versions through rustup. Versions that are" \ | |
"already installed will not be removed (at the end, your system should" \ | |
"look the same). If you want to keep the versions this script downloads" \ | |
"instead, quit and run again with the ${reset}--keep-versions${purple} flag." | |
else | |
echo -e "Rust versions through rustup. As you've passed the" \ | |
"${reset}--keep-versions${purple} flag, versions this script downloads will" \ | |
"be kept instead of being cleaned up immediately." | |
fi) \ | |
| fold -s | |
echo | |
echo "You'll want a fast, unmetered internet connection. If you're running Windows," \ | |
"it will take forever due to https://github.com/rust-lang/rustup.rs/issues/1540." \ | |
| fold -s | |
if [[ -z "$keep_versions" ]]; then | |
echo | |
echo "To pause on Linux/macOS, prefer Ctrl-Z / fg." \ | |
| fold -s | |
fi | |
echo | |
echo -ne "If you still want to proceed (estimated ${reset}${est_steps}${purple} iterations)," \ | |
"press enter now. Otherwise, abort with Ctrl-C.\n" \ | |
"\n${reset}=> " \ | |
| fold -s | |
read | |
echo -e "${purple}" | |
# absolute smallest | |
absmin="$((n_versions - 1))" | |
# smallest unsupported | |
trymin="$absmin" | |
# smallest supported | |
trymax="0" | |
# what we're checking now | |
target="$trymin" | |
# default variable values, needed for cleanup | |
a_priori= | |
target_v="${versions[$target]}" | |
function cleanup { | |
if [[ -z "$a_priori" ]] && [[ -z "$keep_versions" ]]; then | |
echo -e "${reset}" | |
rustup uninstall "$target_v" | |
echo -e "${purple}" | |
fi | |
} | |
# remove the last installed version when the script is interrupted | |
trap 'cleanup ; echo -e "${reset}" ; exit 1' SIGINT | |
while true; do | |
#echo "target: $target trymin: $trymin trymax: $trymax" | |
# the above are indexes, this is the version string | |
target_v="${versions[$target]}" | |
echo -ne "Going to check against version ${reset}${target_v}${purple}" | |
a_priori= | |
if [[ " ${priors[@]} " =~ " ${target_v} " ]]; then | |
a_priori=1 | |
echo -e ", which already exists locally.${reset}" | |
else | |
echo -e ".${reset}" | |
rustup install "$target_v" | |
fi | |
echo | |
if if [[ $target > $checkindex ]]; then | |
rustup run "$target_v" cargo build | |
else | |
rustup run "$target_v" cargo check | |
fi; then | |
echo -e "\n${purple}Version ${reset}${target_v}${purple} is supported!" | |
trymax="$target" | |
target=$(((trymin - trymax) / 2 + trymax)) | |
if [[ $trymax == $target ]] || [[ $target_v == "1.0.0" ]]; then | |
echo "That's the earliest! We're done!" | |
cleanup | |
break | |
fi | |
else | |
echo -e "\n${purple}Version ${reset}${target_v}${purple} is not supported! See above for why." | |
trymin="$target" | |
target=$(((trymin - trymax) / 2 + trymax)) | |
fi | |
cleanup | |
done | |
echo -e "${reset}" |
This comment has been minimized.
This comment has been minimized.
parasyte
commented
Feb 12, 2019
•
Here's a patch to get this script working on macOS. (NOTE: I updated bash to version 5 to get --- rustup-bisect.txt 2019-02-12 14:27:47.000000000 -0800
+++ rustup-bisect 2019-02-12 14:31:22.000000000 -0800
@@ -11,7 +11,7 @@ releases_url="https://raw.githubusercont
mapfile -t versions < <(curl -s "$releases_url" \
| grep -v alpha \
- | grep -oP '^Version [1-9][\d.]+' \
+ | egrep -o '^Version [1-9][0-9.]+' \
| cut -d\ -f2)
# Before that, we have to use `cargo build`
@@ -21,7 +21,7 @@ n_versions=${#versions[@]}
echo -e "${purple}We know of ${reset}${n_versions}${purple} stable Rust versions."
mapfile -t priors < <(rustup toolchain list \
- | grep -oP '^[\d.]+')
+ | egrep -o '^[\d.]+')
echo -e "There are ${reset}${#priors[@]}${purple} past versions explicitly installed here."
@@ -129,3 +129,5 @@ while true; do
echo -e "${purple}"
fi
done
+
+echo -e "${reset}" |
This comment has been minimized.
This comment has been minimized.
@parasyte I merged those in, thank you! |
This comment has been minimized.
This comment has been minimized.
parasyte
commented
Jun 9, 2019
@passcod The latest change missed one of the required fixes to the regular expression for matching versions. I also decided to fix the toolchain uninstall when the script is interrupted. These changes are in my fork of the gist, making it a bit easier to contribute. :) |
This comment has been minimized.
This comment has been minimized.
Thank you! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
passcod commentedJan 25, 2019
Origin and demo: https://twitter.com/passcod/status/1088728138509479936