73 lines
3.0 KiB
Bash
Executable File
73 lines
3.0 KiB
Bash
Executable File
#!/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"
|