152 lines
5.1 KiB
Bash
152 lines
5.1 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# scripts/build-cleanup-script.sh
|
|
#
|
|
# Memory #30 reinforcement. Delta tarballs cannot communicate
|
|
# file DELETIONS — extracting `morphit-delta-cpNN.tar.gz` over an
|
|
# existing checkout adds + overwrites, never removes. cp82's
|
|
# sw.js (deleted in cp81) appeared in operator checkouts as a
|
|
# stale file until Ken's manual delete-and-re-extract workflow.
|
|
#
|
|
# This script generates a `cpNN-cleanup.sh` helper that operators
|
|
# run BEFORE extracting a delta tarball: it `rm -f`s every file
|
|
# that was deleted in the new commits. If no deletions occurred,
|
|
# the helper is not emitted (and the script exits 0 with a
|
|
# message saying "delta is safe; no cleanup needed").
|
|
#
|
|
# Usage:
|
|
#
|
|
# bash scripts/build-cleanup-script.sh [<from-ref>] [<to-ref>]
|
|
#
|
|
# Defaults: `HEAD~1` and `HEAD`. Override for multi-commit
|
|
# spans, e.g.:
|
|
#
|
|
# bash scripts/build-cleanup-script.sh v1.0.0-beta.1 v1.0.0-beta.2
|
|
#
|
|
# Output: writes `cp<NN>-cleanup.sh` to the current directory (or
|
|
# the directory named by `MORPHIT_CLEANUP_OUT_DIR`), where `<NN>`
|
|
# is taken from the most recent `Part 122 cp<NN>` mention in
|
|
# `TARBALL.md` if available, else from `git rev-parse --short
|
|
# <to-ref>`.
|
|
#
|
|
# Idempotent: emitted cleanup script uses `rm -f` (no-op if file
|
|
# already absent) so re-running cleanup after extraction is safe.
|
|
#
|
|
# Exit codes:
|
|
# 0 — cleanup emitted, OR no deletions (helper not emitted but
|
|
# run was successful — operator's delta is safe to extract
|
|
# directly)
|
|
# 1 — git not available, or refs invalid
|
|
|
|
set -euo pipefail
|
|
|
|
FROM_REF="${1:-HEAD~1}"
|
|
TO_REF="${2:-HEAD}"
|
|
OUT_DIR="${MORPHIT_CLEANUP_OUT_DIR:-.}"
|
|
|
|
# Pre-flight: git available?
|
|
if ! command -v git >/dev/null 2>&1; then
|
|
echo "ERROR: git not found in PATH. This script generates a cleanup" >&2
|
|
echo " helper from \`git diff --diff-filter=D\` output — it" >&2
|
|
echo " cannot run without git." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Pre-flight: are we inside a git work tree?
|
|
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
echo "ERROR: not inside a git work tree. cd to a Morphit clone first." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Pre-flight: refs valid?
|
|
if ! git rev-parse --verify "$FROM_REF" >/dev/null 2>&1; then
|
|
echo "ERROR: <from-ref> \`$FROM_REF\` is not a valid git ref." >&2
|
|
exit 1
|
|
fi
|
|
if ! git rev-parse --verify "$TO_REF" >/dev/null 2>&1; then
|
|
echo "ERROR: <to-ref> \`$TO_REF\` is not a valid git ref." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Determine checkpoint label. Prefer the most-recent `cp<NN>`
|
|
# mention in TARBALL.md (top of file is newest checkpoint per
|
|
# the standing "tarball at meaningful checkpoints" rule). Fall
|
|
# back to git short-SHA.
|
|
CP_LABEL=""
|
|
if [[ -f TARBALL.md ]]; then
|
|
CP_LABEL=$(grep -oE 'cp[0-9]+' TARBALL.md | head -1 || true)
|
|
fi
|
|
if [[ -z "$CP_LABEL" ]]; then
|
|
CP_LABEL="cp$(git rev-parse --short "$TO_REF")"
|
|
fi
|
|
|
|
# Collect deletions. `--diff-filter=D` keeps only entries whose
|
|
# status is "Deleted" between the two refs. `-z` would null-
|
|
# delimit the output for paths with spaces; we accept the
|
|
# limitation that Morphit paths don't contain spaces (verified
|
|
# at repo init).
|
|
DELETIONS=$(git diff --diff-filter=D --name-only "$FROM_REF" "$TO_REF")
|
|
|
|
if [[ -z "$DELETIONS" ]]; then
|
|
echo "No deletions between $FROM_REF..$TO_REF — delta is safe to extract directly."
|
|
echo "(No cleanup helper emitted.)"
|
|
exit 0
|
|
fi
|
|
|
|
DELETION_COUNT=$(echo "$DELETIONS" | wc -l | tr -d ' ')
|
|
OUT_FILE="$OUT_DIR/$CP_LABEL-cleanup.sh"
|
|
|
|
# Emit cleanup script. Uses `rm -f` (idempotent — no error if
|
|
# the file is already absent on the operator's box). Header
|
|
# documents what + why.
|
|
|
|
cat > "$OUT_FILE" <<HEADER
|
|
#!/usr/bin/env bash
|
|
#
|
|
# $CP_LABEL-cleanup.sh
|
|
#
|
|
# Autogenerated by \`scripts/build-cleanup-script.sh\` from
|
|
# \`git diff --diff-filter=D $FROM_REF..$TO_REF\`.
|
|
#
|
|
# Memory #30 (delta tarballs cannot communicate deletions):
|
|
# extracting the matching \`morphit-delta-$CP_LABEL.tar.gz\` over
|
|
# an existing checkout adds + overwrites files but never removes
|
|
# them. This helper removes the $DELETION_COUNT file(s) that
|
|
# were DELETED in $FROM_REF..$TO_REF, so the operator's checkout
|
|
# matches the upstream tree post-extract.
|
|
#
|
|
# Run BEFORE extracting the delta tarball:
|
|
#
|
|
# cd /path/to/morphit-clone
|
|
# bash $CP_LABEL-cleanup.sh
|
|
# tar xzf morphit-delta-$CP_LABEL.tar.gz
|
|
#
|
|
# Idempotent: safe to run multiple times. \`rm -f\` no-ops if
|
|
# the file is already absent.
|
|
|
|
set -eu
|
|
|
|
HEADER
|
|
|
|
while IFS= read -r path; do
|
|
# Defensive: skip empty lines (shouldn't happen but cheap).
|
|
[[ -z "$path" ]] && continue
|
|
# Hard-fail if a path contains a single-quote (would break
|
|
# the rm -f shell-quoting); the repo invariant is no such
|
|
# paths, so this is belt-and-braces.
|
|
if [[ "$path" == *"'"* ]]; then
|
|
echo "ERROR: path contains a single quote, cleanup script generation aborted:" >&2
|
|
echo " $path" >&2
|
|
rm -f "$OUT_FILE"
|
|
exit 1
|
|
fi
|
|
printf "rm -f '%s'\n" "$path" >> "$OUT_FILE"
|
|
done <<< "$DELETIONS"
|
|
|
|
cat >> "$OUT_FILE" <<FOOTER
|
|
|
|
echo "$CP_LABEL cleanup: $DELETION_COUNT file(s) removed."
|
|
FOOTER
|
|
|
|
chmod +x "$OUT_FILE"
|
|
echo "Emitted: $OUT_FILE ($DELETION_COUNT deletion(s) listed)"
|