#!/usr/bin/env bash # 在线包的唯一环境准备入口;安装器后台启动,编译入口等待同一把锁。 set -euo pipefail package=$(cd -- "$(dirname -- "$0")/.." && pwd -P) tools="$package/toolchain" root=$(cd "$package/../.." && pwd -P) [[ ! -f $tools/ready ]] || exit 0 exec 9>"$root/.prepare.lock" previous= until flock -w 1 9; do status='Waiting for Dever environment preparation...' if [[ -f $tools/status ]]; then read -r status < "$tools/status" || true; fi if [[ $status != "$previous" ]]; then printf '%s\n' "$status" >&2; previous=$status; fi done [[ ! -f $tools/ready ]] || exit 0 exec 3>&2 exec >"$tools/prepare.log" 2>&1 stage= rust_stage= phase='Preparing Dever environment' finish() { local code=$? if (( code )); then printf 'Failed: %s (exit %s). Details: %s\n' "$phase" "$code" "$tools/prepare.log" > "$tools/status" cat "$tools/status" >&3 fi if [[ -n $stage ]]; then rm -rf -- "$stage"; fi if [[ -n $rust_stage ]]; then rm -rf -- "$rust_stage"; fi } trap finish EXIT trap 'exit 130' INT trap 'exit 143' TERM progress() { phase=$1 printf '%s\n' "$phase" > "$tools/status" printf '%s\n' "$phase" >&3 } read -r rust_version native_id < "$tools/online" mapfile -t sources < "$tools/sources" release_url=${sources[0]} rust_dist=${sources[1]} triple=x86_64-unknown-linux-gnu rust_root="$root/toolchains/rust-$rust_version-$triple" native_root="$root/toolchains/native-$native_id" downloads="$root/cache/downloads" mkdir -p "$downloads" stage=$(mktemp -d "$root/.prepare.XXXXXX") transfers=() archives=() queue() { local url=$1 name=$2 archives+=("$name") if (( ${#transfers[@]} )); then transfers+=(--next); fi transfers+=(--fail --location --silent --show-error --retry 2 --connect-timeout 15 --speed-limit 1024 --speed-time 60 --continue-at - --output "$downloads/$name.part" "$url") transfers+=(--next --fail --location --silent --show-error --retry 2 --connect-timeout 15 --output "$downloads/$name.sha256" "$url.sha256") } native_archive="dever-native-linux-x86_64-$native_id.tar.xz" if [[ ! -d $native_root ]]; then queue "$release_url/$native_archive" "$native_archive"; fi if [[ ! -d $rust_root ]]; then for component in rustc rust-std cargo; do name="$component-$rust_version-$triple.tar.xz" queue "$rust_dist/dist/$name" "$name" done fi if (( ${#archives[@]} )); then progress 'Downloading Dever build environment...' curl --parallel --parallel-immediate --parallel-max 3 --fail-early "${transfers[@]}" progress 'Verifying Dever build environment...' for name in "${archives[@]}"; do read -r expected remainder < "$downloads/$name.sha256" if [[ $name == "$native_archive" && $expected != "$native_id" ]] || ! printf '%s %s\n' "$expected" "$downloads/$name.part" | sha256sum --check --status; then rm -f -- "$downloads/$name.part" "$downloads/$name.sha256" echo "Checksum mismatch: $name" >&2 exit 1 fi done fi progress 'Installing Dever build environment...' if [[ ! -d $rust_root ]]; then # 官方脚本不支持含空格的 prefix;先在独占临时目录安装,再原子发布。 rust_stage=$(mktemp -d /tmp/dever-toolchain.XXXXXX) for component in rustc rust-std cargo; do name="$component-$rust_version-$triple" tar -xJf "$downloads/$name.tar.xz.part" -C "$rust_stage" bash "$rust_stage/$name/install.sh" --prefix="$rust_stage/toolchain" --disable-ldconfig rm -rf -- "$rust_stage/$name" done mv "$rust_stage/toolchain" "$stage/rust" mv "$stage/rust" "$rust_root" fi if [[ ! -d $native_root ]]; then tar -xJf "$downloads/$native_archive.part" -C "$stage" mv "$stage/native-tools" "$native_root" fi "$tools/bin/rustc" --version progress 'Preparing Dever project dependencies...' "$tools/bin/cargo" fetch --locked --target "$triple" --manifest-path "$tools/project/Cargo.toml" for name in "$native_archive" "rustc-$rust_version-$triple.tar.xz" \ "rust-std-$rust_version-$triple.tar.xz" "cargo-$rust_version-$triple.tar.xz"; do rm -f -- "$downloads/$name.part" "$downloads/$name.sha256" done touch "$tools/ready" progress 'Dever build environment is ready.'