#!/bin/sh

# Build deterministic browsing and TDS archives for the independent
# pgfplots-autonode CTAN package.  The TDS archive is tested in isolation and
# remains a separate release artifact; scripts/submit-ctan.sh does not upload it.

set -eu

fail()
{
    printf 'error: %s\n' "$*" >&2
    exit 1
}

need_command()
{
    command -v "$1" >/dev/null 2>&1 \
        || fail "required command not found: $1"
}

[ "$#" -le 1 ] || fail "usage: $0 [OUTPUT_DIRECTORY]"
for command_name in chmod cp date dirname find grep mkdir mktemp mv rm sed sort \
    touch unzip zip; do
    need_command "$command_name"
done
SCRIPT_DIR=$(CDPATH= cd -P "$(dirname "$0")" && pwd)
PROJECT_DIR=$(CDPATH= cd -P "$SCRIPT_DIR/.." && pwd)
MANIFEST=$PROJECT_DIR/PGFPLOTS-AUTONODE-MANIFEST.txt
[ -f "$MANIFEST" ] || MANIFEST=$PROJECT_DIR/MANIFEST.txt
VERSION_FILE=$PROJECT_DIR/PGFPLOTS-AUTONODE-VERSION
[ -f "$VERSION_FILE" ] || VERSION_FILE=$PROJECT_DIR/VERSION
[ -f "$MANIFEST" ] || fail "release manifest not found: $MANIFEST"
[ -f "$VERSION_FILE" ] || fail "release metadata not found: $VERSION_FILE"
OUTPUT_DIR=${1:-$PROJECT_DIR/dist}
mkdir -p "$OUTPUT_DIR"
OUTPUT_DIR=$(CDPATH= cd -P "$OUTPUT_DIR" && pwd)

VERSION=$(sed -n \
    's/^\\ProvidesPackage{pgfplots-autonode}\[[^ ]* v\([^ ]*\) .*/\1/p' \
    "$PROJECT_DIR/pgfplots-autonode.sty")
BUNDLE_VERSION=$(sed -n 's/^VERSION=//p' "$VERSION_FILE")
[ -n "$BUNDLE_VERSION" ] || fail "VERSION metadata is empty"
[ "$VERSION" = "$BUNDLE_VERSION" ] \
    || fail "version mismatch: style=$VERSION, metadata=$BUNDLE_VERSION"

if [ -n "${SOURCE_DATE_EPOCH:-}" ]; then
    RELEASE_EPOCH=$SOURCE_DATE_EPOCH
else
    RELEASE_EPOCH=$(sed -n 's/^SOURCE_DATE_EPOCH=//p' "$VERSION_FILE")
fi
case $RELEASE_EPOCH in
    ''|*[!0-9]*) fail "SOURCE_DATE_EPOCH must be a non-negative integer" ;;
esac
SOURCE_DATE_EPOCH=$RELEASE_EPOCH
FORCE_SOURCE_DATE=1
export SOURCE_DATE_EPOCH FORCE_SOURCE_DATE
if TOUCH_TIMESTAMP=$(date -u -r "$RELEASE_EPOCH" '+%Y%m%d%H%M.%S' 2>/dev/null); then
    :
elif TOUCH_TIMESTAMP=$(date -u -d "@$RELEASE_EPOCH" '+%Y%m%d%H%M.%S' 2>/dev/null); then
    :
else
    fail "could not convert SOURCE_DATE_EPOCH"
fi

TEMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/pgfplots-autonode-release.XXXXXX")
cleanup()
{
    rm -rf "$TEMP_DIR"
}
trap cleanup 0
trap 'exit 1' HUP INT TERM
PACKAGE_NAME=pgfplots-autonode
PACKAGE_DIR=$TEMP_DIR/$PACKAGE_NAME
TDS_DIR=$TEMP_DIR/tds
mkdir -p "$PACKAGE_DIR" "$TDS_DIR"

