#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" DIST_DIR="${ROOT_DIR}/dist" REPO_DIR="${DIST_DIR}/repo" PLUGIN_ADDON_XML="${ROOT_DIR}/addon/addon.xml" REPO_SRC_DIR="${ROOT_DIR}/repository.viewit" REPO_ADDON_XML="${REPO_SRC_DIR}/addon.xml" REPO_BASE_URL="${REPO_BASE_URL:-http://127.0.0.1:8080/repo}" if [[ ! -f "${PLUGIN_ADDON_XML}" ]]; then echo "Missing: ${PLUGIN_ADDON_XML}" >&2 exit 1 fi if [[ ! -f "${REPO_ADDON_XML}" ]]; then echo "Missing: ${REPO_ADDON_XML}" >&2 exit 1 fi mkdir -p "${REPO_DIR}" read -r ADDON_ID ADDON_VERSION < <(python3 - "${PLUGIN_ADDON_XML}" <<'PY' import sys import xml.etree.ElementTree as ET root = ET.parse(sys.argv[1]).getroot() print(root.attrib.get("id", "plugin.video.viewit"), root.attrib.get("version", "0.0.0")) PY ) PLUGIN_ZIP="$("${ROOT_DIR}/scripts/build_kodi_zip.sh")" PLUGIN_ZIP_NAME="$(basename "${PLUGIN_ZIP}")" PLUGIN_ADDON_DIR_IN_REPO="${REPO_DIR}/${ADDON_ID}" mkdir -p "${PLUGIN_ADDON_DIR_IN_REPO}" cp -f "${PLUGIN_ZIP}" "${PLUGIN_ADDON_DIR_IN_REPO}/${PLUGIN_ZIP_NAME}" read -r REPO_ADDON_ID REPO_ADDON_VERSION < <(python3 - "${REPO_ADDON_XML}" <<'PY' import sys import xml.etree.ElementTree as ET root = ET.parse(sys.argv[1]).getroot() print(root.attrib.get("id", "repository.viewit"), root.attrib.get("version", "0.0.0")) PY ) TMP_DIR="$(mktemp -d)" trap 'rm -rf "${TMP_DIR}"' EXIT TMP_REPO_ADDON_DIR="${TMP_DIR}/${REPO_ADDON_ID}" mkdir -p "${TMP_REPO_ADDON_DIR}" if command -v rsync >/dev/null 2>&1; then rsync -a --delete "${REPO_SRC_DIR}/" "${TMP_REPO_ADDON_DIR}/" else cp -a "${REPO_SRC_DIR}/." "${TMP_REPO_ADDON_DIR}/" fi python3 - "${TMP_REPO_ADDON_DIR}/addon.xml" "${REPO_BASE_URL}" <<'PY' import sys import xml.etree.ElementTree as ET addon_xml = sys.argv[1] base_url = sys.argv[2].rstrip("/") tree = ET.parse(addon_xml) root = tree.getroot() dir_node = root.find(".//dir") if dir_node is None: raise SystemExit("Invalid repository addon.xml: missing ") info = dir_node.find("info") checksum = dir_node.find("checksum") datadir = dir_node.find("datadir") if info is None or checksum is None or datadir is None: raise SystemExit("Invalid repository addon.xml: missing info/checksum/datadir") info.text = f"{base_url}/addons.xml" checksum.text = f"{base_url}/addons.xml.md5" datadir.text = f"{base_url}/" tree.write(addon_xml, encoding="utf-8", xml_declaration=True) PY REPO_ZIP_NAME="${REPO_ADDON_ID}-${REPO_ADDON_VERSION}.zip" REPO_ZIP_PATH="${REPO_DIR}/${REPO_ZIP_NAME}" rm -f "${REPO_ZIP_PATH}" python3 "${ROOT_DIR}/scripts/zip_deterministic.py" "${REPO_ZIP_PATH}" "${TMP_REPO_ADDON_DIR}" >/dev/null REPO_ADDON_DIR_IN_REPO="${REPO_DIR}/${REPO_ADDON_ID}" mkdir -p "${REPO_ADDON_DIR_IN_REPO}" cp -f "${REPO_ZIP_PATH}" "${REPO_ADDON_DIR_IN_REPO}/${REPO_ZIP_NAME}" python3 - "${PLUGIN_ADDON_XML}" "${TMP_REPO_ADDON_DIR}/addon.xml" "${REPO_DIR}/addons.xml" <<'PY' import sys import xml.etree.ElementTree as ET from pathlib import Path plugin_xml = Path(sys.argv[1]) repo_xml = Path(sys.argv[2]) target = Path(sys.argv[3]) addons = ET.Element("addons") for source in (plugin_xml, repo_xml): root = ET.parse(source).getroot() addons.append(root) target.write_text('\n' + ET.tostring(addons, encoding="unicode"), encoding="utf-8") PY python3 - "${REPO_DIR}/addons.xml" "${REPO_DIR}/addons.xml.md5" <<'PY' import hashlib import sys from pathlib import Path addons_xml = Path(sys.argv[1]) md5_file = Path(sys.argv[2]) md5 = hashlib.md5(addons_xml.read_bytes()).hexdigest() md5_file.write_text(md5, encoding="ascii") PY python3 "${ROOT_DIR}/scripts/verify_repo_artifacts.py" "${REPO_DIR}" >/dev/null echo "Repo built:" echo " ${REPO_DIR}/addons.xml" echo " ${REPO_DIR}/addons.xml.md5" echo " ${REPO_ZIP_PATH}" echo " ${PLUGIN_ADDON_DIR_IN_REPO}/${PLUGIN_ZIP_NAME}" echo " ${REPO_ADDON_DIR_IN_REPO}/${REPO_ZIP_NAME}"