#!/usr/bin/env bash
set -euo pipefail

HERE="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
cd "$HERE"

if [[ ! -f src/fileflow.py ]]; then
    echo "Run this installer from the TraceFlow directory." >&2
    exit 1
fi

stamp="$(date +%Y%m%d-%H%M%S-%N)"
backup="backups/static-scanner-$stamp"
mkdir -p "$backup"

for file in src/fileflow.py src/clean-tree.py tests/run-tests.sh run.static.sh docs/STATIC-SCANNER.md; do
    if [[ -e "$file" ]]; then
        mkdir -p "$backup/$(dirname "$file")"
        cp -p "$file" "$backup/$file"
    fi
done

python3 - <<'PY'
from pathlib import Path
import base64
import py_compile

files = {'src/fileflow.py': 'IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoiIiJUcmFjZUZsb3cgc3RhdGljIGZpbGUtZmxvdyBzY2FubmVyLgoKUmVhZHMgc291cmNlIHRleHQgb25seTsgbmV2ZXIgZXhlY3V0ZXMgc2Nhbm5lZCBQSFAsIEpTLCBIVE1MLCBDU1MsIHNoZWxsLCBvciBQeXRob24uClN1cHBvcnRzIGxpdGVyYWwgcGF0aHMgcGx1cyBjb21tb24gUEhQIF9fRElSX18gYW5kIGNvbmZpZ3VyZWQgY29uc3RhbnQgcGF0aCBleHByZXNzaW9ucy4KIiIiCmZyb20gX19mdXR1cmVfXyBpbXBvcnQgYW5ub3RhdGlvbnMKCmltcG9ydCBhcmdwYXJzZQppbXBvcnQganNvbgppbXBvcnQgcmUKaW1wb3J0IHN5cwpmcm9tIGNvbGxlY3Rpb25zIGltcG9ydCBkZXF1ZQpmcm9tIHBhdGhsaWIgaW1wb3J0IFBhdGgKZnJvbSB0eXBpbmcgaW1wb3J0IEl0ZXJhYmxlCgpGSUxFX1RZUEVTID0gewogICAgIi5waHAiOiAicGhwIiwgIi5waHRtbCI6ICJwaHAiLCAiLnBocDMiOiAicGhwIiwgIi5waHA0IjogInBocCIsICIucGhwNSI6ICJwaHAiLAogICAgIi5odG1sIjogImh0bWwiLCAiLmh0bSI6ICJodG1sIiwKICAgICIuanMiOiAiamF2YXNjcmlwdCIsICIubWpzIjogImphdmFzY3JpcHQiLCAiLmNqcyI6ICJqYXZhc2NyaXB0IiwKICAgICIuY3NzIjogImNzcyIsCiAgICAiLnNoIjogInNoZWxsIiwgIi5iYXNoIjogInNoZWxsIiwKICAgICIucHkiOiAicHl0aG9uIiwKfQoKUEhQX0xJVEVSQUwgPSByZS5jb21waWxlKAogICAgciIiIlxiKD86aW5jbHVkZXxpbmNsdWRlX29uY2V8cmVxdWlyZXxyZXF1aXJlX29uY2UpXHMqKD86XChccyopP1snXCJdKFteJ1wiXSspWydcIl0iIiIsCiAgICByZS5JR05PUkVDQVNFLAopCgpQSFBfRElSID0gcmUuY29tcGlsZSgKICAgIHIiIiJcYig/OmluY2x1ZGV8aW5jbHVkZV9vbmNlfHJlcXVpcmV8cmVxdWlyZV9vbmNlKVxzKig/OlwoXHMqKT9fX0RJUl9fXHMqXC5ccypbJ1wiXShbXidcIl0rKVsnXCJdIiIiLAogICAgcmUuSUdOT1JFQ0FTRSwKKQoKUEhQX0NPTlNUQU5UID0gcmUuY29tcGlsZSgKICAgIHIiIiJcYig/OmluY2x1ZGV8aW5jbHVkZV9vbmNlfHJlcXVpcmV8cmVxdWlyZV9vbmNlKVxzKig/OlwoXHMqKT8oW0EtWl1bQS1aMC05X10qKVxzKlwuXHMqWydcIl0oW14nXCJdKylbJ1wiXSIiIiwKICAgIHJlLklHTk9SRUNBU0UsCikKCkhUTUxfU0NSSVBUID0gcmUuY29tcGlsZSgKICAgIHIiIiI8c2NyaXB0XGJbXj5dKlxic3JjXHMqPVxzKlsnXCJdKFteJ1wiXSspWydcIl0iIiIsCiAgICByZS5JR05PUkVDQVNFLAopCgpIVE1MX0xJTksgPSByZS5jb21waWxlKAogICAgciIiIjxsaW5rXGJbXj5dKlxiaHJlZlxzKj1ccypbJ1wiXShbXidcIl0rKVsnXCJdIiIiLAogICAgcmUuSUdOT1JFQ0FTRSwKKQoKQ1NTX0lNUE9SVCA9IHJlLmNvbXBpbGUoCiAgICByIiIiQGltcG9ydFxzKyg/OnVybFwoXHMqKT9bJ1wiXShbXidcIl0rKVsnXCJdIiIiLAogICAgcmUuSUdOT1JFQ0FTRSwKKQoKSlNfSU1QT1JUID0gcmUuY29tcGlsZSgKICAgIHIiIiJcYmltcG9ydFxzKig/OlteJ1wiKCldKj9ccytmcm9tXHMrKT9bJ1wiXShbXidcIl0rKVsnXCJdfFxiaW1wb3J0XHMqXChccypbJ1wiXShbXidcIl0rKVsnXCJdXHMqXCl8XGJyZXF1aXJlXHMqXChccypbJ1wiXShbXidcIl0rKVsnXCJdXHMqXCkiIiIsCiAgICByZS5JR05PUkVDQVNFLAopCgpTSEVMTF9TT1VSQ0UgPSByZS5jb21waWxlKAogICAgciIiIig/Ol58Wztcc10pKD86c291cmNlfFwuKVxzK1snXCJdPyhbXlxzJ1wiO10rKSIiIiwKICAgIHJlLk1VTFRJTElORSwKKQoKUFlUSE9OX0lNUE9SVCA9IHJlLmNvbXBpbGUoCiAgICByIiIiXlxzKig/OmZyb21ccysoW0EtWmEtel9dXHcqKD86XC5cdyspKilccytpbXBvcnR8aW1wb3J0XHMrKFtBLVphLXpfXVx3Kig/OlwuXHcrKSopKSIiIiwKICAgIHJlLk1VTFRJTElORSwKKQoKRVhURVJOQUxfUkVGRVJFTkNFID0gcmUuY29tcGlsZShyIl4oPzpodHRwcz86KT8vL3xeZGF0YTp8XiMiLCByZS5JR05PUkVDQVNFKQoKCmRlZiBub3JtYWxpemVfY29uc3RhbnRfcGF0aHMoaXRlbXM6IGxpc3Rbc3RyXSkgLT4gZGljdFtzdHIsIFBhdGhdOgogICAgIiIiUGFyc2UgTkFNRT0vcGF0aCBwYWlycyBzdXBwbGllZCB0aHJvdWdoIC0tY29uc3RhbnQtcGF0aC4iIiIKICAgIHZhbHVlczogZGljdFtzdHIsIFBhdGhdID0ge30KICAgIGZvciBpdGVtIGluIGl0ZW1zOgogICAgICAgIGlmICI9IiBub3QgaW4gaXRlbToKICAgICAgICAgICAgcmFpc2UgVmFsdWVFcnJvcihmIkludmFsaWQgLS1jb25zdGFudC1wYXRoIHZhbHVlOiB7aXRlbSFyfTsgdXNlIE5BTUU9L3BhdGgiKQogICAgICAgIG5hbWUsIHZhbHVlID0gaXRlbS5zcGxpdCgiPSIsIDEpCiAgICAgICAgbmFtZSA9IG5hbWUuc3RyaXAoKQogICAgICAgIHZhbHVlID0gdmFsdWUuc3RyaXAoKQogICAgICAgIGlmIG5vdCByZS5mdWxsbWF0Y2gociJbQS1aXVtBLVowLTlfXSoiLCBuYW1lKToKICAgICAgICAgICAgcmFpc2UgVmFsdWVFcnJvcihmIkludmFsaWQgUEhQIGNvbnN0YW50IG5hbWU6IHtuYW1lIXJ9IikKICAgICAgICBpZiBub3QgdmFsdWU6CiAgICAgICAgICAgIHJhaXNlIFZhbHVlRXJyb3IoZiJFbXB0eSBwYXRoIGZvciBQSFAgY29uc3RhbnQ6IHtuYW1lfSIpCiAgICAgICAgdmFsdWVzW25hbWVdID0gUGF0aCh2YWx1ZSkuZXhwYW5kdXNlcigpLnJlc29sdmUoKQogICAgcmV0dXJuIHZhbHVlcwoKCmNsYXNzIEZpbGVGbG93U2Nhbm5lcjoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCByb290OiBQYXRoLCBjb25zdGFudF9wYXRoczogZGljdFtzdHIsIFBhdGhdIHwgTm9uZSA9IE5vbmUpOgogICAgICAgIHNlbGYucm9vdCA9IHJvb3QucmVzb2x2ZSgpCiAgICAgICAgc2VsZi5jb25zdGFudF9wYXRocyA9IGNvbnN0YW50X3BhdGhzIG9yIHt9CiAgICAgICAgc2VsZi5ub2RlczogZGljdFtzdHIsIGRpY3RdID0ge30KICAgICAgICBzZWxmLmVkZ2VzOiBsaXN0W2RpY3RdID0gW10KICAgICAgICBzZWxmLnVucmVzb2x2ZWQ6IGxpc3RbZGljdF0gPSBbXQogICAgICAgIHNlbGYuc2Nhbm5lZDogc2V0W1BhdGhdID0gc2V0KCkKCiAgICBkZWYgZmlsZV90eXBlKHNlbGYsIHBhdGg6IFBhdGgpIC0+IHN0cjoKICAgICAgICByZXR1cm4gRklMRV9UWVBFUy5nZXQocGF0aC5zdWZmaXgubG93ZXIoKSwgInVua25vd24iKQoKICAgIGRlZiByZWxhdGl2ZV9pZChzZWxmLCBwYXRoOiBQYXRoKSAtPiBzdHI6CiAgICAgICAgcmVzb2x2ZWQgPSBwYXRoLnJlc29sdmUoKQogICAgICAgIHRyeToKICAgICAgICAgICAgcmV0dXJuIHJlc29sdmVkLnJlbGF0aXZlX3RvKHNlbGYucm9vdCkuYXNfcG9zaXgoKQogICAgICAgIGV4Y2VwdCBWYWx1ZUVycm9yOgogICAgICAgICAgICByZXR1cm4gIltleHRlcm5hbF0vIiArIHJlc29sdmVkLm5hbWUKCiAgICBkZWYgYWRkX25vZGUoc2VsZiwgcGF0aDogUGF0aCkgLT4gc3RyOgogICAgICAgIG5vZGVfaWQgPSBzZWxmLnJlbGF0aXZlX2lkKHBhdGgpCiAgICAgICAgc2VsZi5ub2Rlcy5zZXRkZWZhdWx0KG5vZGVfaWQsIHsKICAgICAgICAgICAgImlkIjogbm9kZV9pZCwKICAgICAgICAgICAgInR5cGUiOiBzZWxmLmZpbGVfdHlwZShwYXRoKSwKICAgICAgICB9KQogICAgICAgIHJldHVybiBub2RlX2lkCgogICAgZGVmIGlzX2V4dGVybmFsX3JlZmVyZW5jZShzZWxmLCByYXc6IHN0cikgLT4gYm9vbDoKICAgICAgICByZXR1cm4gYm9vbChFWFRFUk5BTF9SRUZFUkVOQ0UubWF0Y2gocmF3LnN0cmlwKCkpKQoKICAgIGRlZiBjYW5kaWRhdGVfcGF0aHMoc2VsZiwgc291cmNlOiBQYXRoLCByYXc6IHN0ciwga2luZDogc3RyLCBjb25zdGFudDogc3RyIHwgTm9uZSkgLT4gbGlzdFtQYXRoXToKICAgICAgICByYXcgPSByYXcuc3RyaXAoKQogICAgICAgIGNhbmRpZGF0ZXM6IGxpc3RbUGF0aF0gPSBbXQoKICAgICAgICBpZiBraW5kID09ICJwaHAuaW5jbHVkZV9kaXIiOgogICAgICAgICAgICBjYW5kaWRhdGVzLmFwcGVuZChzb3VyY2UucGFyZW50IC8gcmF3KQogICAgICAgICAgICByZXR1cm4gY2FuZGlkYXRlcwoKICAgICAgICBpZiBraW5kID09ICJwaHAuaW5jbHVkZV9jb25zdGFudCI6CiAgICAgICAgICAgIGlmIGNvbnN0YW50IGFuZCBjb25zdGFudCBpbiBzZWxmLmNvbnN0YW50X3BhdGhzOgogICAgICAgICAgICAgICAgY2FuZGlkYXRlcy5hcHBlbmQoc2VsZi5jb25zdGFudF9wYXRoc1tjb25zdGFudF0gLyByYXcubHN0cmlwKCIvIikpCiAgICAgICAgICAgIHJldHVybiBjYW5kaWRhdGVzCgogICAgICAgIGlmIHJhdy5zdGFydHN3aXRoKCIvIik6CiAgICAgICAgICAgIGNhbmRpZGF0ZXMuYXBwZW5kKHNlbGYucm9vdCAvIHJhdy5sc3RyaXAoIi8iKSkKICAgICAgICBlbHNlOgogICAgICAgICAgICBjYW5kaWRhdGVzLmFwcGVuZChzb3VyY2UucGFyZW50IC8gcmF3KQogICAgICAgICAgICBjYW5kaWRhdGVzLmFwcGVuZChzZWxmLnJvb3QgLyByYXcpCgogICAgICAgIHJldHVybiBjYW5kaWRhdGVzCgogICAgZGVmIHJlc29sdmVfcmVmZXJlbmNlKAogICAgICAgIHNlbGYsCiAgICAgICAgc291cmNlOiBQYXRoLAogICAgICAgIHJhdzogc3RyLAogICAgICAgIGtpbmQ6IHN0ciwKICAgICAgICBjb25zdGFudDogc3RyIHwgTm9uZSA9IE5vbmUsCiAgICApIC0+IFBhdGggfCBOb25lOgogICAgICAgIGlmIG5vdCByYXcgb3Igc2VsZi5pc19leHRlcm5hbF9yZWZlcmVuY2UocmF3KToKICAgICAgICAgICAgcmV0dXJuIE5vbmUKCiAgICAgICAgZm9yIGNhbmRpZGF0ZSBpbiBzZWxmLmNhbmRpZGF0ZV9wYXRocyhzb3VyY2UsIHJhdywga2luZCwgY29uc3RhbnQpOgogICAgICAgICAgICBpZiBjYW5kaWRhdGUuaXNfZmlsZSgpOgogICAgICAgICAgICAgICAgcmV0dXJuIGNhbmRpZGF0ZS5yZXNvbHZlKCkKCiAgICAgICAgICAgIGlmIGNhbmRpZGF0ZS5zdWZmaXg6CiAgICAgICAgICAgICAgICBjb250aW51ZQoKICAgICAgICAgICAgZm9yIGV4dGVuc2lvbiBpbiAoIi5waHAiLCAiLmpzIiwgIi5tanMiLCAiLmNzcyIsICIuc2giLCAiLnB5Iik6CiAgICAgICAgICAgICAgICB3aXRoX2V4dGVuc2lvbiA9IFBhdGgoc3RyKGNhbmRpZGF0ZSkgKyBleHRlbnNpb24pCiAgICAgICAgICAgICAgICBpZiB3aXRoX2V4dGVuc2lvbi5pc19maWxlKCk6CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpdGhfZXh0ZW5zaW9uLnJlc29sdmUoKQoKICAgICAgICAgICAgZm9yIGluZGV4X25hbWUgaW4gKCJpbmRleC5waHAiLCAiaW5kZXguanMiLCAiaW5kZXguaHRtbCIpOgogICAgICAgICAgICAgICAgaW5kZXhfZmlsZSA9IGNhbmRpZGF0ZSAvIGluZGV4X25hbWUKICAgICAgICAgICAgICAgIGlmIGluZGV4X2ZpbGUuaXNfZmlsZSgpOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBpbmRleF9maWxlLnJlc29sdmUoKQoKICAgICAgICByZXR1cm4gTm9uZQoKICAgIGRlZiBhZGRfcmVmZXJlbmNlKAogICAgICAgIHNlbGYsCiAgICAgICAgc291cmNlOiBQYXRoLAogICAgICAgIHJhdzogc3RyLAogICAgICAgIGtpbmQ6IHN0ciwKICAgICAgICBjb25zdGFudDogc3RyIHwgTm9uZSA9IE5vbmUsCiAgICApIC0+IFBhdGggfCBOb25lOgogICAgICAgIHNvdXJjZV9pZCA9IHNlbGYuYWRkX25vZGUoc291cmNlKQogICAgICAgIHRhcmdldCA9IHNlbGYucmVzb2x2ZV9yZWZlcmVuY2Uoc291cmNlLCByYXcsIGtpbmQsIGNvbnN0YW50KQoKICAgICAgICBpZiB0YXJnZXQgaXMgTm9uZToKICAgICAgICAgICAgaWYgcmF3IGFuZCBub3Qgc2VsZi5pc19leHRlcm5hbF9yZWZlcmVuY2UocmF3KToKICAgICAgICAgICAgICAgIHJlY29yZCA9IHsKICAgICAgICAgICAgICAgICAgICAiZnJvbSI6IHNvdXJjZV9pZCwKICAgICAgICAgICAgICAgICAgICAicmVmZXJlbmNlIjogcmF3LAogICAgICAgICAgICAgICAgICAgICJraW5kIjoga2luZCwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGlmIGNvbnN0YW50OgogICAgICAgICAgICAgICAgICAgIHJlY29yZFsiY29uc3RhbnQiXSA9IGNvbnN0YW50CiAgICAgICAgICAgICAgICAgICAgaWYgY29uc3RhbnQgbm90IGluIHNlbGYuY29uc3RhbnRfcGF0aHM6CiAgICAgICAgICAgICAgICAgICAgICAgIHJlY29yZFsicmVhc29uIl0gPSAiY29uc3RhbnRfcGF0aF9ub3RfY29uZmlndXJlZCIKICAgICAgICAgICAgICAgIGlmIHJlY29yZCBub3QgaW4gc2VsZi51bnJlc29sdmVkOgogICAgICAgICAgICAgICAgICAgIHNlbGYudW5yZXNvbHZlZC5hcHBlbmQocmVjb3JkKQogICAgICAgICAgICByZXR1cm4gTm9uZQoKICAgICAgICB0YXJnZXRfaWQgPSBzZWxmLmFkZF9ub2RlKHRhcmdldCkKICAgICAgICBlZGdlID0gewogICAgICAgICAgICAiZnJvbSI6IHNvdXJjZV9pZCwKICAgICAgICAgICAgInRvIjogdGFyZ2V0X2lkLAogICAgICAgICAgICAia2luZCI6IGtpbmQsCiAgICAgICAgfQogICAgICAgIGlmIGNvbnN0YW50OgogICAgICAgICAgICBlZGdlWyJjb25zdGFudCJdID0gY29uc3RhbnQKCiAgICAgICAgaWYgZWRnZSBub3QgaW4gc2VsZi5lZGdlczoKICAgICAgICAgICAgc2VsZi5lZGdlcy5hcHBlbmQoZWRnZSkKCiAgICAgICAgcmV0dXJuIHRhcmdldAoKICAgIGRlZiByZWZlcmVuY2VzKHNlbGYsIHBhdGg6IFBhdGgsIHRleHQ6IHN0cikgLT4gSXRlcmFibGVbdHVwbGVbc3RyLCBzdHIsIHN0ciB8IE5vbmVdXToKICAgICAgICBraW5kID0gc2VsZi5maWxlX3R5cGUocGF0aCkKCiAgICAgICAgaWYga2luZCA9PSAicGhwIjoKICAgICAgICAgICAgZm9yIHJhdyBpbiBQSFBfTElURVJBTC5maW5kYWxsKHRleHQpOgogICAgICAgICAgICAgICAgeWllbGQgcmF3LCAicGhwLmluY2x1ZGUiLCBOb25lCgogICAgICAgICAgICBmb3IgcmF3IGluIFBIUF9ESVIuZmluZGFsbCh0ZXh0KToKICAgICAgICAgICAgICAgIHlpZWxkIHJhdywgInBocC5pbmNsdWRlX2RpciIsICJfX0RJUl9fIgoKICAgICAgICAgICAgZm9yIGNvbnN0YW50LCByYXcgaW4gUEhQX0NPTlNUQU5ULmZpbmRhbGwodGV4dCk6CiAgICAgICAgICAgICAgICB5aWVsZCByYXcsICJwaHAuaW5jbHVkZV9jb25zdGFudCIsIGNvbnN0YW50CgogICAgICAgICAgICBmb3IgcmF3IGluIEhUTUxfU0NSSVBULmZpbmRhbGwodGV4dCk6CiAgICAgICAgICAgICAgICB5aWVsZCByYXcsICJodG1sLnNjcmlwdCIsIE5vbmUKCiAgICAgICAgICAgIGZvciByYXcgaW4gSFRNTF9MSU5LLmZpbmRhbGwodGV4dCk6CiAgICAgICAgICAgICAgICB5aWVsZCByYXcsICJodG1sLnN0eWxlc2hlZXQiLCBOb25lCgogICAgICAgIGVsaWYga2luZCA9PSAiaHRtbCI6CiAgICAgICAgICAgIGZvciByYXcgaW4gSFRNTF9TQ1JJUFQuZmluZGFsbCh0ZXh0KToKICAgICAgICAgICAgICAgIHlpZWxkIHJhdywgImh0bWwuc2NyaXB0IiwgTm9uZQoKICAgICAgICAgICAgZm9yIHJhdyBpbiBIVE1MX0xJTksuZmluZGFsbCh0ZXh0KToKICAgICAgICAgICAgICAgIHlpZWxkIHJhdywgImh0bWwuc3R5bGVzaGVldCIsIE5vbmUKCiAgICAgICAgZWxpZiBraW5kID09ICJjc3MiOgogICAgICAgICAgICBmb3IgcmF3IGluIENTU19JTVBPUlQuZmluZGFsbCh0ZXh0KToKICAgICAgICAgICAgICAgIHlpZWxkIHJhdywgImNzcy5pbXBvcnQiLCBOb25lCgogICAgICAgIGVsaWYga2luZCA9PSAiamF2YXNjcmlwdCI6CiAgICAgICAgICAgIGZvciBtYXRjaCBpbiBKU19JTVBPUlQuZmluZGFsbCh0ZXh0KToKICAgICAgICAgICAgICAgIHJhdyA9IG5leHQoKHZhbHVlIGZvciB2YWx1ZSBpbiBtYXRjaCBpZiB2YWx1ZSksICIiKQogICAgICAgICAgICAgICAgaWYgcmF3OgogICAgICAgICAgICAgICAgICAgIHlpZWxkIHJhdywgImpzLmltcG9ydCIsIE5vbmUKCiAgICAgICAgZWxpZiBraW5kID09ICJzaGVsbCI6CiAgICAgICAgICAgIGZvciByYXcgaW4gU0hFTExfU09VUkNFLmZpbmRhbGwodGV4dCk6CiAgICAgICAgICAgICAgICB5aWVsZCByYXcsICJzaGVsbC5zb3VyY2UiLCBOb25lCgogICAgICAgIGVsaWYga2luZCA9PSAicHl0aG9uIjoKICAgICAgICAgICAgZm9yIGZyb21fbW9kdWxlLCBpbXBvcnRfbW9kdWxlIGluIFBZVEhPTl9JTVBPUlQuZmluZGFsbCh0ZXh0KToKICAgICAgICAgICAgICAgIG1vZHVsZSA9IGZyb21fbW9kdWxlIG9yIGltcG9ydF9tb2R1bGUKICAgICAgICAgICAgICAgIGlmIG1vZHVsZToKICAgICAgICAgICAgICAgICAgICB5aWVsZCBtb2R1bGUucmVwbGFjZSgiLiIsICIvIikgKyAiLnB5IiwgInB5dGhvbi5pbXBvcnQiLCBOb25lCgogICAgZGVmIHNjYW4oc2VsZiwgZW50cmllczogbGlzdFtQYXRoXSkgLT4gZGljdDoKICAgICAgICBxdWV1ZTogZGVxdWVbUGF0aF0gPSBkZXF1ZShlbnRyaWVzKQoKICAgICAgICB3aGlsZSBxdWV1ZToKICAgICAgICAgICAgc291cmNlID0gcXVldWUucG9wbGVmdCgpLnJlc29sdmUoKQoKICAgICAgICAgICAgaWYgc291cmNlIGluIHNlbGYuc2Nhbm5lZCBvciBub3Qgc291cmNlLmlzX2ZpbGUoKToKICAgICAgICAgICAgICAgIGNvbnRpbnVlCgogICAgICAgICAgICBzZWxmLnNjYW5uZWQuYWRkKHNvdXJjZSkKICAgICAgICAgICAgc2VsZi5hZGRfbm9kZShzb3VyY2UpCgogICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICB0ZXh0ID0gc291cmNlLnJlYWRfdGV4dChlbmNvZGluZz0idXRmLTgiLCBlcnJvcnM9InJlcGxhY2UiKQogICAgICAgICAgICBleGNlcHQgT1NFcnJvciBhcyBlcnJvcjoKICAgICAgICAgICAgICAgIHNlbGYudW5yZXNvbHZlZC5hcHBlbmQoewogICAgICAgICAgICAgICAgICAgICJmcm9tIjogc2VsZi5yZWxhdGl2ZV9pZChzb3VyY2UpLAogICAgICAgICAgICAgICAgICAgICJyZWZlcmVuY2UiOiBzdHIoc291cmNlKSwKICAgICAgICAgICAgICAgICAgICAia2luZCI6ICJmaWxlLnJlYWQiLAogICAgICAgICAgICAgICAgICAgICJyZWFzb24iOiBzdHIoZXJyb3IpLAogICAgICAgICAgICAgICAgfSkKICAgICAgICAgICAgICAgIGNvbnRpbnVlCgogICAgICAgICAgICBmb3IgcmF3LCBraW5kLCBjb25zdGFudCBpbiBzZWxmLnJlZmVyZW5jZXMoc291cmNlLCB0ZXh0KToKICAgICAgICAgICAgICAgIHRhcmdldCA9IHNlbGYuYWRkX3JlZmVyZW5jZShzb3VyY2UsIHJhdywga2luZCwgY29uc3RhbnQpCiAgICAgICAgICAgICAgICBpZiB0YXJnZXQgaXMgbm90IE5vbmUgYW5kIHRhcmdldCBub3QgaW4gc2VsZi5zY2FubmVkOgogICAgICAgICAgICAgICAgICAgIHF1ZXVlLmFwcGVuZCh0YXJnZXQpCgogICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICJub2RlcyI6IHNvcnRlZChzZWxmLm5vZGVzLnZhbHVlcygpLCBrZXk9bGFtYmRhIGl0ZW06IGl0ZW1bImlkIl0pLAogICAgICAgICAgICAiZWRnZXMiOiBzb3J0ZWQoCiAgICAgICAgICAgICAgICBzZWxmLmVkZ2VzLAogICAgICAgICAgICAgICAga2V5PWxhbWJkYSBpdGVtOiAoaXRlbVsiZnJvbSJdLCBpdGVtWyJ0byJdLCBpdGVtWyJraW5kIl0pLAogICAgICAgICAgICApLAogICAgICAgICAgICAidW5yZXNvbHZlZCI6IHNvcnRlZCgKICAgICAgICAgICAgICAgIHNlbGYudW5yZXNvbHZlZCwKICAgICAgICAgICAgICAgIGtleT1sYW1iZGEgaXRlbTogKGl0ZW1bImZyb20iXSwgaXRlbVsicmVmZXJlbmNlIl0sIGl0ZW1bImtpbmQiXSksCiAgICAgICAgICAgICksCiAgICAgICAgICAgICJzdW1tYXJ5IjogewogICAgICAgICAgICAgICAgIm5vZGVfY291bnQiOiBsZW4oc2VsZi5ub2RlcyksCiAgICAgICAgICAgICAgICAiZWRnZV9jb3VudCI6IGxlbihzZWxmLmVkZ2VzKSwKICAgICAgICAgICAgICAgICJ1bnJlc29sdmVkX2NvdW50IjogbGVuKHNlbGYudW5yZXNvbHZlZCksCiAgICAgICAgICAgIH0sCiAgICAgICAgfQoKCmRlZiBtYWtlX3BhdGhfZGlzcGxheShyb290OiBQYXRoLCBtb2RlOiBzdHIpOgogICAgZGVmIGRpc3BsYXkobm9kZV9pZDogc3RyKSAtPiBzdHI6CiAgICAgICAgaWYgbm9kZV9pZC5zdGFydHN3aXRoKCJbZXh0ZXJuYWxdLyIpOgogICAgICAgICAgICByZXR1cm4gbm9kZV9pZAoKICAgICAgICBpZiBtb2RlID09ICJyZWxhdGl2ZSI6CiAgICAgICAgICAgIHJldHVybiBub2RlX2lkCgogICAgICAgIGlmIG1vZGUgPT0gInJvb3QiOgogICAgICAgICAgICByZXR1cm4gIiRST09ULyIgKyBub2RlX2lkCgogICAgICAgIHJldHVybiBzdHIoKHJvb3QgLyBub2RlX2lkKS5yZXNvbHZlKCkpCgogICAgcmV0dXJuIGRpc3BsYXkKCgpkZWYgcHJpbnRfdGV4dF9ncmFwaChncmFwaDogZGljdCwgZGlzcGxheSkgLT4gTm9uZToKICAgIGZvciBlZGdlIGluIGdyYXBoWyJlZGdlcyJdOgogICAgICAgIHN1ZmZpeCA9ICIiCiAgICAgICAgaWYgZWRnZS5nZXQoImNvbnN0YW50Iik6CiAgICAgICAgICAgIHN1ZmZpeCA9IGYiOyB7ZWRnZVsnY29uc3RhbnQnXX0iCiAgICAgICAgcHJpbnQoCiAgICAgICAgICAgIGYie2Rpc3BsYXkoZWRnZVsnZnJvbSddKX0gIgogICAgICAgICAgICBmIi0tW3tlZGdlWydraW5kJ119e3N1ZmZpeH1dLS0+ICIKICAgICAgICAgICAgZiJ7ZGlzcGxheShlZGdlWyd0byddKX0iCiAgICAgICAgKQoKICAgIGZvciBpdGVtIGluIGdyYXBoWyJ1bnJlc29sdmVkIl06CiAgICAgICAgcmVhc29uID0gZiI7IHtpdGVtWydyZWFzb24nXX0iIGlmIGl0ZW0uZ2V0KCJyZWFzb24iKSBlbHNlICIiCiAgICAgICAgY29uc3RhbnQgPSBmIjsge2l0ZW1bJ2NvbnN0YW50J119IiBpZiBpdGVtLmdldCgiY29uc3RhbnQiKSBlbHNlICIiCiAgICAgICAgcHJpbnQoCiAgICAgICAgICAgIGYie2Rpc3BsYXkoaXRlbVsnZnJvbSddKX0gIgogICAgICAgICAgICBmIi0tW3tpdGVtWydraW5kJ119OyB1bnJlc29sdmVke2NvbnN0YW50fXtyZWFzb259XS0tPiAiCiAgICAgICAgICAgIGYie2l0ZW1bJ3JlZmVyZW5jZSddfSIKICAgICAgICApCgogICAgcHJpbnQoanNvbi5kdW1wcyhncmFwaFsic3VtbWFyeSJdKSkKCgpkZWYgcHJpbnRfdHJlZShncmFwaDogZGljdCwgZW50cnlfaWRzOiBsaXN0W3N0cl0sIGRpc3BsYXkpIC0+IE5vbmU6CiAgICBub2RlcyA9IHtub2RlWyJpZCJdOiBub2RlIGZvciBub2RlIGluIGdyYXBoWyJub2RlcyJdfQogICAgY2hpbGRyZW46IGRpY3Rbc3RyLCBsaXN0W2RpY3RdXSA9IHt9CgogICAgZm9yIGVkZ2UgaW4gZ3JhcGhbImVkZ2VzIl06CiAgICAgICAgY2hpbGRyZW4uc2V0ZGVmYXVsdChlZGdlWyJmcm9tIl0sIFtdKS5hcHBlbmQoZWRnZSkKCiAgICBmb3Igc291cmNlX2lkIGluIGNoaWxkcmVuOgogICAgICAgIGNoaWxkcmVuW3NvdXJjZV9pZF0uc29ydChrZXk9bGFtYmRhIGVkZ2U6IChlZGdlWyJraW5kIl0sIGVkZ2VbInRvIl0pKQoKICAgIGRlZiB2aXNpdCgKICAgICAgICBub2RlX2lkOiBzdHIsCiAgICAgICAgcHJlZml4OiBzdHIgPSAiIiwKICAgICAgICBpc19sYXN0OiBib29sID0gVHJ1ZSwKICAgICAgICBzZWVuOiBzZXRbc3RyXSB8IE5vbmUgPSBOb25lLAogICAgICAgIHJlbGF0aW9uOiBzdHIgfCBOb25lID0gTm9uZSwKICAgICkgLT4gTm9uZToKICAgICAgICBzZWVuID0gc2V0KCkgaWYgc2VlbiBpcyBOb25lIGVsc2Ugc2VlbgogICAgICAgIG5vZGVfdHlwZSA9IG5vZGVzLmdldChub2RlX2lkLCB7fSkuZ2V0KCJ0eXBlIiwgInVua25vd24iKQoKICAgICAgICBpZiByZWxhdGlvbiBpcyBOb25lOgogICAgICAgICAgICBwcmludChmIntkaXNwbGF5KG5vZGVfaWQpfSBbe25vZGVfdHlwZX1dIikKICAgICAgICBlbHNlOgogICAgICAgICAgICBjb25uZWN0b3IgPSAi4pSU4pSAICIgaWYgaXNfbGFzdCBlbHNlICLilJzilIAgIgogICAgICAgICAgICBwcmludChmIntwcmVmaXh9e2Nvbm5lY3Rvcn17cmVsYXRpb259IC0+IHtkaXNwbGF5KG5vZGVfaWQpfSBbe25vZGVfdHlwZX1dIikKCiAgICAgICAgaWYgbm9kZV9pZCBpbiBzZWVuOgogICAgICAgICAgICBpZiByZWxhdGlvbiBpcyBub3QgTm9uZToKICAgICAgICAgICAgICAgIHByaW50KHByZWZpeCArICgiICAgIiBpZiBpc19sYXN0IGVsc2UgIuKUgiAgIikgKyAiW3NlZW5dIikKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIHByaW50KCJbc2Vlbl0iKQogICAgICAgICAgICByZXR1cm4KCiAgICAgICAgbmV4dF9zZWVuID0gc2VlbiB8IHtub2RlX2lkfQogICAgICAgIG91dGdvaW5nID0gY2hpbGRyZW4uZ2V0KG5vZGVfaWQsIFtdKQoKICAgICAgICBmb3IgaW5kZXgsIGVkZ2UgaW4gZW51bWVyYXRlKG91dGdvaW5nKToKICAgICAgICAgICAgY2hpbGRfaXNfbGFzdCA9IGluZGV4ID09IGxlbihvdXRnb2luZykgLSAxCiAgICAgICAgICAgIGNoaWxkX3ByZWZpeCA9IHByZWZpeAoKICAgICAgICAgICAgaWYgcmVsYXRpb24gaXMgbm90IE5vbmU6CiAgICAgICAgICAgICAgICBjaGlsZF9wcmVmaXggKz0gIiAgICIgaWYgaXNfbGFzdCBlbHNlICLilIIgICIKCiAgICAgICAgICAgIHZpc2l0KAogICAgICAgICAgICAgICAgZWRnZVsidG8iXSwKICAgICAgICAgICAgICAgIGNoaWxkX3ByZWZpeCwKICAgICAgICAgICAgICAgIGNoaWxkX2lzX2xhc3QsCiAgICAgICAgICAgICAgICBuZXh0X3NlZW4sCiAgICAgICAgICAgICAgICBlZGdlWyJraW5kIl0sCiAgICAgICAgICAgICkKCiAgICBmb3IgaW5kZXgsIGVudHJ5X2lkIGluIGVudW1lcmF0ZShlbnRyeV9pZHMpOgogICAgICAgIGlmIGluZGV4OgogICAgICAgICAgICBwcmludCgpCiAgICAgICAgdmlzaXQoZW50cnlfaWQpCgoKZGVmIHJlc29sdmVfZW50cmllcyhyb290OiBQYXRoLCByYXdfZW50cmllczogbGlzdFtzdHJdKSAtPiBsaXN0W1BhdGhdOgogICAgZW50cmllczogbGlzdFtQYXRoXSA9IFtdCgogICAgZm9yIGl0ZW0gaW4gcmF3X2VudHJpZXM6CiAgICAgICAgcGF0aCA9IFBhdGgoaXRlbSkuZXhwYW5kdXNlcigpCiAgICAgICAgZW50cmllcy5hcHBlbmQocGF0aC5yZXNvbHZlKCkgaWYgcGF0aC5pc19hYnNvbHV0ZSgpIGVsc2UgKHJvb3QgLyBwYXRoKS5yZXNvbHZlKCkpCgogICAgcmV0dXJuIGVudHJpZXMKCgpkZWYgbWFpbigpIC0+IGludDoKICAgIHBhcnNlciA9IGFyZ3BhcnNlLkFyZ3VtZW50UGFyc2VyKAogICAgICAgIGRlc2NyaXB0aW9uPSJOb24tZXhlY3V0aW5nIFRyYWNlRmxvdyBzdGF0aWMgZmlsZS1mbG93IHNjYW5uZXIiCiAgICApCgogICAgc3VicGFyc2VycyA9IHBhcnNlci5hZGRfc3VicGFyc2VycyhkZXN0PSJjb21tYW5kIiwgcmVxdWlyZWQ9VHJ1ZSkKCiAgICBkZWYgYWRkX2NvbW1vbl9hcmd1bWVudHMoY29tbWFuZF9wYXJzZXI6IGFyZ3BhcnNlLkFyZ3VtZW50UGFyc2VyKSAtPiBOb25lOgogICAgICAgIGNvbW1hbmRfcGFyc2VyLmFkZF9hcmd1bWVudCgKICAgICAgICAgICAgIi0tcm9vdCIsCiAgICAgICAgICAgIGRlZmF1bHQ9Ii4iLAogICAgICAgICAgICBoZWxwPSJQcm9qZWN0IHJvb3QgdXNlZCB0byByZXNvbHZlIGxvY2FsIHNvdXJjZSByZWZlcmVuY2VzIiwKICAgICAgICApCiAgICAgICAgY29tbWFuZF9wYXJzZXIuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1lbnRyeSIsCiAgICAgICAgICAgIGFjdGlvbj0iYXBwZW5kIiwKICAgICAgICAgICAgcmVxdWlyZWQ9VHJ1ZSwKICAgICAgICAgICAgaGVscD0iRW50cnkgZmlsZSByZWxhdGl2ZSB0byAtLXJvb3Q7IHNwZWNpZnkgbW9yZSB0aGFuIG9uY2UgZm9yIG11bHRpcGxlIHJvb3RzIiwKICAgICAgICApCiAgICAgICAgY29tbWFuZF9wYXJzZXIuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1jb25zdGFudC1wYXRoIiwKICAgICAgICAgICAgYWN0aW9uPSJhcHBlbmQiLAogICAgICAgICAgICBkZWZhdWx0PVtdLAogICAgICAgICAgICBtZXRhdmFyPSJOQU1FPVBBVEgiLAogICAgICAgICAgICBoZWxwPSJSZXNvbHZlIGEgUEhQIGNvbnN0YW50IHBhdGgsIGUuZy4gU1lTVEVNX1JPT1Q9L3BhdGgvdG8vc3lzdGVtIiwKICAgICAgICApCiAgICAgICAgY29tbWFuZF9wYXJzZXIuYWRkX2FyZ3VtZW50KAogICAgICAgICAgICAiLS1wYXRocyIsCiAgICAgICAgICAgIGNob2ljZXM9WyJyZWxhdGl2ZSIsICJyb290IiwgImFic29sdXRlIl0sCiAgICAgICAgICAgIGRlZmF1bHQ9InJlbGF0aXZlIiwKICAgICAgICAgICAgaGVscD0iUGF0aCBzdHlsZSBmb3IgdGV4dC90cmVlIG91dHB1dCIsCiAgICAgICAgKQoKICAgIHNjYW5fcGFyc2VyID0gc3VicGFyc2Vycy5hZGRfcGFyc2VyKAogICAgICAgICJzY2FuIiwKICAgICAgICBoZWxwPSJHZW5lcmF0ZSBhIGZsYXQgSlNPTiBvciB0ZXh0IGdyYXBoIiwKICAgICkKICAgIGFkZF9jb21tb25fYXJndW1lbnRzKHNjYW5fcGFyc2VyKQogICAgc2Nhbl9wYXJzZXIuYWRkX2FyZ3VtZW50KAogICAgICAgICItLWZvcm1hdCIsCiAgICAgICAgY2hvaWNlcz1bImpzb24iLCAidGV4dCJdLAogICAgICAgIGRlZmF1bHQ9Impzb24iLAogICAgICAgIGhlbHA9Ik91dHB1dCBmb3JtYXQgd2hlbiAtLW91dHB1dCBpcyBub3QgdXNlZCIsCiAgICApCiAgICBzY2FuX3BhcnNlci5hZGRfYXJndW1lbnQoCiAgICAgICAgIi0tb3V0cHV0IiwKICAgICAgICBoZWxwPSJXcml0ZSBKU09OIGdyYXBoIHRvIHRoaXMgZmlsZW5hbWUiLAogICAgKQoKICAgIHRyZWVfcGFyc2VyID0gc3VicGFyc2Vycy5hZGRfcGFyc2VyKAogICAgICAgICJ0cmVlIiwKICAgICAgICBoZWxwPSJSZW5kZXIgaGllcmFyY2h5IGZyb20gb25lIG9yIG1vcmUgZW50cnkgZmlsZXMiLAogICAgKQogICAgYWRkX2NvbW1vbl9hcmd1bWVudHModHJlZV9wYXJzZXIpCgogICAgYXJncyA9IHBhcnNlci5wYXJzZV9hcmdzKCkKCiAgICByb290ID0gUGF0aChhcmdzLnJvb3QpLmV4cGFuZHVzZXIoKS5yZXNvbHZlKCkKICAgIGlmIG5vdCByb290LmlzX2RpcigpOgogICAgICAgIHBhcnNlci5lcnJvcihmIi0tcm9vdCBpcyBub3QgYSBkaXJlY3Rvcnk6IHtyb290fSIpCgogICAgdHJ5OgogICAgICAgIGNvbnN0YW50X3BhdGhzID0gbm9ybWFsaXplX2NvbnN0YW50X3BhdGhzKGFyZ3MuY29uc3RhbnRfcGF0aCkKICAgIGV4Y2VwdCBWYWx1ZUVycm9yIGFzIGVycm9yOgogICAgICAgIHBhcnNlci5lcnJvcihzdHIoZXJyb3IpKQoKICAgIGVudHJpZXMgPSByZXNvbHZlX2VudHJpZXMocm9vdCwgYXJncy5lbnRyeSkKICAgIG1pc3NpbmcgPSBbc3RyKHBhdGgpIGZvciBwYXRoIGluIGVudHJpZXMgaWYgbm90IHBhdGguaXNfZmlsZSgpXQogICAgaWYgbWlzc2luZzoKICAgICAgICBwcmludCgiTWlzc2luZyBlbnRyeSBmaWxlKHMpOiAiICsgIiwgIi5qb2luKG1pc3NpbmcpLCBmaWxlPXN5cy5zdGRlcnIpCiAgICAgICAgcmV0dXJuIDIKCiAgICBzY2FubmVyID0gRmlsZUZsb3dTY2FubmVyKHJvb3QsIGNvbnN0YW50X3BhdGhzKQogICAgZ3JhcGggPSBzY2FubmVyLnNjYW4oZW50cmllcykKICAgIGRpc3BsYXkgPSBtYWtlX3BhdGhfZGlzcGxheShyb290LCBhcmdzLnBhdGhzKQoKICAgIGlmIGFyZ3MuY29tbWFuZCA9PSAidHJlZSI6CiAgICAgICAgZW50cnlfaWRzID0gW3NjYW5uZXIucmVsYXRpdmVfaWQocGF0aCkgZm9yIHBhdGggaW4gZW50cmllc10KICAgICAgICBwcmludF90cmVlKGdyYXBoLCBlbnRyeV9pZHMsIGRpc3BsYXkpCiAgICAgICAgcmV0dXJuIDAKCiAgICBpZiBhcmdzLmZvcm1hdCA9PSAidGV4dCI6CiAgICAgICAgcHJpbnRfdGV4dF9ncmFwaChncmFwaCwgZGlzcGxheSkKICAgICAgICByZXR1cm4gMAoKICAgIHJlbmRlcmVkID0ganNvbi5kdW1wcyhncmFwaCwgaW5kZW50PTIsIGVuc3VyZV9hc2NpaT1GYWxzZSkgKyAiXG4iCiAgICBpZiBhcmdzLm91dHB1dDoKICAgICAgICBvdXRwdXQgPSBQYXRoKGFyZ3Mub3V0cHV0KS5leHBhbmR1c2VyKCkKICAgICAgICBvdXRwdXQucGFyZW50Lm1rZGlyKHBhcmVudHM9VHJ1ZSwgZXhpc3Rfb2s9VHJ1ZSkKICAgICAgICBvdXRwdXQud3JpdGVfdGV4dChyZW5kZXJlZCwgZW5jb2Rpbmc9InV0Zi04IikKICAgIGVsc2U6CiAgICAgICAgcHJpbnQocmVuZGVyZWQsIGVuZD0iIikKCiAgICByZXR1cm4gMAoKCgpkZWYgbWFza19jb21tZW50cyh0ZXh0KToKICAgIHBhdHRlcm4gPSByZS5jb21waWxlKAogICAgICAgIHIiKCcoPzpcXC58W14nXFxdKSonfFwiKD86XFwufFteXCJcXF0pKlwiKSIKICAgICAgICByInwoL1wqW1xzXFNdKj9cKi98Ly9bXlxuXSp8XCNbXlxuXSopIgogICAgKQogICAgZGVmIHJlcGxhY2UobWF0Y2gpOgogICAgICAgIGlmIG1hdGNoLmdyb3VwKDEpOiByZXR1cm4gbWF0Y2guZ3JvdXAoMCkKICAgICAgICByZXR1cm4gJycuam9pbignXG4nIGlmIGM9PSdcbicgZWxzZSAnICcgZm9yIGMgaW4gbWF0Y2guZ3JvdXAoMCkpCiAgICByZXR1cm4gcGF0dGVybi5zdWIocmVwbGFjZSx0ZXh0KQoKZGVmIHNwbGl0X2V4cHJlc3Npb24oZXhwcik6CiAgICBwYXJ0cz1bXTsgYmVnaW49MDsgZGVwdGg9MDsgcXVvdGU9Tm9uZTsgZXNjYXBlPUZhbHNlCiAgICBmb3IgaSxjIGluIGVudW1lcmF0ZShleHByKToKICAgICAgICBpZiBxdW90ZToKICAgICAgICAgICAgaWYgZXNjYXBlOiBlc2NhcGU9RmFsc2UKICAgICAgICAgICAgZWxpZiBjPT0nXFwnOiBlc2NhcGU9VHJ1ZQogICAgICAgICAgICBlbGlmIGM9PXF1b3RlOiBxdW90ZT1Ob25lCiAgICAgICAgZWxpZiBjIGluICInXCIiOiBxdW90ZT1jCiAgICAgICAgZWxpZiBjPT0nKCc6IGRlcHRoKz0xCiAgICAgICAgZWxpZiBjPT0nKSc6IGRlcHRoLT0xCiAgICAgICAgZWxpZiBjPT0nLicgYW5kIGRlcHRoPT0wOgogICAgICAgICAgICBwYXJ0cy5hcHBlbmQoZXhwcltiZWdpbjppXSk7IGJlZ2luPWkrMQogICAgcGFydHMuYXBwZW5kKGV4cHJbYmVnaW46XSkKICAgIHJldHVybiBwYXJ0cwoKQVNTRVRfSEVMUEVSUz17J2FwcF91cmwnOidBUFBfUFVCTElDX1JPT1QnLCd2ZXJzaW9uZWRfc3lzdGVtX2Fzc2V0X3VybCc6J1BVQkxJQ19TWVNURU1fUk9PVCd9CgpkZWYgZXZhbHVhdGVfcGF0aChleHByLHNvdXJjZSx2YWx1ZXMpOgogICAgZXhwcj1leHByLnN0cmlwKCkKICAgIGlmIGV4cHIuc3RhcnRzd2l0aCgnKCcpIGFuZCBleHByLmVuZHN3aXRoKCcpJyk6CiAgICAgICAgcmV0dXJuIGV2YWx1YXRlX3BhdGgoZXhwclsxOi0xXSxzb3VyY2UsdmFsdWVzKQogICAgcGFydHM9c3BsaXRfZXhwcmVzc2lvbihleHByKQogICAgaWYgbGVuKHBhcnRzKT4xOgogICAgICAgIHJlc3VsdHM9W2V2YWx1YXRlX3BhdGgocCxzb3VyY2UsdmFsdWVzKSBmb3IgcCBpbiBwYXJ0c10KICAgICAgICByZXR1cm4gTm9uZSBpZiBhbnkodiBpcyBOb25lIGZvciB2IGluIHJlc3VsdHMpIGVsc2UgJycuam9pbihyZXN1bHRzKQogICAgaWYgbGVuKGV4cHIpPj0yIGFuZCBleHByWzBdIGluICInXCIiIGFuZCBleHByWy0xXT09ZXhwclswXToKICAgICAgICB2YWx1ZT1leHByWzE6LTFdCiAgICAgICAgaWYgZXhwclswXT09JyInOgogICAgICAgICAgICB1bmtub3duPUZhbHNlCiAgICAgICAgICAgIGRlZiBzdWIobSk6CiAgICAgICAgICAgICAgICBub25sb2NhbCB1bmtub3duCiAgICAgICAgICAgICAgICBrZXk9bS5ncm91cCgwKQogICAgICAgICAgICAgICAgaWYga2V5IG5vdCBpbiB2YWx1ZXM6IHVua25vd249VHJ1ZTsgcmV0dXJuIGtleQogICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlc1trZXldCiAgICAgICAgICAgIHZhbHVlPXJlLnN1YihyJ1wkW0EtWmEtel9dXHcqJyxzdWIsdmFsdWUpCiAgICAgICAgICAgIGlmIHVua25vd246IHJldHVybiBOb25lCiAgICAgICAgcmV0dXJuIHZhbHVlCiAgICBpZiBleHByPT0nX19ESVJfXyc6IHJldHVybiBzdHIoc291cmNlLnBhcmVudCkKICAgIGlmIGV4cHI9PSdfX0ZJTEVfXyc6IHJldHVybiBzdHIoc291cmNlKQogICAgaWYgZXhwcj09J0RJUkVDVE9SWV9TRVBBUkFUT1InOiByZXR1cm4gJy8nCiAgICBtPXJlLmZ1bGxtYXRjaChyJ2Rpcm5hbWVccypcKCguKj8pKD86LFxzKihcZCspKT9cKScsZXhwcixyZS5TKQogICAgaWYgbToKICAgICAgICB2PWV2YWx1YXRlX3BhdGgobVsxXSxzb3VyY2UsdmFsdWVzKQogICAgICAgIGlmIHYgaXMgTm9uZTogcmV0dXJuIE5vbmUKICAgICAgICBwPVBhdGgodikKICAgICAgICBmb3IgXyBpbiByYW5nZShpbnQobVsyXSBvciAxKSk6IHA9cC5wYXJlbnQKICAgICAgICByZXR1cm4gc3RyKHApCiAgICBtPXJlLmZ1bGxtYXRjaChyIihhcHBfdXJsfHZlcnNpb25lZF9zeXN0ZW1fYXNzZXRfdXJsKVxzKlwoXHMqWydcIl0oW14nXCJdKylbJ1wiXVxzKlwpIixleHByLHJlLlMpCiAgICBpZiBtOgogICAgICAgIGJhc2U9dmFsdWVzLmdldChBU1NFVF9IRUxQRVJTW21bMV1dKQogICAgICAgIGlmIGJhc2U6IHJldHVybiBzdHIoUGF0aChiYXNlKS9tWzJdLmxzdHJpcCgnLycpKQogICAgcmV0dXJuIHZhbHVlcy5nZXQoZXhwcikKCmRlZiBwYXJzZV9wYWdlX3NldHVwKGV4cHIsc291cmNlLHZhbHVlcyk6CiAgICBleHByPWV4cHIuc3RyaXAoKQogICAgaWYgbm90IChleHByLnN0YXJ0c3dpdGgoJ1snKSBhbmQgZXhwci5lbmRzd2l0aCgnXScpKToKICAgICAgICByZXR1cm4gRmFsc2UKICAgIGlubmVyPWV4cHJbMTotMV0KICAgIHBhcnRzPVtdOyBiZWdpbj0wOyBkZXB0aD0wOyBxdW90ZT1Ob25lOyBlc2NhcGU9RmFsc2UKICAgIGZvciBpLGMgaW4gZW51bWVyYXRlKGlubmVyKToKICAgICAgICBpZiBxdW90ZToKICAgICAgICAgICAgaWYgZXNjYXBlOiBlc2NhcGU9RmFsc2UKICAgICAgICAgICAgZWxpZiBjPT0nXFwnOiBlc2NhcGU9VHJ1ZQogICAgICAgICAgICBlbGlmIGM9PXF1b3RlOiBxdW90ZT1Ob25lCiAgICAgICAgZWxpZiBjIGluICInXCIiOiBxdW90ZT1jCiAgICAgICAgZWxpZiBjPT0nWyc6IGRlcHRoKz0xCiAgICAgICAgZWxpZiBjPT0nXSc6IGRlcHRoLT0xCiAgICAgICAgZWxpZiBjPT0nLCcgYW5kIGRlcHRoPT0wOgogICAgICAgICAgICBwYXJ0cy5hcHBlbmQoaW5uZXJbYmVnaW46aV0pOyBiZWdpbj1pKzEKICAgIHBhcnRzLmFwcGVuZChpbm5lcltiZWdpbjpdKQogICAgZm9yIHBhcnQgaW4gcGFydHM6CiAgICAgICAgcGFpcj1yZS5tYXRjaChyIlxzKlsnXCJdKFteJ1wiXSspWydcIl1ccyo9PlxzKiguKz8pXHMqJCIscGFydCxyZS5TKQogICAgICAgIGlmIHBhaXI6CiAgICAgICAgICAgIHZhbHVlc1siJHBhZ2VTZXR1cFsnIitwYWlyWzFdKyInXSJdPWV2YWx1YXRlX3BhdGgocGFpclsyXSxzb3VyY2UsdmFsdWVzKQogICAgcmV0dXJuIFRydWUKCmRlZiBpbXByb3ZlZF9yZWZlcmVuY2VzKHNlbGYscGF0aCx0ZXh0KToKICAgIGtpbmQ9c2VsZi5maWxlX3R5cGUocGF0aCkKICAgIGNsZWFuPW1hc2tfY29tbWVudHModGV4dCkgaWYga2luZCBpbiAoJ3BocCcsJ2phdmFzY3JpcHQnLCdjc3MnKSBlbHNlIHRleHQKICAgIGNsZWFuPXJlLnN1YihyJzwhLS1bXHNcU10qPy0tPicsbGFtYmRhIG06Jycuam9pbignXG4nIGlmIGM9PSdcbicgZWxzZSAnICcgZm9yIGMgaW4gbVswXSksY2xlYW4pCiAgICB2YWx1ZXM9e2s6c3RyKHYpIGZvciBrLHYgaW4gc2VsZi5jb25zdGFudF9wYXRocy5pdGVtcygpfQogICAgbWF0Y2hlcz1bXQogICAgaWYga2luZD09J3BocCc6CiAgICAgICAgdG9rZW5zPXJlLmNvbXBpbGUociIoP1A8aW5jbHVkZT5cYig/OmluY2x1ZGVfaWZfZXhpc3RzfGluY2x1ZGVfb25jZXxyZXF1aXJlX29uY2V8aW5jbHVkZXxyZXF1aXJlKVxiKVxzKig/UDxpZXhwcj5bXjtdKyk7fCg/OlxiY29uc3RccyspPyg/UDxhc3NpZ24+XCRbQS1aYS16X11cdyp8W0EtWl1bQS1aMC05X10qKVxzKj0oPyE9KVxzKig/UDxhZXhwcj5bXjtdKyk7fFxiZGVmaW5lXHMqXChccypbJ1wiXSg/UDxkZWZpbmU+W0EtWmEtel9dXHcqKVsnXCJdXHMqLFxzKig/UDxkZXhwcj5bXjtdKylcKVxzKjsiLHJlLlMpCiAgICAgICAgZm9yIG0gaW4gdG9rZW5zLmZpbmRpdGVyKGNsZWFuKToKICAgICAgICAgICAgaWYgbVsnaW5jbHVkZSddOgogICAgICAgICAgICAgICAgZXhwcmVzc2lvbj1tWydpZXhwciddLnN0cmlwKCkKICAgICAgICAgICAgICAgIHBhZ2VfbWF0Y2g9cmUuZnVsbG1hdGNoKHIiXChccypcJHBhZ2VTZXR1cFxbWydcIl1bXidcIl0rWydcIl1cXVxzKlwpIixleHByZXNzaW9uKQogICAgICAgICAgICAgICAgaWYgcGFnZV9tYXRjaDoKICAgICAgICAgICAgICAgICAgICBrZXlfbWF0Y2g9cmUuc2VhcmNoKHIiXCRwYWdlU2V0dXBcW1snXCJdKFteJ1wiXSspWydcIl1cXSIsZXhwcmVzc2lvbikKICAgICAgICAgICAgICAgICAgICBpZiBrZXlfbWF0Y2ggaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcy5hcHBlbmQoKG0uc3RhcnQoKSxleHByZXNzaW9uLCdwaHAuaW5jbHVkZScsTm9uZSxGYWxzZSxleHByZXNzaW9uKSkKICAgICAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgICAgICBrZXk9a2V5X21hdGNoLmdyb3VwKDEpCiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlPXZhbHVlcy5nZXQoIiRwYWdlU2V0dXBbJyIra2V5KyInXSIpCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIHZhbHVlIGlzIE5vbmU6IHZhbHVlPXZhbHVlcy5nZXQoa2V5KQogICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzLmFwcGVuZCgobS5zdGFydCgpLHZhbHVlIG9yIGV4cHJlc3Npb24sJ3BocC5pbmNsdWRlX2lmX2V4aXN0cycsTm9uZSx2YWx1ZSBpcyBub3QgTm9uZSxleHByZXNzaW9uKSkKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgdmFsdWU9ZXZhbHVhdGVfcGF0aChleHByZXNzaW9uLHBhdGgsdmFsdWVzKQogICAgICAgICAgICAgICAgICAgIG1hdGNoZXMuYXBwZW5kKChtLnN0YXJ0KCksdmFsdWUgb3IgZXhwcmVzc2lvbiwncGhwLmluY2x1ZGUnLE5vbmUsdmFsdWUgaXMgbm90IE5vbmUsZXhwcmVzc2lvbikpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBuYW1lPW1bJ2Fzc2lnbiddIG9yIG1bJ2RlZmluZSddCiAgICAgICAgICAgICAgICBjb25maWd1cmVkX3ZhbHVlPXZhbHVlcy5nZXQobmFtZSkKICAgICAgICAgICAgICAgIGlmIGNvbmZpZ3VyZWRfdmFsdWUgaXMgbm90IE5vbmU6IGNvbnRpbnVlCiAgICAgICAgICAgICAgICBpZiBuYW1lPT0nJHBhZ2VTZXR1cCc6CiAgICAgICAgICAgICAgICAgICAgcGFyc2VfcGFnZV9zZXR1cChtWydhZXhwciddLHBhdGgsdmFsdWVzKQogICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICB2YWx1ZXNbbmFtZV09ZXZhbHVhdGVfcGF0aChtWydhZXhwciddIG9yIG1bJ2RleHByJ10scGF0aCx2YWx1ZXMpCiAgICBhc3NldD1yZS5jb21waWxlKHIiIiI8KD9QPHRhZz5zY3JpcHR8bGluaylcYltePl0qP1xiKD86c3JjfGhyZWYpXHMqPVxzKlsnXCJdKD9QPHZhbHVlPjxcP3BocFxzKy4qP1w/Pnw8XD89Lio/XD8+fFteJ1wiXSspWydcIl0iIiIscmUuU3xyZS5JKQogICAgZm9yIG0gaW4gYXNzZXQuZmluZGl0ZXIoY2xlYW4pOgogICAgICAgIHZhbHVlPW1bJ3ZhbHVlJ10uc3RyaXAoKQogICAgICAgIGlmIHZhbHVlLnN0YXJ0c3dpdGgoJzwnKToKICAgICAgICAgICAgcGhwPXJlLnN1YihyJ148XD8oPzpwaHB8PSk/JywnJyx2YWx1ZSk7IHBocD1waHAucmVtb3Zlc3VmZml4KCc/PicpLnN0cmlwKCkKICAgICAgICAgICAgcmVzb2x2ZWQ9ZXZhbHVhdGVfcGF0aChwaHAscGF0aCx2YWx1ZXMpCiAgICAgICAgICAgIG1hdGNoZXMuYXBwZW5kKChtLnN0YXJ0KCkscmVzb2x2ZWQgb3IgcGhwLCdodG1sLicrKCdzY3JpcHQnIGlmIG1bJ3RhZyddLmxvd2VyKCk9PSdzY3JpcHQnIGVsc2UgJ3N0eWxlc2hlZXQnKSxOb25lLHJlc29sdmVkIGlzIG5vdCBOb25lLHBocCkpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgbWF0Y2hlcy5hcHBlbmQoKG0uc3RhcnQoKSx2YWx1ZSwnaHRtbC4nKygnc2NyaXB0JyBpZiBtWyd0YWcnXS5sb3dlcigpPT0nc2NyaXB0JyBlbHNlICdzdHlsZXNoZWV0JyksTm9uZSxUcnVlLHZhbHVlKSkKICAgIHBhdHRlcm5zPVtdCiAgICBpZiBraW5kPT0nY3NzJzogcGF0dGVybnMuYXBwZW5kKChDU1NfSU1QT1JULCdjc3MuaW1wb3J0JykpCiAgICBpZiBraW5kPT0namF2YXNjcmlwdCc6IHBhdHRlcm5zLmFwcGVuZCgoSlNfSU1QT1JULCdqcy5pbXBvcnQnKSkKICAgIGlmIGtpbmQ9PSdzaGVsbCc6IHBhdHRlcm5zLmFwcGVuZCgoU0hFTExfU09VUkNFLCdzaGVsbC5zb3VyY2UnKSkKICAgIGlmIGtpbmQ9PSdweXRob24nOiBwYXR0ZXJucy5hcHBlbmQoKFBZVEhPTl9JTVBPUlQsJ3B5dGhvbi5pbXBvcnQnKSkKICAgIGZvciBwYXR0ZXJuLHJlbGF0aW9uIGluIHBhdHRlcm5zOgogICAgICAgIGZvciBtIGluIHBhdHRlcm4uZmluZGl0ZXIoY2xlYW4pOgogICAgICAgICAgICByYXc9bmV4dCgodiBmb3IgdiBpbiBtLmdyb3VwcygpIGlmIHYpLCcnKQogICAgICAgICAgICBpZiBraW5kPT0ncHl0aG9uJzogcmF3PXJhdy5yZXBsYWNlKCcuJywnLycpKycucHknCiAgICAgICAgICAgIG1hdGNoZXMuYXBwZW5kKChtLnN0YXJ0KCkscmF3LHJlbGF0aW9uLE5vbmUsVHJ1ZSxyYXcpKQogICAgZm9yIHBvc2l0aW9uLHJhdyxyZWxhdGlvbixjb25zdGFudCxyZXNvbHZlZCxleHByZXNzaW9uIGluIHNvcnRlZChtYXRjaGVzKToKICAgICAgICBzZWxmLmN1cnJlbnRfbGluZT10ZXh0LmNvdW50KCdcbicsMCxwb3NpdGlvbikrMQogICAgICAgIHNlbGYuY3VycmVudF9leHByZXNzaW9uPWV4cHJlc3Npb24KICAgICAgICBzZWxmLmR5bmFtaWNfZXhwcmVzc2lvbj1ub3QgcmVzb2x2ZWQKICAgICAgICB5aWVsZCByYXcscmVsYXRpb24sY29uc3RhbnQKCl9vcmlnaW5hbF9hZGQ9RmlsZUZsb3dTY2FubmVyLmFkZF9yZWZlcmVuY2UKZGVmIGltcHJvdmVkX2FkZChzZWxmLHNvdXJjZSxyYXcsa2luZCxjb25zdGFudD1Ob25lKToKICAgIGlmIHNlbGYuZHluYW1pY19leHByZXNzaW9uOgogICAgICAgIHNlbGYudW5yZXNvbHZlZC5hcHBlbmQoeydmcm9tJzpzZWxmLmFkZF9ub2RlKHNvdXJjZSksJ3JlZmVyZW5jZSc6cmF3LCdraW5kJzpraW5kLCdyZWFzb24nOid1bnN1cHBvcnRlZF9keW5hbWljX2V4cHJlc3Npb24nLCdsaW5lJzpzZWxmLmN1cnJlbnRfbGluZSwnZXhwcmVzc2lvbic6c2VsZi5jdXJyZW50X2V4cHJlc3Npb259KQogICAgICAgIHJldHVybiBOb25lCiAgICBlYz1sZW4oc2VsZi5lZGdlcyk7IHVjPWxlbihzZWxmLnVucmVzb2x2ZWQpCiAgICB0YXJnZXQ9X29yaWdpbmFsX2FkZChzZWxmLHNvdXJjZSxyYXcsa2luZCxjb25zdGFudCkKICAgIGZvciByZWNvcmQgaW4gc2VsZi5lZGdlc1tlYzpdK3NlbGYudW5yZXNvbHZlZFt1YzpdOgogICAgICAgIHJlY29yZFsnbGluZSddPXNlbGYuY3VycmVudF9saW5lOyByZWNvcmRbJ2V4cHJlc3Npb24nXT1zZWxmLmN1cnJlbnRfZXhwcmVzc2lvbgogICAgcmV0dXJuIHRhcmdldAoKX29yaWdpbmFsX2NhbmRpZGF0ZXM9RmlsZUZsb3dTY2FubmVyLmNhbmRpZGF0ZV9wYXRocwpkZWYgaW1wcm92ZWRfY2FuZGlkYXRlcyhzZWxmLHNvdXJjZSxyYXcsa2luZCxjb25zdGFudCk6CiAgICBpZiBraW5kLnN0YXJ0c3dpdGgoJ2h0bWwuJyk6CiAgICAgICAgcmF3PXJhdy5zcGxpdCgnPycsMSlbMF0uc3BsaXQoJyMnLDEpWzBdCiAgICAgICAgaWYgcmF3LnN0YXJ0c3dpdGgoJy9fc3lzdGVtLycpOgogICAgICAgICAgICBiYXNlPXNlbGYuY29uc3RhbnRfcGF0aHMuZ2V0KCdQVUJMSUNfU1lTVEVNX1JPT1QnKQogICAgICAgICAgICBpZiBiYXNlOiByZXR1cm4gW2Jhc2UvcmF3LnJlbW92ZXByZWZpeCgnL19zeXN0ZW0vJyldCiAgICAgICAgaWYgUGF0aChyYXcpLmlzX2Fic29sdXRlKCk6IHJldHVybiBbUGF0aChyYXcpXQogICAgICAgIGlmIHJhdy5zdGFydHN3aXRoKCcvJyk6CiAgICAgICAgICAgIGJhc2U9c2VsZi5jb25zdGFudF9wYXRocy5nZXQoJ0FQUF9QVUJMSUNfUk9PVCcpCiAgICAgICAgICAgIGlmIGJhc2U6IHJldHVybiBbYmFzZS9yYXcubHN0cmlwKCcvJyldCiAgICBpZiBraW5kLnN0YXJ0c3dpdGgoJ3BocC4nKSBhbmQgUGF0aChyYXcpLmlzX2Fic29sdXRlKCk6IHJldHVybiBbUGF0aChyYXcpXQogICAgcmV0dXJuIF9vcmlnaW5hbF9jYW5kaWRhdGVzKHNlbGYsc291cmNlLHJhdyxraW5kLGNvbnN0YW50KQoKZGVmIGltcHJvdmVkX2lkKHNlbGYscGF0aCk6CiAgICB0cnk6IHJldHVybiBwYXRoLnJlc29sdmUoKS5yZWxhdGl2ZV90byhzZWxmLnJvb3QpLmFzX3Bvc2l4KCkKICAgIGV4Y2VwdCBWYWx1ZUVycm9yOiByZXR1cm4gc3RyKHBhdGgucmVzb2x2ZSgpKQoKRmlsZUZsb3dTY2FubmVyLnJlZmVyZW5jZXM9aW1wcm92ZWRfcmVmZXJlbmNlcwpGaWxlRmxvd1NjYW5uZXIuYWRkX3JlZmVyZW5jZT1pbXByb3ZlZF9hZGQKRmlsZUZsb3dTY2FubmVyLmNhbmRpZGF0ZV9wYXRocz1pbXByb3ZlZF9jYW5kaWRhdGVzCkZpbGVGbG93U2Nhbm5lci5yZWxhdGl2ZV9pZD1pbXByb3ZlZF9pZAoKZGVmIHByaW50X3RyZWUoZ3JhcGgsZW50cnlfaWRzLGRpc3BsYXkpOgogICAgY2hpbGRyZW49e30KICAgIGZvciByZWNvcmQgaW4gZ3JhcGhbJ2VkZ2VzJ10rZ3JhcGhbJ3VucmVzb2x2ZWQnXToKICAgICAgICBjaGlsZHJlbi5zZXRkZWZhdWx0KHJlY29yZFsnZnJvbSddLFtdKS5hcHBlbmQocmVjb3JkKQogICAgZm9yIHJlY29yZHMgaW4gY2hpbGRyZW4udmFsdWVzKCk6IHJlY29yZHMuc29ydChrZXk9bGFtYmRhIHI6ci5nZXQoJ2xpbmUnLDApKQogICAgZGVmIHZpc2l0KG5vZGUscHJlZml4LGFuY2VzdG9ycyk6CiAgICAgICAgcmVjb3Jkcz1jaGlsZHJlbi5nZXQobm9kZSxbXSkKICAgICAgICBmb3IgaSxyZWNvcmQgaW4gZW51bWVyYXRlKHJlY29yZHMpOgogICAgICAgICAgICBsYXN0PWk9PWxlbihyZWNvcmRzKS0xCiAgICAgICAgICAgIGNvbm5lY3Rvcj0n4pSU4pSAICcgaWYgbGFzdCBlbHNlICfilJzilIAgJwogICAgICAgICAgICBjb250aW51YXRpb249JyAgICcgaWYgbGFzdCBlbHNlICfilIIgICcKICAgICAgICAgICAgbGFiZWw9ZiJ7cmVjb3JkWydraW5kJ119OyBsaW5lIHtyZWNvcmQuZ2V0KCdsaW5lJywnPycpfSIKICAgICAgICAgICAgaWYgJ3RvJyBub3QgaW4gcmVjb3JkOgogICAgICAgICAgICAgICAgcHJpbnQocHJlZml4K2Nvbm5lY3RvcitmIlt7bGFiZWx9OyB7cmVjb3JkLmdldCgncmVhc29uJywndW5yZXNvbHZlZCcpfV0gIityZWNvcmRbJ3JlZmVyZW5jZSddKQogICAgICAgICAgICAgICAgY29udGludWUKICAgICAgICAgICAgdGFyZ2V0PXJlY29yZFsndG8nXTsgY3ljbGU9dGFyZ2V0IGluIGFuY2VzdG9ycwogICAgICAgICAgICBwcmludChwcmVmaXgrY29ubmVjdG9yK2YnW3tsYWJlbH1dICcrZGlzcGxheSh0YXJnZXQpKygnIFtjeWNsZV0nIGlmIGN5Y2xlIGVsc2UgJycpKQogICAgICAgICAgICBpZiBub3QgY3ljbGU6IHZpc2l0KHRhcmdldCxwcmVmaXgrY29udGludWF0aW9uLGFuY2VzdG9yc3x7dGFyZ2V0fSkKICAgIGZvciBlbnRyeSBpbiBlbnRyeV9pZHM6CiAgICAgICAgcHJpbnQoZGlzcGxheShlbnRyeSkrJyBbc3RhdGljIHNvdXJjZS1yZWZlcmVuY2UgdHJlZV0nKQogICAgICAgIHZpc2l0KGVudHJ5LCcnLHtlbnRyeX0pCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHJhaXNlIFN5c3RlbUV4aXQobWFpbigpKQo=', 'src/clean-tree.py': 'IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwppbXBvcnQgYXJncGFyc2UKaW1wb3J0IGpzb24KZnJvbSBwYXRobGliIGltcG9ydCBQYXRoCgpwID0gYXJncGFyc2UuQXJndW1lbnRQYXJzZXIoZGVzY3JpcHRpb249IlJlbmRlciByZXNvbHZlZCBzdGF0aWMgZGVwZW5kZW5jaWVzIikKcC5hZGRfYXJndW1lbnQoImdyYXBoIikKcC5hZGRfYXJndW1lbnQoIi0tZW50cnkiLCByZXF1aXJlZD1UcnVlKQpwLmFkZF9hcmd1bWVudCgiLS1vdXRwdXQiKQphID0gcC5wYXJzZV9hcmdzKCkKZyA9IGpzb24ubG9hZHMoUGF0aChhLmdyYXBoKS5yZWFkX3RleHQoKSkKY2hpbGRyZW4gPSB7fQpmb3IgZWRnZSBpbiBnWyJlZGdlcyJdOgogICAgY2hpbGRyZW4uc2V0ZGVmYXVsdChlZGdlWyJmcm9tIl0sIFtdKS5hcHBlbmQoZWRnZSkKZm9yIGVkZ2VzIGluIGNoaWxkcmVuLnZhbHVlcygpOgogICAgZWRnZXMuc29ydChrZXk9bGFtYmRhIGU6IGUuZ2V0KCJsaW5lIiwgMCkpCmxpbmVzID0gW2EuZW50cnldCmRlZiB3YWxrKG5vZGUsIHByZWZpeCwgYW5jZXN0b3JzKToKICAgIGVkZ2VzID0gY2hpbGRyZW4uZ2V0KG5vZGUsIFtdKQogICAgZm9yIGksIGVkZ2UgaW4gZW51bWVyYXRlKGVkZ2VzKToKICAgICAgICBsYXN0ID0gaSA9PSBsZW4oZWRnZXMpIC0gMQogICAgICAgIHRhcmdldCA9IGVkZ2VbInRvIl0KICAgICAgICBjeWNsZSA9IHRhcmdldCBpbiBhbmNlc3RvcnMKICAgICAgICBsaW5lcy5hcHBlbmQocHJlZml4ICsgKCLilJTilIDilIAgIiBpZiBsYXN0IGVsc2UgIuKUnOKUgOKUgCAiKSArIHRhcmdldAogICAgICAgICAgICAgICAgICAgICArICgiIFtjeWNsZV0iIGlmIGN5Y2xlIGVsc2UgIiIpKQogICAgICAgIGlmIG5vdCBjeWNsZToKICAgICAgICAgICAgd2Fsayh0YXJnZXQsIHByZWZpeCArICgiICAgICIgaWYgbGFzdCBlbHNlICLilIIgICAiKSwKICAgICAgICAgICAgICAgICBhbmNlc3RvcnMgfCB7dGFyZ2V0fSkKaWYgYS5lbnRyeSBub3QgaW4ge25bImlkIl0gZm9yIG4gaW4gZ1sibm9kZXMiXX06CiAgICBwLmVycm9yKCJFbnRyeSBpcyBub3QgcHJlc2VudCBpbiBncmFwaCIpCndhbGsoYS5lbnRyeSwgIiIsIHthLmVudHJ5fSkKcmVzdWx0ID0gIlxuIi5qb2luKGxpbmVzKSArICJcbiIKaWYgYS5vdXRwdXQ6CiAgICBQYXRoKGEub3V0cHV0KS53cml0ZV90ZXh0KHJlc3VsdCkKcHJpbnQocmVzdWx0LCBlbmQ9IiIpCnByaW50KCJSZXNvbHZlZCByZWZlcmVuY2VzIG9ubHk7IHVucmVzb2x2ZWQgY291bnQ6ICIKICAgICAgKyBzdHIobGVuKGcuZ2V0KCJ1bnJlc29sdmVkIiwgW10pKSkpCg==', 'tests/run-tests.sh': 'IyEvdXNyL2Jpbi9lbnYgYmFzaApzZXQgLWV1byBwaXBlZmFpbAoKU0NSSVBUX0RJUj0iJCgKICBDRFBBVEg9IGNkIC0tICIkKGRpcm5hbWUgLS0gIiR7QkFTSF9TT1VSQ0VbMF19IikiID4vZGV2L251bGwgMj4mMQogIHB3ZCAtUAopIgoKUk9PVD0iJCgKICBDRFBBVEg9IGNkIC0tICIkU0NSSVBUX0RJUi8uLiIgPi9kZXYvbnVsbCAyPiYxCiAgcHdkIC1QCikiCgpUTVA9IiQobWt0ZW1wIC1kICIke1RNUERJUjotL3RtcH0vdHJhY2VmbG93LXRlc3RzLlhYWFhYWCIpIgp0cmFwICdybSAtcmYgLS0gIiRUTVAiJyBFWElUCm1rZGlyIC1wIC0tICIkVE1QL2xvZ3MiCgpleHBvcnQgVFJBQ0VGTE9XX0xPR19ESVI9IiRUTVAvbG9ncyIKZXhwb3J0IFRSQUNFRkxPV19FTkFCTEVEPTEKCnBhc3M9MApmYWlsPTAKCm9rKCkgewogIHByaW50ZiAnUEFTUyAgJXNcbicgIiQxIgogIHBhc3M9JCgocGFzcyArIDEpKQp9CgpubygpIHsKICBwcmludGYgJ0ZBSUwgICVzXG4nICIkMSIgPiYyCiAgZmFpbD0kKChmYWlsICsgMSkpCn0KCmlmIGJhc2ggLW4gIiRST09UL2Jpbi90cmFjZWZsb3cuc2giOyB0aGVuCiAgb2sgJ0Jhc2ggc3ludGF4JwplbHNlCiAgbm8gJ0Jhc2ggc3ludGF4JwpmaQoKaWYgYmFzaCAtbiAiJFJPT1QvYmluL3RyYWNlZmxvdyI7IHRoZW4KICBvayAnQ0xJIHN5bnRheCcKZWxzZQogIG5vICdDTEkgc3ludGF4JwpmaQoKaWYgcHl0aG9uMyAtbSBweV9jb21waWxlIFwKICAiJFJPT1Qvc3JjL3RyYWNlZmxvdy5weSIgXAogICIkUk9PVC9zcmMvZmlsZWZsb3cucHkiOyB0aGVuCiAgb2sgJ1B5dGhvbiBzeW50YXgnCmVsc2UKICBubyAnUHl0aG9uIHN5bnRheCcKZmkKCmlmIGNvbW1hbmQgLXYgcGhwID4vZGV2L251bGwgMj4mMTsgdGhlbgogIGlmIHBocCAtbCAiJFJPT1Qvc3JjL1RyYWNlRmxvdy5waHAiID4vZGV2L251bGwgJiYKICAgICBwaHAgLWwgIiRST09UL2V4YW1wbGVzL3J1bnRpbWUtZmlsZS1mbG93LnBocCIgPi9kZXYvbnVsbDsgdGhlbgogICAgb2sgJ1BIUCBzeW50YXgnCiAgZWxzZQogICAgbm8gJ1BIUCBzeW50YXgnCiAgZmkKCiAgaWYgcGhwICIkUk9PVC9leGFtcGxlcy9ydW50aW1lLWZpbGUtZmxvdy5waHAiOyB0aGVuCiAgICBvayAnUEhQIGluY2x1ZGUgcnVudGltZSBjYXB0dXJlJwogIGVsc2UKICAgIG5vICdQSFAgaW5jbHVkZSBydW50aW1lIGNhcHR1cmUnCiAgZmkKZWxzZQogIHByaW50ZiAnU0tJUCAgUEhQIHVuYXZhaWxhYmxlXG4nCmZpCgppZiBjb21tYW5kIC12IG5vZGUgPi9kZXYvbnVsbCAyPiYxOyB0aGVuCiAgaWYgbm9kZSAtLWNoZWNrICIkUk9PVC9zcmMvdHJhY2VmbG93LmpzIiAmJgogICAgIG5vZGUgIiRST09UL3Rlc3RzL3Rlc3QtanMubWpzIjsgdGhlbgogICAgb2sgJ05vZGUvSlMgcmVzb3VyY2UgdGltaW5nJwogIGVsc2UKICAgIG5vICdOb2RlL0pTIHJlc291cmNlIHRpbWluZycKICBmaQplbHNlCiAgcHJpbnRmICdTS0lQICBOb2RlIHVuYXZhaWxhYmxlXG4nCmZpCgppZiAiJFJPT1QvZXhhbXBsZXMvZGVtby5zaCIgPi9kZXYvbnVsbDsgdGhlbgogIG9rICdDcm9zcy1sYW5ndWFnZSBkZW1vJwplbHNlCiAgbm8gJ0Nyb3NzLWxhbmd1YWdlIGRlbW8nCmZpCgppZiBweXRob24zICIkUk9PVC9zcmMvZmlsZWZsb3cucHkiIHNjYW4gXAogIC0tcm9vdCAiJFJPT1QiIFwKICAtLWVudHJ5IGV4YW1wbGVzL2Zsb3ctZGVtby9pbmRleC5waHAgXAogIC0tZW50cnkgZXhhbXBsZXMvZmxvdy1kZW1vL2Jpbi9qb2Iuc2ggXAogIC0tZW50cnkgZXhhbXBsZXMvZmxvdy1kZW1vL2pvYnMvaW1wb3J0ZXIucHkgXAogIC0tb3V0cHV0ICIkVE1QL2dyYXBoLmpzb24iICYmCiAgcHl0aG9uMyAtICIkVE1QL2dyYXBoLmpzb24iIDw8J1BZJwppbXBvcnQganNvbgppbXBvcnQgc3lzCgpncmFwaCA9IGpzb24ubG9hZChvcGVuKHN5cy5hcmd2WzFdLCBlbmNvZGluZz0idXRmLTgiKSkKCmtpbmRzID0ge2VkZ2VbImtpbmQiXSBmb3IgZWRnZSBpbiBncmFwaFsiZWRnZXMiXX0KCnJlcXVpcmVkID0gewogICAgInBocC5pbmNsdWRlIiwKICAgICJodG1sLnNjcmlwdCIsCiAgICAiaHRtbC5zdHlsZXNoZWV0IiwKICAgICJjc3MuaW1wb3J0IiwKICAgICJqcy5pbXBvcnQiLAogICAgInNoZWxsLnNvdXJjZSIsCiAgICAicHl0aG9uLmltcG9ydCIsCn0KCm1pc3NpbmcgPSByZXF1aXJlZCAtIGtpbmRzCgppZiBtaXNzaW5nOgogICAgcmFpc2UgU3lzdGVtRXhpdCgKICAgICAgICAiTWlzc2luZyBleHBlY3RlZCBzdGF0aWMtZmxvdyBlZGdlIHR5cGVzOiAiCiAgICAgICAgKyAiLCAiLmpvaW4oc29ydGVkKG1pc3NpbmcpKQogICAgKQpQWQp0aGVuCiAgb2sgJ1N0YXRpYyBmaWxlLWZsb3cgc2NhbicKZWxzZQogIG5vICdTdGF0aWMgZmlsZS1mbG93IHNjYW4nCmZpCgppZiBweXRob24zICIkUk9PVC9zcmMvZmlsZWZsb3cucHkiIHRyZWUgXAogIC0tcm9vdCAiJFJPT1QiIFwKICAtLWVudHJ5IGV4YW1wbGVzL2Zsb3ctZGVtby9pbmRleC5waHAgXAogIC0tcGF0aHMgcm9vdCA+IiRUTVAvdHJlZS50eHQiICYmCiAgZ3JlcCAtRnEgJyRST09UL2V4YW1wbGVzL2Zsb3ctZGVtby9hcHAvYm9vdHN0cmFwLnBocCcgIiRUTVAvdHJlZS50eHQiOyB0aGVuCiAgb2sgJ1N0YXRpYyBoaWVyYXJjaHkgdHJlZSBhbmQgcm9vdCBwYXRocycKZWxzZQogIG5vICdTdGF0aWMgaGllcmFyY2h5IHRyZWUgYW5kIHJvb3QgcGF0aHMnCmZpCgppZiAiJFJPT1QvYmluL3RyYWNlZmxvdyIgdmFsaWRhdGU7IHRoZW4KICBvayAnSlNPTkwgdmFsaWRhdGlvbicKZWxzZQogIG5vICdKU09OTCB2YWxpZGF0aW9uJwpmaQoKdHJhY2VfY291bnQ9IiQoCiAgIiRST09UL2Jpbi90cmFjZWZsb3ciIGxpc3QgfAogIHNlZCAnL15bWzpzcGFjZTpdXSokL2QnIHwKICB3YyAtbCB8CiAgdHIgLWQgJ1s6c3BhY2U6XScKKSIKCmlmIFtbICIkdHJhY2VfY291bnQiIC1nZSAxIF1dOyB0aGVuCiAgb2sgJ1RyYWNlIENMSSBsaXN0JwplbHNlCiAgbm8gJ1RyYWNlIENMSSBsaXN0JwpmaQoKcHJpbnRmICdcblJlc3VsdHM6ICVzIHBhc3NlZDsgJXMgZmFpbGVkXG4nICIkcGFzcyIgIiRmYWlsIgoKW1sgIiRmYWlsIiAtZXEgMCBdXQo=', 'run.static.sh': 'IyEvdXNyL2Jpbi9lbnYgYmFzaApzZXQgLWVvIHBpcGVmYWlsCgpIRVJFPSIkKENEUEFUSD0gY2QgLS0gIiQoZGlybmFtZSAtLSAiJHtCQVNIX1NPVVJDRVswXX0iKSIgJiYgcHdkIC1QKSIKYXBwVGVzdD0iJHsxOi1kZWZhcHB9IgoKaWYgW1sgISAiJGFwcFRlc3QiID1+IF5bQS1aYS16MC05Xy1dKyQgXV07IHRoZW4KICAgIHByaW50ZiAnSW52YWxpZCBhcHBsaWNhdGlvbiBuYW1lOiAlc1xuJyAiJGFwcFRlc3QiID4mMgogICAgZXhpdCAyCmZpCgpsYXlvdXRSb290PSIkKGRpcm5hbWUgIiQoZGlybmFtZSAiJEhFUkUiKSIpIgpzeXN0ZW1Db25maWc9IiRsYXlvdXRSb290L3N5c3RlbS9jb25maWcvLmVudiIKYXBwQ29uZmlnPSIkbGF5b3V0Um9vdC9zeXN0ZW0vY29uZmlnL2FwcHMvJGFwcFRlc3QvLmVudiIKCmZvciBlbnZGaWxlIGluICIkc3lzdGVtQ29uZmlnIiAiJGFwcENvbmZpZyI7IGRvCiAgICBpZiBbWyAhIC1yICIkZW52RmlsZSIgXV07IHRoZW4KICAgICAgICBwcmludGYgJ01pc3Npbmcgb3IgdW5yZWFkYWJsZSBjb25maWd1cmF0aW9uOiAlc1xuJyAiJGVudkZpbGUiID4mMgogICAgICAgIGV4aXQgMgogICAgZmkKZG9uZQoKc291cmNlICIkc3lzdGVtQ29uZmlnIgpzb3VyY2UgIiRhcHBDb25maWciCnNldCAtdQoKc2NhblJvb3Q9IiR7VFJBQ0VGTE9XX1NDQU5fUk9PVDotJGxheW91dFJvb3R9IgphcHBzQmFzZT0iJHtBUFBTX0JBU0U6LSR7QVBQU19ST09UOi0kbGF5b3V0Um9vdC9hcHBzfX0iCmFwcERpcj0iJGFwcHNCYXNlLyRhcHBUZXN0IgplbnRyeT0iJHtUUkFDRUZMT1dfRU5UUlk6LSRhcHBEaXIvJGFwcFRlc3QuaW5kZXgucGhwfSIKCmlmIFtbICEgLWYgIiRlbnRyeSIgXV07IHRoZW4KICAgIHByaW50ZiAnTWlzc2luZyBhcHBsaWNhdGlvbiBlbnRyeTogJXNcbicgIiRlbnRyeSIgPiYyCiAgICBleGl0IDIKZmkKCmFyZ3M9KC0tcm9vdCAiJHNjYW5Sb290IiAtLWVudHJ5ICIkZW50cnkiKQoKZm9yIG5hbWUgaW4gU1lTVEVNX1JPT1QgQVBQX1JPT1QgVEVNUExBVEVfUk9PVDsgZG8KICAgIHZhbHVlPSIkeyFuYW1lOi19IgogICAgaWYgW1sgLW4gIiR2YWx1ZSIgXV07IHRoZW4KICAgICAgICBhcmdzKz0oLS1jb25zdGFudC1wYXRoICIkbmFtZT0kdmFsdWUiKQogICAgZmkKZG9uZQoKY2QgIiRIRVJFIgpta2RpciAtcCBzdG9yYWdlCgpwcmludGYgJ1xuQXBwbGljYXRpb246ICVzXG5FbnRyeTogJXNcblxuJyAiJGFwcFRlc3QiICIkZW50cnkiCnB5dGhvbjMgc3JjL2ZpbGVmbG93LnB5IHNjYW4gIiR7YXJnc1tAXX0iIC0tb3V0cHV0ICJzdG9yYWdlLyRhcHBUZXN0LnN0YXRpYy5qc29uIgpweXRob24zIHNyYy9maWxlZmxvdy5weSB0cmVlICIke2FyZ3NbQF19IiAtLXBhdGhzIHJvb3QgPiAic3RvcmFnZS8kYXBwVGVzdC5kZXRhaWxlZC50eHQiCmNhdCAic3RvcmFnZS8kYXBwVGVzdC5kZXRhaWxlZC50eHQiCgplbnRyeUlkPSIkKHB5dGhvbjMgLSAiJHNjYW5Sb290IiAiJGVudHJ5IiA8PCdQWScKZnJvbSBwYXRobGliIGltcG9ydCBQYXRoCmltcG9ydCBzeXMKcm9vdD1QYXRoKHN5cy5hcmd2WzFdKS5yZXNvbHZlKCk7IGVudHJ5PVBhdGgoc3lzLmFyZ3ZbMl0pLnJlc29sdmUoKQp0cnk6IHByaW50KGVudHJ5LnJlbGF0aXZlX3RvKHJvb3QpLmFzX3Bvc2l4KCkpCmV4Y2VwdCBWYWx1ZUVycm9yOiBwcmludChlbnRyeSkKUFkKKSIKCnByaW50ZiAnXG5DbGVhbiBkZXBlbmRlbmN5IHRyZWU6XG5cbicKcHl0aG9uMyBzcmMvY2xlYW4tdHJlZS5weSAic3RvcmFnZS8kYXBwVGVzdC5zdGF0aWMuanNvbiIgLS1lbnRyeSAiJGVudHJ5SWQiIC0tb3V0cHV0ICJzdG9yYWdlLyRhcHBUZXN0LnRyZWUudHh0Igo=', 'docs/STATIC-SCANNER.md': 'IyBUcmFjZUZsb3cgU3RhdGljIFNjYW5uZXIgVXBkYXRlCgpUaGlzIHVwZGF0ZSBpbXByb3ZlcyBzdGF0aWMgZGVwZW5kZW5jeSBkaXNjb3Zlcnkgb25seS4gSXQgZG9lcyBub3QKZXhlY3V0ZSBhcHBsaWNhdGlvbiBjb2RlIGFuZCBkb2VzIG5vdCBjaGFuZ2UgcnVudGltZSB0cmFjaW5nIGZpbGVzLgoKIyMgSW5zdGFsbGVkIGZpbGVzCgotIHNyYy9maWxlZmxvdy5weQotIHNyYy9jbGVhbi10cmVlLnB5Ci0gdGVzdHMvcnVuLXRlc3RzLnNoCi0gcnVuLnN0YXRpYy5zaAotIGRvY3MvU1RBVElDLVNDQU5ORVIubWQKCkV4aXN0aW5nIGZpbGVzIGFyZSBiYWNrZWQgdXAgdW5kZXIgYmFja3Vwcy9zdGF0aWMtc2Nhbm5lci08dGltZXN0YW1wPi8uCgojIyBXaGF0IHRoZSBzY2FubmVyIHJlc29sdmVzCgotIFBIUCBpbmNsdWRlLCBpbmNsdWRlX29uY2UsIHJlcXVpcmUsIGFuZCByZXF1aXJlX29uY2UuCi0gTGl0ZXJhbCBwYXRocywgX19ESVJfXywgX19GSUxFX18sIERJUkVDVE9SWV9TRVBBUkFUT1IsIGFuZCBkaXJuYW1lKCkuCi0gU3VwcG9ydGVkIGNvbnN0YW50cyBhbmQgdmFyaWFibGUgcGF0aCBhc3NpZ25tZW50cy4KLSBpbmNsdWRlX2lmX2V4aXN0cygkcGFnZVNldHVwWydrZXknXSkgdmFsdWVzLgotIGFwcF91cmwoJ3BhdGgnKSB1c2luZyBBUFBfUFVCTElDX1JPT1QuCi0gdmVyc2lvbmVkX3N5c3RlbV9hc3NldF91cmwoJ3BhdGgnKSB1c2luZyBQVUJMSUNfU1lTVEVNX1JPT1QuCi0gTGl0ZXJhbCAvX3N5c3RlbS8gVVJMcyB1c2luZyBQVUJMSUNfU1lTVEVNX1JPT1QuCi0gSFRNTCBzY3JpcHQgYW5kIHN0eWxlc2hlZXQgcmVmZXJlbmNlcy4KLSBDU1MgQGltcG9ydCBhbmQgc3VwcG9ydGVkIEphdmFTY3JpcHQgaW1wb3J0cy4KLSBTb3VyY2UgbGluZSBudW1iZXJzIGFuZCBzb3VyY2UtcmVmZXJlbmNlIG9yZGVyLgotIE1pc3NpbmcgZmlsZXMgYW5kIHVuc3VwcG9ydGVkIGR5bmFtaWMgZXhwcmVzc2lvbnMuCgojIyBDb25maWd1cmF0aW9uIG1hcHBpbmdzCgpQYXNzIHRoZXNlIHNjYW5uZXIgbWFwcGluZ3Mgd2hlbiBuZWVkZWQ6CgotIFNZU1RFTV9ST09UPS9wYXRoL3RvL3N5c3RlbQotIEFQUF9QVUJMSUNfUk9PVD0vcGF0aC90by9hcHBzL0FQUE5BTUUKLSBQVUJMSUNfU1lTVEVNX1JPT1Q9L3BhdGgvdG8vYXBwcy9fc3lzdGVtCgpydW4uc3RhdGljLnNoIHBhc3NlcyBTWVNURU1fUk9PVCwgQVBQX1JPT1QsIGFuZCBURU1QTEFURV9ST09UIGZyb20gdGhlCmxvYWRlZCBlbnZpcm9ubWVudCB3aGVuIHRob3NlIHZhbHVlcyBhcmUgc2V0LgoKIyMgUnVuIHRlc3RzCgpgYGBiYXNoCmJhc2ggdGVzdHMvcnVuLXRlc3RzLnNoCmBgYAoKIyMgU2NhbiBhbiBhcHBsaWNhdGlvbgoKYGBgYmFzaApiYXNoIHJ1bi5zdGF0aWMuc2ggZGVmYXBwCmJhc2ggcnVuLnN0YXRpYy5zaCB3ZWF0aGVyZGFzaApgYGAKCk91dHB1dHMgYXJlIHdyaXR0ZW4gdG8gc3RvcmFnZS86CgotIEFQUE5BTUUuc3RhdGljLmpzb24KLSBBUFBOQU1FLmRldGFpbGVkLnR4dAotIEFQUE5BTUUudHJlZS50eHQKCiMjIENsZWFuIHRyZWUKClRoZSBjbGVhbiB0cmVlIHNob3dzIHJlc29sdmVkIGZpbGVzIG9ubHkuIEl0IGlzIG5vdCBhbiBleGVjdXRpb24gb3JkZXIuCgpgYGBiYXNoCnB5dGhvbjMgc3JjL2NsZWFuLXRyZWUucHkgXAogIHN0b3JhZ2UvZGVmYXBwLnN0YXRpYy5qc29uIFwKICAtLWVudHJ5IGFwcHMvZGVmYXBwL2RlZmFwcC5pbmRleC5waHAgXAogIC0tb3V0cHV0IHN0b3JhZ2UvZGVmYXBwLnRyZWUudHh0CmBgYAoKIyMgS25vd24gbGltaXRzCgpUaGlzIGlzIGEgbGlnaHR3ZWlnaHQgc3RhdGljIHRleHQgc2Nhbm5lciwgbm90IGEgUEhQIHBhcnNlci4KCkl0IGRvZXMgbm90IHlldCByZXNvbHZlOgoKLSBhc3NldHNfY3NzX2Jsb2NrKCkgb3IgYXNzZXRzX2pzX2Jsb2NrKCkgZ2VuZXJhdGVkIGFzc2V0cy4KLSBDb21wbGV4IGNvbmRpdGlvbmFsIG9yIGZ1bmN0aW9uLXNjb3BlZCBjb25maWd1cmF0aW9uLgotIER5bmFtaWMgVVJMcyBwcm9kdWNlZCBieSBhcmJpdHJhcnkgaGVscGVycy4KLSBGdWxsIHJ1bnRpbWUgZXhlY3V0aW9uIG9yZGVyLgotIEZyYW1ld29yayBhdXRvbG9hZGVycyBvciBidW5kbGVyIGFsaWFzZXMuCgpNaXNzaW5nIGZpbGVzIGFyZSByZXBvcnRlZCBzZXBhcmF0ZWx5IGZyb20gZXhwcmVzc2lvbnMgdGhlIHNjYW5uZXIKY2Fubm90IHJlc29sdmUuCgojIyBWYWxpZGF0aW9uCgpUaGUgaW5zdGFsbGVyIHZhbGlkYXRlcyBQeXRob24gc3ludGF4LiBUaGUgc2Nhbm5lciB3YXMgdGVzdGVkIGFnYWluc3QKYSBmb2N1c2VkIGZpeHR1cmUgY292ZXJpbmcgUEhQIGluY2x1ZGVzLCBhcHAgQ1NTLCBzaGFyZWQgSmF2YVNjcmlwdCwKbGl0ZXJhbCBzaGFyZWQgVVJMcywgcGFnZS1zZXR1cCBpbmNsdWRlcywgY29tbWVudHMsIGFuZCB1bnJlc29sdmVkCmV4cHJlc3Npb25zLgoKUnVuIHRoZSBmdWxsIGxvY2FsIHN1aXRlIGFuZCBhcHBsaWNhdGlvbiBzY2FucyBiZWZvcmUgcmVseWluZyBvbiB0aGUKcmVzdWx0cy4K'}
for name, encoded in files.items():
    target = Path(name)
    target.parent.mkdir(parents=True, exist_ok=True)
    target.write_bytes(base64.b64decode(encoded))
    print("Installed:", name)

py_compile.compile("src/fileflow.py", doraise=True)
py_compile.compile("src/clean-tree.py", doraise=True)
print("Python syntax validation passed.")
PY

chmod +x tests/run-tests.sh run.static.sh
printf '\nBackup: %s\n' "$backup"
printf 'Installation complete.\n'
printf 'Next:\n  bash tests/run-tests.sh\n  bash run.static.sh defapp\n'
