#!/usr/bin/env bash

set -euo pipefail

NEW_WEB=${1:?new web root is required}
OLD_WEB=${2:?old web root is required}
MAX_COMPATIBILITY_GENERATIONS=${3:-3}

case "$MAX_COMPATIBILITY_GENERATIONS" in
  ''|*[!0-9]*) printf 'invalid compatibility generation limit: %s\n' "$MAX_COMPATIBILITY_GENERATIONS" >&2; exit 1 ;;
esac
test "$MAX_COMPATIBILITY_GENERATIONS" -ge 1 || { printf 'compatibility generation limit must be positive\n' >&2; exit 1; }
test -f "$NEW_WEB/.release-assets" || { printf 'new release manifest is missing\n' >&2; exit 1; }
test -f "$OLD_WEB/.release-assets" || { printf 'old release manifest is missing\n' >&2; exit 1; }
mkdir -p "$NEW_WEB/assets" "$NEW_WEB/.compatibility-manifests"

validate_asset() {
  local asset=$1
  case "$asset" in
    ''|/*|*/*|.|..) printf 'unsafe release asset: %s\n' "$asset" >&2; return 1 ;;
  esac
}

while IFS= read -r asset || test -n "$asset"; do
  asset=${asset%$'\r'}
  test -n "$asset" || continue
  validate_asset "$asset"
  test -f "$NEW_WEB/assets/$asset" || { printf 'current asset is missing: %s\n' "$NEW_WEB/assets/$asset" >&2; exit 1; }
done < "$NEW_WEB/.release-assets"

copy_manifest_assets() {
  local manifest=$1
  local asset source destination
  while IFS= read -r asset || test -n "$asset"; do
    asset=${asset%$'\r'}
    test -n "$asset" || continue
    validate_asset "$asset"
    source="$OLD_WEB/assets/$asset"
    destination="$NEW_WEB/assets/$asset"
    test -f "$source" || { printf 'compatibility asset is missing: %s\n' "$source" >&2; return 1; }
    if test -f "$destination"; then
      cmp -s "$source" "$destination" || { printf 'asset hash collision has different content: %s\n' "$asset" >&2; return 1; }
    else
      cp "$source" "$destination"
    fi
  done < "$manifest"
}

cp "$OLD_WEB/.release-assets" "$NEW_WEB/.compatibility-manifests/1.assets"
generation=2
while test "$generation" -le "$MAX_COMPATIBILITY_GENERATIONS"; do
  previous=$((generation - 1))
  source_manifest="$OLD_WEB/.compatibility-manifests/$previous.assets"
  test -f "$source_manifest" || break
  cp "$source_manifest" "$NEW_WEB/.compatibility-manifests/$generation.assets"
  generation=$((generation + 1))
done

compatibility_manifest="$NEW_WEB/.compatibility-assets"
: > "$compatibility_manifest"
for manifest in "$NEW_WEB"/.compatibility-manifests/*.assets; do
  test -f "$manifest" || continue
  copy_manifest_assets "$manifest"
  cat "$manifest" >> "$compatibility_manifest"
done
LC_ALL=C sort -u "$compatibility_manifest" -o "$compatibility_manifest"

current_count=$(awk 'NF { count += 1 } END { print count + 0 }' "$NEW_WEB/.release-assets")
compatibility_count=$(awk 'NF { count += 1 } END { print count + 0 }' "$compatibility_manifest")
generation_count=$(find "$NEW_WEB/.compatibility-manifests" -maxdepth 1 -type f -name '*.assets' | wc -l | tr -d ' ')
served_count=$(find "$NEW_WEB/assets" -maxdepth 1 -type f | wc -l | tr -d ' ')
printf 'web_release_tree=ok current_assets=%s compatibility_assets=%s compatibility_generations=%s served_assets=%s\n' "$current_count" "$compatibility_count" "$generation_count" "$served_count"
