| 1 | #!/bin/sh |
| 2 | # Portable opt-in Cargo cache topology for Codewhale worktrees. |
| 3 | # |
| 4 | # Isolated per-workspace intermediates (Cargo build-dir + {workspace-path-hash}) |
| 5 | # plus optional shared sccache. Never hard-codes a machine path. Does not |
| 6 | # change product behavior. This file is safe to source from other /bin/sh |
| 7 | # helpers; the CLI path is the only one that calls `set -eu` and `exit`. |
| 8 | # |
| 9 | # Usage: |
| 10 | # . scripts/dev-cache.sh && codewhale_dev_cache_apply |
| 11 | # scripts/dev-cache.sh --status |
| 12 | # scripts/dev-cache.sh --self-check |
| 13 | # scripts/dev-cache.sh --print-exports |
| 14 | # scripts/dev-cache.sh --help |
| 15 | # |
| 16 | # Environment: |
| 17 | # CODEWHALE_CACHE_ROOT cache root (default: |
| 18 | # ${XDG_CACHE_HOME:-$HOME/.cache}/codewhale) |
| 19 | # CODEWHALE_DEV_CACHE auto|1|force|local|0 (default auto) |
| 20 | # auto/1/force = isolated build-dir (still |
| 21 | # respects an already-set |
| 22 | # CARGO_TARGET_DIR / CARGO_BUILD_BUILD_DIR) |
| 23 | # local = keep compiling into ./target |
| 24 | # 0 = do nothing |
| 25 | # CODEWHALE_SCCACHE auto|1|0 (default auto) |
| 26 | # auto = wrap rustc only when incremental is |
| 27 | # already off and sccache is on PATH |
| 28 | # 1 = request CARGO_INCREMENTAL=0 (unless |
| 29 | # the caller already set it to on) and |
| 30 | # wrap if sccache exists |
| 31 | # 0 = never wrap |
| 32 | # CODEWHALE_DEV_CACHE_QUIET 1 to suppress the one-line status |
| 33 | # CODEWHALE_DEV_CACHE_REPO_ROOT |
| 34 | # workspace root used for ./target detection |
| 35 | # (default: $PWD) |
| 36 | # CODEWHALE_RUSTC_COMMIT override the rustc commit used to namespace |
| 37 | # SCCACHE_DIR (tests / offline hosts) |
| 38 | # |
| 39 | # sccache cannot cache incremental units. This helper never enables the |
| 40 | # wrapper while CARGO_INCREMENTAL is on, and it never turns incremental off |
| 41 | # unless CODEWHALE_SCCACHE=1. Everyday edits stay on cargo's incremental |
| 42 | # default. New-worktree / CI-like rebuilds that already set |
| 43 | # CARGO_INCREMENTAL=0 get the measured shared-compiler-output path. |
| 44 | |
| 45 | codewhale_dev_cache_truthy() { |
| 46 | case ${1:-} in |
| 47 | 1|true|yes|on|force) return 0 ;; |
| 48 | *) return 1 ;; |
| 49 | esac |
| 50 | } |
| 51 | |
| 52 | codewhale_dev_cache_falsey() { |
| 53 | case ${1:-} in |
| 54 | 0|false|no|off|never|disabled) return 0 ;; |
| 55 | *) return 1 ;; |
| 56 | esac |
| 57 | } |
| 58 | |
| 59 | codewhale_dev_cache_root() { |
| 60 | if [ -n "${CODEWHALE_CACHE_ROOT:-}" ]; then |
| 61 | printf '%s\n' "$CODEWHALE_CACHE_ROOT" |
| 62 | return |
| 63 | fi |
| 64 | if [ -n "${XDG_CACHE_HOME:-}" ]; then |
| 65 | printf '%s\n' "$XDG_CACHE_HOME/codewhale" |
| 66 | return |
| 67 | fi |
| 68 | if [ -n "${HOME:-}" ]; then |
| 69 | printf '%s\n' "$HOME/.cache/codewhale" |
| 70 | return |
| 71 | fi |
| 72 | printf '%s\n' "${TMPDIR:-/tmp}/codewhale-cache" |
| 73 | } |
| 74 | |
| 75 | codewhale_dev_cache_repo_root() { |
| 76 | if [ -n "${CODEWHALE_DEV_CACHE_REPO_ROOT:-}" ]; then |
| 77 | printf '%s\n' "$CODEWHALE_DEV_CACHE_REPO_ROOT" |
| 78 | return |
| 79 | fi |
| 80 | pwd |
| 81 | } |
| 82 | |
| 83 | codewhale_dev_cache_rustc_commit() { |
| 84 | if [ -n "${CODEWHALE_RUSTC_COMMIT:-}" ]; then |
| 85 | printf '%s\n' "$CODEWHALE_RUSTC_COMMIT" |
| 86 | return |
| 87 | fi |
| 88 | # rustc -vV is cheap and does not start a compile. |
| 89 | _cw_out=$(rustc -vV 2>/dev/null || true) |
| 90 | _cw_commit=$(printf '%s\n' "$_cw_out" | awk '/^commit-hash:/{print $2; exit}') |
| 91 | if [ -n "$_cw_commit" ]; then |
| 92 | printf '%s\n' "$_cw_commit" |
| 93 | else |
| 94 | printf '%s\n' "unknown" |
| 95 | fi |
| 96 | } |
| 97 | |
| 98 | codewhale_dev_cache_cargo_version_mm() { |
| 99 | # cargo 1.97.0 -> 1097. Empty if cargo is missing or unparsable. |
| 100 | cargo --version 2>/dev/null | awk '{ |
| 101 | split($2, a, ".") |
| 102 | if (a[1] ~ /^[0-9]+$/ && a[2] ~ /^[0-9]+$/) |
| 103 | printf "%d\n", a[1]*1000+a[2] |
| 104 | }' |
| 105 | } |
| 106 | |
| 107 | # Stable 16-hex-char fingerprint of a path. Used only for the pre-1.91 |
| 108 | # CARGO_TARGET_DIR fallback; Cargo 1.91+ expands {workspace-path-hash}. |
| 109 | codewhale_dev_cache_path_fingerprint() { |
| 110 | if command -v sha256sum >/dev/null 2>&1; then |
| 111 | printf '%s' "$1" | sha256sum | awk '{print substr($1,1,16)}' |
| 112 | elif command -v shasum >/dev/null 2>&1; then |
| 113 | printf '%s' "$1" | shasum -a 256 | awk '{print substr($1,1,16)}' |
| 114 | elif command -v openssl >/dev/null 2>&1; then |
| 115 | printf '%s' "$1" | openssl dgst -sha256 | awk '{print substr($NF,1,16)}' |
| 116 | else |
| 117 | printf '%s' "$1" | cksum | awk '{printf "%s%08s\n", $1, $2}' | tr ' ' '0' |
| 118 | fi |
| 119 | } |
| 120 | |
| 121 | codewhale_dev_cache_incremental_off() { |
| 122 | case ${CARGO_INCREMENTAL:-} in |
| 123 | 0|false|no|off) return 0 ;; |
| 124 | *) return 1 ;; |
| 125 | esac |
| 126 | } |
| 127 | |
| 128 | codewhale_dev_cache_incremental_on() { |
| 129 | case ${CARGO_INCREMENTAL:-} in |
| 130 | 1|true|yes|on) return 0 ;; |
| 131 | *) return 1 ;; |
| 132 | esac |
| 133 | } |
| 134 | |
| 135 | codewhale_dev_cache_sccache_bin() { |
| 136 | command -v sccache 2>/dev/null || true |
| 137 | } |
| 138 | |
| 139 | codewhale_dev_cache_log() { |
| 140 | if [ "${CODEWHALE_DEV_CACHE_QUIET:-}" = 1 ]; then |
| 141 | return 0 |
| 142 | fi |
| 143 | printf 'dev-cache: %s\n' "$*" >&2 |
| 144 | } |
| 145 | |
| 146 | # Free space (in GiB, integer, truncated) on the filesystem holding $1, or |
| 147 | # empty when it cannot be determined. `df -Pk` is the POSIX-portable form and |
| 148 | # behaves the same on macOS and Linux. |
| 149 | codewhale_dev_cache_free_gib() { |
| 150 | _cw_probe=$1 |
| 151 | # Walk up to the nearest existing ancestor: the cache root usually does not |
| 152 | # exist yet on a first run, and df needs a real path. |
| 153 | while [ -n "$_cw_probe" ] && [ ! -d "$_cw_probe" ]; do |
| 154 | _cw_parent=$(dirname -- "$_cw_probe") |
| 155 | [ "$_cw_parent" = "$_cw_probe" ] && break |
| 156 | _cw_probe=$_cw_parent |
| 157 | done |
| 158 | [ -d "$_cw_probe" ] || return 0 |
| 159 | df -Pk -- "$_cw_probe" 2>/dev/null | awk 'NR==2 { print int($4 / 1048576) }' |
| 160 | } |
| 161 | |
| 162 | # A cold workspace build-dir is ~6 GB, and cargo writes it incrementally, so a |
| 163 | # volume that runs out mid-build leaves a half-written cache and a failed run. |
| 164 | # Worse, on the host where this was added the low volume was also $TMPDIR's: |
| 165 | # the shell tool's spill `tempfile` fails on a full disk, which is the exact |
| 166 | # wedge #5465 was filed for. Warn before the build starts rather than after it |
| 167 | # dies, and name the override that fixes it. |
| 168 | CODEWHALE_DEV_CACHE_MIN_FREE_GIB=${CODEWHALE_DEV_CACHE_MIN_FREE_GIB:-15} |
| 169 | |
| 170 | codewhale_dev_cache_warn_low_space() { |
| 171 | _cw_root=$1 |
| 172 | _cw_free=$(codewhale_dev_cache_free_gib "$_cw_root") |
| 173 | [ -n "$_cw_free" ] || return 0 |
| 174 | [ "$_cw_free" -lt "$CODEWHALE_DEV_CACHE_MIN_FREE_GIB" ] || return 0 |
| 175 | codewhale_dev_cache_log \ |
| 176 | "WARNING: only ${_cw_free}GiB free on the volume holding ${_cw_root}; a cold build-dir is ~6GB." |
| 177 | codewhale_dev_cache_log \ |
| 178 | " Set CODEWHALE_CACHE_ROOT=<dir on a roomier volume> (threshold: CODEWHALE_DEV_CACHE_MIN_FREE_GIB)." |
| 179 | } |
| 180 | |
| 181 | # Apply the topology to the current shell. Idempotent. Never overrides an |
| 182 | # already-set CARGO_TARGET_DIR, CARGO_BUILD_BUILD_DIR, RUSTC_WRAPPER, or |
| 183 | # SCCACHE_DIR. |
| 184 | codewhale_dev_cache_apply() { |
| 185 | CODEWHALE_DEV_CACHE_MODE=${CODEWHALE_DEV_CACHE_MODE:-} |
| 186 | # Re-entry after a previous apply in this shell: keep the first decision |
| 187 | # unless the caller unset the mode (tests do that between cases). |
| 188 | if [ -n "${CODEWHALE_DEV_CACHE_APPLIED:-}" ] && [ -n "${CODEWHALE_DEV_CACHE_MODE:-}" ]; then |
| 189 | return 0 |
| 190 | fi |
| 191 | |
| 192 | _cw_want=${CODEWHALE_DEV_CACHE:-auto} |
| 193 | _cw_root=$(codewhale_dev_cache_root) |
| 194 | _cw_sccache_want=${CODEWHALE_SCCACHE:-auto} |
| 195 | _cw_commit=$(codewhale_dev_cache_rustc_commit) |
| 196 | CODEWHALE_DEV_CACHE_SCCACHE_DIR=${SCCACHE_DIR:-${_cw_root}/sccache/${_cw_commit}} |
| 197 | CODEWHALE_DEV_CACHE_BUILD_DIR=${_cw_root}/build/'{workspace-path-hash}' |
| 198 | CODEWHALE_DEV_CACHE_LEGACY_TARGET_DIR=${_cw_root}/target/$(codewhale_dev_cache_path_fingerprint "$(codewhale_dev_cache_repo_root)") |
| 199 | |
| 200 | if codewhale_dev_cache_falsey "$_cw_want"; then |
| 201 | CODEWHALE_DEV_CACHE_MODE=disabled |
| 202 | CODEWHALE_DEV_CACHE_SCCACHE=disabled |
| 203 | CODEWHALE_DEV_CACHE_APPLIED=1 |
| 204 | export CODEWHALE_DEV_CACHE_MODE CODEWHALE_DEV_CACHE_SCCACHE |
| 205 | codewhale_dev_cache_log "disabled (CODEWHALE_DEV_CACHE=${_cw_want})" |
| 206 | return 0 |
| 207 | fi |
| 208 | |
| 209 | if [ -n "${CARGO_TARGET_DIR:-}" ]; then |
| 210 | CODEWHALE_DEV_CACHE_MODE=inherited-target-dir |
| 211 | elif [ -n "${CARGO_BUILD_BUILD_DIR:-}" ]; then |
| 212 | CODEWHALE_DEV_CACHE_MODE=inherited-build-dir |
| 213 | elif [ "$_cw_want" = local ]; then |
| 214 | # Explicit stay-in-./target. A stub target/ created by a previous |
| 215 | # isolated build-dir run is not a reason to abandon isolation: Cargo |
| 216 | # still writes CACHEDIR.TAG (and sometimes finals) under ./target |
| 217 | # when build-dir is split, and treating that as "warm" made the |
| 218 | # second command recompile everything into a second tree. |
| 219 | CODEWHALE_DEV_CACHE_MODE=existing-target |
| 220 | else |
| 221 | CODEWHALE_DEV_CACHE_MODE=isolated-build-dir |
| 222 | fi |
| 223 | |
| 224 | case $CODEWHALE_DEV_CACHE_MODE in |
| 225 | force-isolated|isolated-build-dir) |
| 226 | _cw_mm=$(codewhale_dev_cache_cargo_version_mm) |
| 227 | if [ -n "$_cw_mm" ] && [ "$_cw_mm" -lt 1091 ]; then |
| 228 | # Cargo 1.91 introduced build.build-dir. Older cargo only isolates |
| 229 | # via CARGO_TARGET_DIR; keep that fallback per-workspace. |
| 230 | if [ -z "${CARGO_TARGET_DIR:-}" ]; then |
| 231 | CARGO_TARGET_DIR=$CODEWHALE_DEV_CACHE_LEGACY_TARGET_DIR |
| 232 | export CARGO_TARGET_DIR |
| 233 | fi |
| 234 | CODEWHALE_DEV_CACHE_MODE=${CODEWHALE_DEV_CACHE_MODE}-legacy-target-dir |
| 235 | else |
| 236 | CARGO_BUILD_BUILD_DIR=$CODEWHALE_DEV_CACHE_BUILD_DIR |
| 237 | export CARGO_BUILD_BUILD_DIR |
| 238 | mkdir -p "$_cw_root/build" 2>/dev/null || true |
| 239 | fi |
| 240 | ;; |
| 241 | esac |
| 242 | |
| 243 | # sccache: never wrap incremental rustc. Missing binary is a fallback, |
| 244 | # not an error. |
| 245 | if codewhale_dev_cache_falsey "$_cw_sccache_want"; then |
| 246 | CODEWHALE_DEV_CACHE_SCCACHE=disabled |
| 247 | elif [ -n "${RUSTC_WRAPPER:-}" ]; then |
| 248 | case $RUSTC_WRAPPER in |
| 249 | *sccache*) CODEWHALE_DEV_CACHE_SCCACHE=external-sccache ;; |
| 250 | *) CODEWHALE_DEV_CACHE_SCCACHE=external-wrapper ;; |
| 251 | esac |
| 252 | else |
| 253 | if codewhale_dev_cache_truthy "$_cw_sccache_want" && ! codewhale_dev_cache_incremental_on; then |
| 254 | # Request the measured new-worktree / CI-like topology. |
| 255 | if [ -z "${CARGO_INCREMENTAL:-}" ]; then |
| 256 | CARGO_INCREMENTAL=0 |
| 257 | export CARGO_INCREMENTAL |
| 258 | fi |
| 259 | fi |
| 260 | if ! codewhale_dev_cache_incremental_off; then |
| 261 | CODEWHALE_DEV_CACHE_SCCACHE=skipped-incremental |
| 262 | else |
| 263 | _cw_bin=$(codewhale_dev_cache_sccache_bin) |
| 264 | if [ -z "$_cw_bin" ]; then |
| 265 | CODEWHALE_DEV_CACHE_SCCACHE=not-found |
| 266 | else |
| 267 | RUSTC_WRAPPER=$_cw_bin |
| 268 | export RUSTC_WRAPPER |
| 269 | if [ -z "${SCCACHE_DIR:-}" ]; then |
| 270 | SCCACHE_DIR=$CODEWHALE_DEV_CACHE_SCCACHE_DIR |
| 271 | export SCCACHE_DIR |
| 272 | fi |
| 273 | mkdir -p "$SCCACHE_DIR" 2>/dev/null || true |
| 274 | CODEWHALE_DEV_CACHE_SCCACHE=enabled |
| 275 | fi |
| 276 | fi |
| 277 | fi |
| 278 | |
| 279 | CODEWHALE_DEV_CACHE_APPLIED=1 |
| 280 | export CODEWHALE_DEV_CACHE_MODE CODEWHALE_DEV_CACHE_SCCACHE |
| 281 | export CODEWHALE_DEV_CACHE_SCCACHE_DIR |
| 282 | |
| 283 | _cw_line="mode=${CODEWHALE_DEV_CACHE_MODE} sccache=${CODEWHALE_DEV_CACHE_SCCACHE}" |
| 284 | case $CODEWHALE_DEV_CACHE_MODE in |
| 285 | isolated-build-dir*|force-isolated*) |
| 286 | _cw_line="${_cw_line} build-dir=${CARGO_BUILD_BUILD_DIR:-${CARGO_TARGET_DIR:-unset}}" |
| 287 | ;; |
| 288 | inherited-target-dir) |
| 289 | _cw_line="${_cw_line} CARGO_TARGET_DIR=${CARGO_TARGET_DIR}" |
| 290 | ;; |
| 291 | inherited-build-dir) |
| 292 | _cw_line="${_cw_line} CARGO_BUILD_BUILD_DIR=${CARGO_BUILD_BUILD_DIR}" |
| 293 | ;; |
| 294 | existing-target) |
| 295 | _cw_line="${_cw_line} using ./target (CODEWHALE_DEV_CACHE=local)" |
| 296 | ;; |
| 297 | esac |
| 298 | if [ "${CODEWHALE_DEV_CACHE_SCCACHE}" = enabled ]; then |
| 299 | _cw_line="${_cw_line} SCCACHE_DIR=${SCCACHE_DIR} rustc=${_cw_commit}" |
| 300 | fi |
| 301 | codewhale_dev_cache_log "$_cw_line" |
| 302 | case $CODEWHALE_DEV_CACHE_MODE in |
| 303 | disabled|existing-target) ;; |
| 304 | *) codewhale_dev_cache_warn_low_space "$(codewhale_dev_cache_root)" ;; |
| 305 | esac |
| 306 | } |
| 307 | |
| 308 | codewhale_dev_cache_status() { |
| 309 | _cw_tmpl=${CODEWHALE_DEV_CACHE_BUILD_DIR:-} |
| 310 | if [ -z "$_cw_tmpl" ]; then |
| 311 | _cw_tmpl=$(codewhale_dev_cache_root)/build/'{workspace-path-hash}' |
| 312 | fi |
| 313 | printf '%s\n' \ |
| 314 | "cache_root=$(codewhale_dev_cache_root)" \ |
| 315 | "repo_root=$(codewhale_dev_cache_repo_root)" \ |
| 316 | "mode=${CODEWHALE_DEV_CACHE_MODE:-unset}" \ |
| 317 | "sccache=${CODEWHALE_DEV_CACHE_SCCACHE:-unset}" \ |
| 318 | "build_dir_template=${_cw_tmpl}" \ |
| 319 | "CARGO_BUILD_BUILD_DIR=${CARGO_BUILD_BUILD_DIR:-<unset>}" \ |
| 320 | "CARGO_TARGET_DIR=${CARGO_TARGET_DIR:-<unset>}" \ |
| 321 | "CARGO_INCREMENTAL=${CARGO_INCREMENTAL:-<unset>}" \ |
| 322 | "RUSTC_WRAPPER=${RUSTC_WRAPPER:-<unset>}" \ |
| 323 | "SCCACHE_DIR=${SCCACHE_DIR:-<unset>}" \ |
| 324 | "rustc_commit=$(codewhale_dev_cache_rustc_commit)" \ |
| 325 | "sccache_bin=$(codewhale_dev_cache_sccache_bin)" |
| 326 | } |
| 327 | |
| 328 | # Extra cargo CLI flags that force template expansion of build-dir. |
| 329 | # CARGO_BUILD_BUILD_DIR is still exported for nested tools; --config is |
| 330 | # what Cargo documents as supporting {workspace-path-hash}. |
| 331 | codewhale_dev_cache_exec_cargo() { |
| 332 | case ${CODEWHALE_DEV_CACHE_MODE:-} in |
| 333 | isolated-build-dir|force-isolated) |
| 334 | if [ -n "${CARGO_BUILD_BUILD_DIR:-}" ]; then |
| 335 | exec cargo --config "build.build-dir = \"${CARGO_BUILD_BUILD_DIR}\"" "$@" |
| 336 | fi |
| 337 | ;; |
| 338 | esac |
| 339 | exec cargo "$@" |
| 340 | } |
| 341 | |
| 342 | codewhale_dev_cache_print_exports() { |
| 343 | [ -n "${CARGO_BUILD_BUILD_DIR:-}" ] && printf 'export CARGO_BUILD_BUILD_DIR=%s\n' "$CARGO_BUILD_BUILD_DIR" |
| 344 | [ -n "${CARGO_TARGET_DIR:-}" ] && printf 'export CARGO_TARGET_DIR=%s\n' "$CARGO_TARGET_DIR" |
| 345 | [ -n "${CARGO_INCREMENTAL:-}" ] && printf 'export CARGO_INCREMENTAL=%s\n' "$CARGO_INCREMENTAL" |
| 346 | [ -n "${RUSTC_WRAPPER:-}" ] && printf 'export RUSTC_WRAPPER=%s\n' "$RUSTC_WRAPPER" |
| 347 | [ -n "${SCCACHE_DIR:-}" ] && printf 'export SCCACHE_DIR=%s\n' "$SCCACHE_DIR" |
| 348 | [ -n "${CODEWHALE_DEV_CACHE_MODE:-}" ] && printf 'export CODEWHALE_DEV_CACHE_MODE=%s\n' "$CODEWHALE_DEV_CACHE_MODE" |
| 349 | [ -n "${CODEWHALE_DEV_CACHE_SCCACHE:-}" ] && printf 'export CODEWHALE_DEV_CACHE_SCCACHE=%s\n' "$CODEWHALE_DEV_CACHE_SCCACHE" |
| 350 | } |
| 351 | |
| 352 | codewhale_dev_cache_self_check() { |
| 353 | _cw_fail=0 |
| 354 | _cw_root=$(codewhale_dev_cache_root) |
| 355 | _cw_home=${HOME:-} |
| 356 | _cw_xdg=${XDG_CACHE_HOME:-} |
| 357 | |
| 358 | if [ -z "${CODEWHALE_CACHE_ROOT:-}" ]; then |
| 359 | if [ -n "$_cw_xdg" ]; then |
| 360 | case $_cw_root in |
| 361 | "$_cw_xdg"/codewhale) ;; |
| 362 | *) |
| 363 | printf 'self-check: expected XDG default %s/codewhale, got %s\n' "$_cw_xdg" "$_cw_root" >&2 |
| 364 | _cw_fail=1 |
| 365 | ;; |
| 366 | esac |
| 367 | elif [ -n "$_cw_home" ]; then |
| 368 | case $_cw_root in |
| 369 | "$_cw_home"/.cache/codewhale) ;; |
| 370 | *) |
| 371 | printf 'self-check: expected HOME default %s/.cache/codewhale, got %s\n' "$_cw_home" "$_cw_root" >&2 |
| 372 | _cw_fail=1 |
| 373 | ;; |
| 374 | esac |
| 375 | fi |
| 376 | fi |
| 377 | |
| 378 | case ${CARGO_BUILD_BUILD_DIR:-} in |
| 379 | *'{workspace-path-hash}'*) |
| 380 | ;; |
| 381 | '') |
| 382 | case ${CODEWHALE_DEV_CACHE_MODE:-} in |
| 383 | isolated-build-dir|force-isolated) |
| 384 | printf 'self-check: isolated mode did not set CARGO_BUILD_BUILD_DIR\n' >&2 |
| 385 | _cw_fail=1 |
| 386 | ;; |
| 387 | esac |
| 388 | ;; |
| 389 | *) |
| 390 | case ${CODEWHALE_DEV_CACHE_MODE:-} in |
| 391 | isolated-build-dir|force-isolated) |
| 392 | printf 'self-check: isolated build-dir lacks {workspace-path-hash}: %s\n' "$CARGO_BUILD_BUILD_DIR" >&2 |
| 393 | _cw_fail=1 |
| 394 | ;; |
| 395 | esac |
| 396 | ;; |
| 397 | esac |
| 398 | |
| 399 | if [ "${CODEWHALE_DEV_CACHE_SCCACHE:-}" = enabled ]; then |
| 400 | if ! codewhale_dev_cache_incremental_off; then |
| 401 | printf 'self-check: sccache enabled while incremental is not off\n' >&2 |
| 402 | _cw_fail=1 |
| 403 | fi |
| 404 | case ${RUSTC_WRAPPER:-} in |
| 405 | *sccache*) ;; |
| 406 | *) |
| 407 | printf 'self-check: sccache enabled but RUSTC_WRAPPER=%s\n' "${RUSTC_WRAPPER:-<unset>}" >&2 |
| 408 | _cw_fail=1 |
| 409 | ;; |
| 410 | esac |
| 411 | fi |
| 412 | |
| 413 | if [ "${CODEWHALE_DEV_CACHE_SCCACHE:-}" = not-found ]; then |
| 414 | if [ -n "${RUSTC_WRAPPER:-}" ]; then |
| 415 | printf 'self-check: missing sccache must not set RUSTC_WRAPPER (%s)\n' "$RUSTC_WRAPPER" >&2 |
| 416 | _cw_fail=1 |
| 417 | fi |
| 418 | fi |
| 419 | |
| 420 | if [ "$_cw_fail" -eq 0 ]; then |
| 421 | printf 'dev-cache: self-check ok\n' |
| 422 | return 0 |
| 423 | fi |
| 424 | printf 'dev-cache: self-check FAILED\n' >&2 |
| 425 | return 1 |
| 426 | } |
| 427 | |
| 428 | codewhale_dev_cache_usage() { |
| 429 | cat <<'EOF' |
| 430 | usage: scripts/dev-cache.sh --status|--self-check|--print-exports|--help |
| 431 | |
| 432 | Portable opt-in Cargo cache topology. Source this file and call |
| 433 | codewhale_dev_cache_apply from scripts/dev-test.sh / scripts/dev-cargo.sh. |
| 434 | |
| 435 | --status apply (if needed) and print key=value status |
| 436 | --self-check apply and check portable defaults / sccache fallback |
| 437 | --print-exports apply and print export statements for eval |
| 438 | --help this message |
| 439 | |
| 440 | Environment overrides are documented at the top of this file. Defaults |
| 441 | never contain a machine-specific absolute path. |
| 442 | EOF |
| 443 | } |
| 444 | |
| 445 | # CLI only when this file is the executed program, not when sourced. |
| 446 | case ${0##*/} in |
| 447 | dev-cache.sh) |
| 448 | set -eu |
| 449 | _cw_cmd=${1:---status} |
| 450 | case $_cw_cmd in |
| 451 | --status|-s) |
| 452 | codewhale_dev_cache_apply |
| 453 | codewhale_dev_cache_status |
| 454 | ;; |
| 455 | --self-check) |
| 456 | codewhale_dev_cache_apply |
| 457 | codewhale_dev_cache_status |
| 458 | codewhale_dev_cache_self_check |
| 459 | ;; |
| 460 | --print-exports) |
| 461 | codewhale_dev_cache_apply |
| 462 | codewhale_dev_cache_print_exports |
| 463 | ;; |
| 464 | --help|-h) |
| 465 | codewhale_dev_cache_usage |
| 466 | ;; |
| 467 | *) |
| 468 | codewhale_dev_cache_usage >&2 |
| 469 | exit 2 |
| 470 | ;; |
| 471 | esac |
| 472 | ;; |
| 473 | esac |
| 474 |