1
0
Files
kobopatch-webui/kobopatch-wasm/test-patches.sh

154 lines
4.8 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# Test all patches against cached firmware using kobopatch -t.
# Iterates over all firmware versions in tests/firmware-config.js,
# builds the native kobopatch binary, and generates blacklist.json.
cd "$(dirname "$0")"
# Use local Go if available
LOCAL_GO_DIR="$(pwd)/go"
if [ -x "$LOCAL_GO_DIR/bin/go" ]; then
export GOROOT="$LOCAL_GO_DIR"
export PATH="$LOCAL_GO_DIR/bin:$PATH"
fi
FIRMWARE_CONFIG="$(cd .. && pwd)/tests/firmware-config.js"
CACHED_ASSETS="$(cd .. && pwd)/tests/cached_assets"
PATCHES_DIR="$(cd .. && pwd)/web/src/patches"
BLACKLIST_FILE="$PATCHES_DIR/blacklist.json"
# Build the native kobopatch binary.
echo "=== Building kobopatch ==="
cd kobopatch-src
go build -o ../kobopatch ./kobopatch
cd ..
echo "Built kobopatch successfully."
# Start with an empty blacklist.
echo "{}" > "$BLACKLIST_FILE"
# Iterate over all firmware versions in the config (primary + others).
CONFIGS=$(node -e "var c=require('$FIRMWARE_CONFIG'); console.log(JSON.stringify([c.primary, ...c.others]))")
COUNT=$(echo "$CONFIGS" | jq 'length')
for i in $(seq 0 $((COUNT - 1))); do
ENTRY=$(echo "$CONFIGS" | jq -c ".[$i]")
VERSION=$(echo "$ENTRY" | jq -r '.version')
SHORT_VERSION=$(echo "$ENTRY" | jq -r '.shortVersion')
PATCHES=$(echo "$ENTRY" | jq -r '.patches')
URL=$(echo "$ENTRY" | jq -r '.url')
FIRMWARE_FILE="$CACHED_ASSETS/kobo-update-${VERSION}.zip"
PATCHES_ZIP="$PATCHES_DIR/$PATCHES"
if [ ! -f "$FIRMWARE_FILE" ]; then
echo ""
echo "=== Downloading firmware $VERSION ==="
mkdir -p "$CACHED_ASSETS"
curl -fL --progress-bar -o "$FIRMWARE_FILE.tmp" "$URL"
mv "$FIRMWARE_FILE.tmp" "$FIRMWARE_FILE"
fi
if [ ! -f "$PATCHES_ZIP" ]; then
echo ""
echo "=== Skipping $VERSION (patches zip $PATCHES not found) ==="
continue
fi
# Extract patches to a temp directory.
TMPDIR="$(mktemp -d)"
trap 'rm -rf "$TMPDIR"' EXIT
echo ""
echo "=== Extracting $PATCHES ==="
unzip -q "$PATCHES_ZIP" -d "$TMPDIR"
# Rewrite the config to point at the cached firmware and create output dir.
sed -i "s|^in:.*|in: $FIRMWARE_FILE|" "$TMPDIR/kobopatch.yaml"
mkdir -p "$TMPDIR/out"
# Run patch tests and capture output.
echo ""
echo "=== Testing patches against kobo-update-${VERSION}.zip ==="
echo ""
OUTPUT=$(./kobopatch -t -f "$FIRMWARE_FILE" "$TMPDIR/kobopatch.yaml" 2>&1 || true)
echo "$OUTPUT"
# Update blacklist.json with failed patches for this version.
echo ""
echo "=== Updating blacklist.json for $SHORT_VERSION ==="
echo "$OUTPUT" | python3 -c "
import sys, json, os
version = '$SHORT_VERSION'
blacklist_file = '$BLACKLIST_FILE'
tmpdir = '$TMPDIR'
with open(blacklist_file) as f:
blacklist = json.load(f)
current_file = None
failed = {}
for line in sys.stdin:
line = line.rstrip()
if line.startswith('Patching ./'):
current_file = line.split('Patching ./')[1]
elif '✕' in line and current_file:
name = line.split('✕')[1].strip()
failed.setdefault(current_file, []).append(name)
# Parse kobopatch.yaml patches section to get target -> src mapping.
src_to_target = {}
in_patches = False
with open(os.path.join(tmpdir, 'kobopatch.yaml')) as f:
for cfg_line in f:
cfg_line = cfg_line.rstrip()
if cfg_line.startswith('patches:'):
in_patches = True
continue
if in_patches and cfg_line and not cfg_line.startswith(' ') and not cfg_line.startswith('#'):
in_patches = False
if in_patches:
parts = cfg_line.strip().split(':')
if len(parts) >= 2 and parts[0].endswith('.yaml'):
src_to_target[parts[0].strip()] = parts[1].strip()
# Build a patch-name -> src file mapping by scanning patch files.
patch_name_to_src = {}
for src in src_to_target:
src_path = os.path.join(tmpdir, src)
if not os.path.exists(src_path):
continue
with open(src_path) as pf:
for pf_line in pf:
pf_line = pf_line.rstrip()
if pf_line and not pf_line.startswith(' ') and not pf_line.startswith('#') and pf_line.endswith(':'):
patch_name_to_src[pf_line[:-1].strip()] = src
# Build the version entry keyed by src file.
version_entry = {}
for target, patches in sorted(failed.items()):
for patch in sorted(patches):
src = patch_name_to_src.get(patch, target)
version_entry.setdefault(src, []).append(patch)
blacklist[version] = version_entry
with open(blacklist_file, 'w') as f:
json.dump(blacklist, f, indent=2)
f.write('\n')
total_failed = sum(len(v) for v in version_entry.values())
print(f'Wrote {total_failed} blacklisted patch(es) for version {version}')
"
rm -rf "$TMPDIR"
trap - EXIT
done
echo ""
echo "=== Blacklist written to $BLACKLIST_FILE ==="