while IFS= read -r relative_path || [ -n "$relative_path" ]; do
    case $relative_path in
        ''|'#'*) continue ;;
        /*|..|../*|*/../*) fail "unsafe manifest entry: $relative_path" ;;
    esac
    source_path=$PROJECT_DIR/$relative_path
    if [ ! -f "$source_path" ]; then
        case $relative_path in
            pgfplots-autonode-LICENSE) source_path=$PROJECT_DIR/LICENSE ;;
            pgfplots-autonode-CHANGELOG.md) source_path=$PROJECT_DIR/CHANGELOG.md ;;
            pgfplots-autonode-README.md) source_path=$PROJECT_DIR/README.md ;;
            PGFPLOTS-AUTONODE-VERSION) source_path=$PROJECT_DIR/VERSION ;;
            PGFPLOTS-AUTONODE-MANIFEST.txt) source_path=$PROJECT_DIR/MANIFEST.txt ;;
        esac
    fi
    [ -f "$source_path" ] || fail "manifest file not found: $relative_path"
    case $relative_path in
        pgfplots-autonode-LICENSE) staged_path=LICENSE ;;
        pgfplots-autonode-CHANGELOG.md) staged_path=CHANGELOG.md ;;
        pgfplots-autonode-README.md) staged_path=README.md ;;
        PGFPLOTS-AUTONODE-VERSION) staged_path=VERSION ;;
        PGFPLOTS-AUTONODE-MANIFEST.txt) staged_path=MANIFEST.txt ;;
        *) staged_path=$relative_path ;;
    esac
    target_path=$PACKAGE_DIR/$staged_path
    mkdir -p "$(dirname "$target_path")"
    cp "$source_path" "$target_path"
done <"$MANIFEST"

# The repository keeps package-specific metadata names because two independent
# distributions share one checkout.  The browsing archive uses conventional
# names, so its public manifest must describe the staged tree rather than the
# repository tree.  This also makes an extracted browsing archive repackable.
sed -e 's|^pgfplots-autonode-LICENSE$|LICENSE|' \
    -e 's|^pgfplots-autonode-CHANGELOG\.md$|CHANGELOG.md|' \
    -e 's|^pgfplots-autonode-README\.md$|README.md|' \
    -e 's|^PGFPLOTS-AUTONODE-VERSION$|VERSION|' \
    -e 's|^PGFPLOTS-AUTONODE-MANIFEST\.txt$|MANIFEST.txt|' \
    "$MANIFEST" >"$PACKAGE_DIR/MANIFEST.txt.generated"
mv -f "$PACKAGE_DIR/MANIFEST.txt.generated" "$PACKAGE_DIR/MANIFEST.txt"

install_tds_file()
{
    source_name=$1
    target_name=$2
    [ -f "$PACKAGE_DIR/$source_name" ] \
        || fail "TDS source is missing: $source_name"
    mkdir -p "$(dirname "$TDS_DIR/$target_name")"
    cp "$PACKAGE_DIR/$source_name" "$TDS_DIR/$target_name"
}

for file_name in pgflibrarypgfplots.autonode.code.tex \
    pgfplots-autonode.code.tex; do
    install_tds_file "$file_name" "tex/generic/pgfplots-autonode/$file_name"
done
install_tds_file pgfplots-autonode.sty \
    tex/latex/pgfplots-autonode/pgfplots-autonode.sty
install_tds_file pgfplots-autonode.lua \
    tex/luatex/pgfplots-autonode/pgfplots-autonode.lua

for file_name in README.md CHANGELOG.md LICENSE VERSION \
    pgfplots-autonode-manual.pdf; do
    install_tds_file "$file_name" "doc/generic/pgfplots-autonode/$file_name"
done
find "$PACKAGE_DIR/examples" -type f \( -name '*.tex' -o -name '*.pdf' \) \
    -print >"$TEMP_DIR/document-files"
while IFS= read -r source_file; do
    relative=${source_file#"$PACKAGE_DIR/"}
    install_tds_file "$relative" "doc/generic/pgfplots-autonode/$relative"
done <"$TEMP_DIR/document-files"

for file_name in MANIFEST.txt VERSION pgfplots-autonode-manual.tex \
    pgflibrarypgfplots.autonode.code.tex pgfplots-autonode.code.tex \
    pgfplots-autonode.lua pgfplots-autonode.sty; do
    install_tds_file "$file_name" "source/generic/pgfplots-autonode/$file_name"
done
find "$PACKAGE_DIR/docs" "$PACKAGE_DIR/examples" "$PACKAGE_DIR/scripts" \
    "$PACKAGE_DIR/tests" -type f ! -name '*.pdf' ! -name '*.log' -print \
    >"$TEMP_DIR/source-files"
while IFS= read -r source_file; do
    relative=${source_file#"$PACKAGE_DIR/"}
    install_tds_file "$relative" "source/generic/pgfplots-autonode/$relative"
done <"$TEMP_DIR/source-files"

normalize_tree()
{
    tree=$1
    find "$tree" -type d -exec chmod 755 {} +
    find "$tree" -type f -exec chmod 644 {} +
    if [ -d "$tree/scripts" ]; then
        find "$tree/scripts" -type f -name '*.sh' -exec chmod 755 {} +
    fi
    if [ -d "$tree/source/generic/pgfplots-autonode/scripts" ]; then
        find "$tree/source/generic/pgfplots-autonode/scripts" -type f \
            -name '*.sh' -exec chmod 755 {} +
    fi
    find "$tree" -exec touch -t "$TOUCH_TIMESTAMP" {} +
}

zip_tds()
{
    (CDPATH= cd -P "$TDS_DIR" && find tex doc source -type f -print) \
        | sort >"$TEMP_DIR/tds-files"
    (CDPATH= cd -P "$TDS_DIR" && zip -X -q "$1" -@ \
        <"$TEMP_DIR/tds-files")
}

normalize_tree "$PACKAGE_DIR"
normalize_tree "$TDS_DIR"
TDS_ARCHIVE=$TEMP_DIR/pgfplots-autonode.tds.zip
zip_tds "$TDS_ARCHIVE" || fail "could not create the autonode TDS ZIP"
if unzip -Z1 "$TDS_ARCHIVE" | grep -E \
    '(^|/)luacoolprop(\.lua|\.tex|\.sty|-manual\.pdf)?$' >/dev/null; then
    fail "pgfplots-autonode TDS archive embeds a LuaCoolProp file"
fi
"$SCRIPT_DIR/test-autonode.sh" "$TDS_ARCHIVE"

(CDPATH= cd -P "$TEMP_DIR" && find "$PACKAGE_NAME" -type f -print) \
    | sort >"$TEMP_DIR/outer-files"
BROWSING_ARCHIVE=$TEMP_DIR/pgfplots-autonode.zip
(CDPATH= cd -P "$TEMP_DIR" && zip -X -q "$BROWSING_ARCHIVE" -@ \
    <"$TEMP_DIR/outer-files") \
    || fail "could not create the autonode browsing ZIP"
if unzip -Z1 "$BROWSING_ARCHIVE" | grep -E \
    '(^|/)luacoolprop(\.lua|\.tex|\.sty|-manual\.pdf)?$' >/dev/null; then
    fail "pgfplots-autonode browsing archive embeds a LuaCoolProp file"
fi

cp "$TDS_ARCHIVE" "$OUTPUT_DIR/pgfplots-autonode.tds.zip"
mv -f "$BROWSING_ARCHIVE" "$OUTPUT_DIR/pgfplots-autonode.zip"
printf '%s\n%s\n' "$OUTPUT_DIR/pgfplots-autonode.zip" \
    "$OUTPUT_DIR/pgfplots-autonode.tds.zip"
