#!/usr/bin/env bash
#
# Single source of truth for the SwiftPM scratch (build) directory, keyed by where the
# build is running. Prints the flags to append to `swift build/run/test` — empty on the
# host, a `--scratch-path <dir>` redirect on the macOS VM.
#
# Why this exists
# ---------------
# SwiftPM and the SwiftBuild backend bake the repository's ABSOLUTE path into the build
# tree — build.db, the *.yaml manifests, manifest.pif, everything under
# .build/out/Intermediates.noindex/XCBuildData, and the per-file `.d` dependency lists all
# contain fully-qualified source paths. That is fine until the SAME checkout is reachable
# at more than one absolute path, which is exactly our situation:
#
#     host / sandbox container : /Users/<user>/.nucleic/control/.../trunk
#     per-session macOS VM     : /Volumes/My Shared Files/workspace   (virtio-fs share of the trunk)
#
# Both mount points see one physical .build/ (it lives inside the shared trunk). The moment
# a build runs from the second mount, the embedded paths stop matching the current location:
# incremental builds thrash or fail outright, and you end up with a .build/ that contains a
# mix of /Users/... and "/Volumes/My Shared Files/..." strings (grep it — that mixture is
# the smoking gun of a poisoned cache). On the VM there is a second cost: driving every
# object file through the virtio-fs share is far slower than the guest's own disk.
#
# The fix
# -------
# Give each mount point its own scratch tree:
#   * Host / container  -> the default in-repo .build/ (this script prints nothing, so the
#                          existing `swift build` behaviour is untouched — zero risk).
#   * macOS VM (/Volumes) -> a scratch tree on the GUEST's local disk under $HOME, keyed by a
#                          hash of the mount path so distinct shares/worktrees never collide.
#
# This is the general recipe for "build artifact embeds a host path that differs across
# VM/sandbox mounts": don't try to rewrite the baked-in paths after the fact — instead put
# the artifact where its embedded path will be stable, one location per mount namespace.
#
# Escape hatch: export NUCLEIC_SCRATCH_PATH=/some/dir to force a specific scratch directory
# (useful for a throwaway build, or to pin the VM tree somewhere other than $HOME).
#
# Usage
#   SCRATCH_ARGS="$(bash scripts/lib/build-scratch.sh)" # "" or "--scratch-path /…/<hash>"
#   swift build $SCRATCH_ARGS ...                       # leave $SCRATCH_ARGS UNQUOTED
#   swift build $SCRATCH_ARGS --show-bin-path           # …and pass it to --show-bin-path too
#
# Takes the repo/working root as $1 (defaults to $PWD). Emits nothing but the flags on
# stdout, so it is safe to capture in `$(...)`.

set -euo pipefail

root="${1:-$PWD}"

# Explicit override always wins.
if [ -n "${NUCLEIC_SCRATCH_PATH:-}" ]; then
  printf -- '--scratch-path %s' "$NUCLEIC_SCRATCH_PATH"
  exit 0
fi

case "$root" in
  /Volumes/*)
    # On the VM share: redirect onto the guest's own fast, private disk. Hash the mount
    # path so two shares mounted at different points get independent trees.
    if command -v shasum >/dev/null 2>&1; then
      tag="$(printf '%s' "$root" | shasum | cut -c1-12)"
    else
      tag="$(printf '%s' "$root" | sha1sum | cut -c1-12)"
    fi
    printf -- '--scratch-path %s/.nucleic-scratch/%s' "${HOME:-/tmp}" "$tag"
    ;;
  *)
    # Host / sandbox container: keep the default in-repo .build/. Print nothing.
    :
    ;;
esac
