Files
RedBear-OS/local/scripts/warm-cargo-offline-cache.sh
T
vasilito 63614382d6 feat: add offline cargo cache warmer and SDDM/virgl QEMU harness
warm-cargo-offline-cache.sh: builds run cargo with --offline --locked, so
resolution comes from the sparse-index CACHE, which only an online cargo
run refreshes. A lockfile can pin a version whose .crate is already
downloaded while the index cache does not list it, producing

  error: failed to select a version for the requirement quinn = ^0.11.1
         (locked to 0.11.11)
  candidate versions found which didn't match: 0.11.9

on a dependency that is in fact present. 13 lockfiles were missing 42
crates this way. --check reports offending manifests without fetching.

test-sddm-virgl-qemu.sh: boots redbear-full on virtio-gpu-gl with
egl-headless so the guest takes the accelerated redox-drm -> Mesa (virgl)
-> Wayland path, captures the serial console and classifies each boot
marker independently rather than collapsing to pass/fail.
2026-08-03 09:09:56 +03:00

127 lines
4.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# warm-cargo-offline-cache.sh — make every Rust recipe/fork resolvable OFFLINE.
#
# WHY THIS EXISTS
#
# Red Bear builds are offline by default (COOKBOOK_OFFLINE=true), so the
# cookbook invokes cargo with `--offline --locked`. In that mode cargo resolves
# dependencies purely from the local registry, and — critically — from the
# *sparse index cache* under
# ~/.cargo/registry/index/<registry>/.cache/. That cache is only refreshed by an
# ONLINE cargo invocation.
#
# The failure mode is silent and confusing: a Cargo.lock can pin a version that
# is present in ~/.cargo/registry/cache as a .crate file, while the index cache
# entry is older and does not list it. Cargo then reports
#
# error: failed to select a version for the requirement `quinn = "^0.11.1"`
# (locked to 0.11.11)
# candidate versions found which didn't match: 0.11.9
#
# even though quinn-0.11.11.crate is sitting in the cache. The build fails on a
# dependency that is, in fact, already downloaded.
#
# Running this script once while online makes every lockfile-pinned version
# visible to the offline resolver. Run it after any lockfile change, after
# `bump-release.sh`, or when provisioning a new build host.
#
# It is READ-ONLY with respect to the repo: `cargo fetch --locked` populates
# ~/.cargo but never edits Cargo.lock (--locked makes cargo fail rather than
# update a lockfile).
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
cd "$PROJECT_ROOT"
usage() {
cat <<'USAGE'
Usage: warm-cargo-offline-cache.sh [--check] [--timeout SECONDS]
--check Do not fetch; only report which manifests FAIL to resolve
offline. Exits non-zero if any do. Safe with no network.
--timeout SECONDS Per-manifest timeout (default 300).
Covers every Cargo.toml that the build drives directly:
local/sources/*/ (Cat 2 upstream forks)
local/recipes/*/*/source/ (Cat 1 in-house crates + vendored Rust)
USAGE
}
check_only=0
per_timeout=300
while [[ $# -gt 0 ]]; do
case "$1" in
--help|-h) usage; exit 0 ;;
--check) check_only=1 ;;
--timeout) shift; per_timeout="${1:?--timeout requires seconds}" ;;
--timeout=*) per_timeout="${1#*=}" ;;
*) echo "ERROR: unsupported argument $1" >&2; usage >&2; exit 1 ;;
esac
shift
done
mapfile -t manifests < <(
{
find local/sources -maxdepth 2 -name Cargo.toml 2>/dev/null
find local/recipes -maxdepth 4 -path '*/source/Cargo.toml' 2>/dev/null
} | sort -u
)
if [[ "${#manifests[@]}" -eq 0 ]]; then
echo "ERROR: no Cargo manifests found under local/sources or local/recipes" >&2
exit 1
fi
echo ">>> ${#manifests[@]} Rust manifest(s) to verify"
failed=0
fixed=0
skipped=0
for m in "${manifests[@]}"; do
# A manifest with no lockfile is resolved as part of a parent workspace;
# fetching it standalone is meaningless.
lock_dir="$(dirname "$m")"
if [[ ! -f "$lock_dir/Cargo.lock" ]]; then
skipped=$((skipped + 1))
continue
fi
if timeout "$per_timeout" cargo metadata --offline --locked \
--manifest-path "$m" --format-version 1 >/dev/null 2>&1; then
continue
fi
if [[ "$check_only" -eq 1 ]]; then
echo " OFFLINE-FAIL $m"
failed=$((failed + 1))
continue
fi
echo " warming $m"
if timeout "$per_timeout" cargo fetch --locked --manifest-path "$m" >/dev/null 2>&1 \
&& timeout "$per_timeout" cargo metadata --offline --locked \
--manifest-path "$m" --format-version 1 >/dev/null 2>&1; then
fixed=$((fixed + 1))
else
echo " STILL-FAIL $m"
failed=$((failed + 1))
fi
done
echo ">>> skipped (no own lockfile): $skipped"
if [[ "$check_only" -eq 1 ]]; then
if [[ "$failed" -gt 0 ]]; then
echo ">>> $failed manifest(s) will FAIL an offline build."
echo ">>> Fix: run this script without --check while online."
exit 1
fi
echo ">>> All manifests resolve offline."
exit 0
fi
echo ">>> warmed: $fixed, still failing: $failed"
[[ "$failed" -eq 0 ]] || exit 1
echo ">>> Offline cargo resolution is complete for every Rust manifest."