# yah-source-ship <dir> — the attach return path (R969-F7). Commits <dir>, a
# checkout of the step's source snapshot, onto that snapshot and pushes it to
# the attach's return ref, where `qed.harvest` picks it up. qed hands this
# script to a debug forge as $YAH_SOURCE_SHIP; `yah qed exec <id> -- ship`
# runs it as
#
#     sh -c "$YAH_SOURCE_SHIP" yah-source-ship <dir>
#
#   $YAH_SOURCE_CONTEXT_URL  git+<remote>#<ref> — the remote to push to
#   $YAH_ATTACH_SNAPSHOT     the snapshot commit <dir> was checked out from
#   $YAH_RETURN_REF          where the result goes (refs/qed/<run>/<step>.return)
#   $YAH_RETURN_GIT_TOKEN    a git:write token, via GIT_CONFIG_* env — never argv
#
# The commit is built in the same node-persistent bare cache yah-source-fetch
# used, with a scratch index seeded from the snapshot, so ignored files stay
# out exactly as they did on the way in.
set -eu
dir="${1:?usage: yah-source-ship <dir>}"
fail() {
  echo "yah-source-ship: $1" >&2
  exit 1
}
url="${YAH_SOURCE_CONTEXT_URL:?no source context — this forge was not attached to a git source snapshot}"
snap="${YAH_ATTACH_SNAPSHOT:?no YAH_ATTACH_SNAPSHOT — only a qed.attach debug forge can ship}"
ret="${YAH_RETURN_REF:?no YAH_RETURN_REF — only a qed.attach debug forge can ship}"
tok="${YAH_RETURN_GIT_TOKEN:?no YAH_RETURN_GIT_TOKEN — the attach minted no write token}"
case "$url" in
git+*) ;;
*) fail "the source context is a tarball, which has no return path; re-run the step with the git transport" ;;
esac
command -v git >/dev/null 2>&1 || fail "git is not on PATH in this forge"
spec="${url#git+}"
remote="${spec%%#*}"
if [ -n "${YAH_SOURCE_GIT_CACHE:-}" ]; then
  cache="$YAH_SOURCE_GIT_CACHE"
elif [ -d /yah/source-git ] && [ -w /yah/source-git ]; then
  cache=/yah/source-git/src.git
else
  cache="${TMPDIR:-/tmp}/yah-source-git.git"
fi
[ -f "$cache/HEAD" ] || fail "no source cache at $cache — was $dir materialized with yah-source-fetch?"
export GIT_TERMINAL_PROMPT=0 GIT_DIR="$cache"
export GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=http.extraHeader
export GIT_CONFIG_VALUE_0="Authorization: Bearer $tok"
exec 9>"$cache.lock"
if command -v flock >/dev/null 2>&1; then flock 9; fi
git cat-file -e "$snap^{commit}" 2>/dev/null || fail "snapshot $snap is not in $cache"
idx_dir="$(mktemp -d)"
trap 'rm -rf "$idx_dir"' EXIT
export GIT_INDEX_FILE="$idx_dir/index"
git read-tree "$snap" || fail "git read-tree $snap"
(cd "$dir" && git --work-tree=. add -A .) || fail "git add -A in $dir"
tree="$(git write-tree)" || fail "git write-tree"
commit="$(GIT_AUTHOR_NAME=yah-attach GIT_AUTHOR_EMAIL=qed@yah.invalid \
  GIT_COMMITTER_NAME=yah-attach GIT_COMMITTER_EMAIL=qed@yah.invalid \
  git commit-tree "$tree" -p "$snap" -m "yah-attach-return onto $snap")" || fail "git commit-tree"
git push --quiet "$remote" "+$commit:$ret" || fail "git push $ret to $remote"
echo "yah-source-ship: pushed $commit to $ret" >&2
