36 lines
1.4 KiB
Bash
Executable File
36 lines
1.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
SOURCE_DIR=${1:?usage: ensure-rust-toolchain.sh SOURCE_DIR}
|
|
[[ -r "$SOURCE_DIR/Cargo.toml" ]] || { echo "missing Cargo.toml: $SOURCE_DIR" >&2; exit 1; }
|
|
metadata=$(python3.11 - "$SOURCE_DIR" <<'PY'
|
|
import pathlib, re, sys, tomllib
|
|
root=pathlib.Path(sys.argv[1])
|
|
manifest=tomllib.loads((root/'Cargo.toml').read_text())
|
|
minimum=manifest.get('package',{}).get('rust-version','')
|
|
pinned=''
|
|
p=root/'rust-toolchain.toml'
|
|
if p.exists(): pinned=tomllib.loads(p.read_text()).get('toolchain',{}).get('channel','')
|
|
if minimum and not re.fullmatch(r'[0-9]+\.[0-9]+(?:\.[0-9]+)?', minimum): raise SystemExit('unsupported rust-version')
|
|
if pinned and not (pinned=='stable' or re.fullmatch(r'[0-9]+\.[0-9]+(?:\.[0-9]+)?', pinned)): raise SystemExit('unsupported rust-toolchain channel')
|
|
print(minimum)
|
|
print(pinned)
|
|
PY
|
|
)
|
|
mapfile -t requested <<< "$metadata"
|
|
minimum=${requested[0]:-}
|
|
channel=${requested[1]:-stable}
|
|
[[ -n "$channel" ]] || channel=stable
|
|
if ! rustup run "$channel" rustc --version >/dev/null 2>&1; then
|
|
echo "installing Rust toolchain $channel" >&2
|
|
rustup toolchain install "$channel" --profile minimal >&2
|
|
fi
|
|
installed=$(rustup run "$channel" rustc --version | awk '{print $2}')
|
|
if [[ -n "$minimum" ]]; then
|
|
lowest=$(printf '%s\n%s\n' "$installed" "$minimum" | sort -V | head -n1)
|
|
if [[ "$lowest" != "$minimum" ]]; then
|
|
echo "Rust $installed does not satisfy project MSRV $minimum" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
printf '%s\n' "$channel"
|