#!/bin/sh
# alloy-layer-repos — fence the first boot's layering to the carried repo.
#
# alloy-layer-components.service installs the console and terminal from
# /usr/share/alloy/rpm, a file:// repo that ships on the medium precisely so an
# offline install produces a working machine (docs/STACK.md, Hotfixes). It did
# not. rpm-ostree refreshes metadata for every ENABLED repo before it
# depsolves, and the image leaves Fedora's own four enabled, so a first boot
# with no name resolution failed like this and left the machine with no
# console:
#
#   error: Updating rpm-md repo 'fedora-cisco-openh264': Cannot prepare
#   internal mirrorlist: Curl error (6): Could not resolve hostname for
#   https://mirrors.fedoraproject.org/metalink?repo=fedora-cisco-openh264-43
#
# Measured 2026-08-25 on an installed server-profile machine in qemu, and
# reproduced by hand afterwards, so it is not a boot-ordering race.
#
# WHY THE FLAGS ARE NOT THE ANSWER. Both levers rpm-ostree offers are refused
# outside a container build, which docs/STACK.md already records for the first
# of them:
#
#   # rpm-ostree install --enablerepo=alloy-local alloy
#   error: --enablerepo currently only works in a container build
#   # rpm-ostree install --disablerepo="*" alloy
#   error: --disablerepo currently only works in a container build
#
# `--cache-only` is not the answer either: it reads cached metadata and
# refreshes none, so on a machine that has never refreshed anything it answers
# `error: Packages not found: alloy` with the packages sitting on the disk.
#
# So the repo set the daemon reads is the only lever, and this moves it for the
# length of one transaction. `off` disables everything but the carried repo;
# `on` puts /etc back. Both are idempotent.
#
# WHY `on` COPIES FROM /usr/etc RATHER THAN FROM A BACKUP. /usr/etc is the
# image's own /etc, so it is authoritative and it is always there. A backup in
# /run is not: a machine that loses power between `off` and `on` comes back
# with the repos disabled and the backup gone. The unit runs `on` before `off`
# for that reason as well as after, so an interrupted first boot heals itself
# on the next one rather than leaving a machine whose repos are quietly off.
#
# WHAT IT DOES NOT LEAK. The deployment the transaction stages does not inherit
# the disabled files: measured by rebooting into it, where the enabled set is
# alloy-local plus Fedora's four, as on any other machine. ostree's /etc merge
# reads the state /etc is left in, and `on` runs before the reboot.
#
# NOT A USER-FACING REPO POLICY. Which repos an installed Alloy leaves enabled
# is unchanged by this, deliberately: `alloy pkg` layers Fedora packages, and a
# machine that ships them disabled is a machine where that quietly finds
# nothing. The fence exists for one transaction on one boot.
#
# Deliberately dependency-free, and on the boot path in front of the only thing
# that gives the machine a console: sh, sed, cp, a glob. Same argument as
# alloy-layer-notice's.

set -eu

REPOS=/etc/yum.repos.d
SHIPPED=/usr/etc/yum.repos.d
CARRIED=alloy-local.repo

case "${1:-}" in
    off)
        [ -d "$REPOS" ] || exit 0
        for repo in "$REPOS"/*.repo; do
            [ -e "$repo" ] || continue
            [ "${repo##*/}" != "$CARRIED" ] || continue
            sed -i 's/^enabled[[:space:]]*=[[:space:]]*1$/enabled=0/' "$repo"
        done
        ;;
    on)
        # A missing /usr/etc means this is not an ostree deployment at all,
        # which is a dev box running the script by hand. Nothing to put back.
        [ -d "$SHIPPED" ] || exit 0
        for repo in "$SHIPPED"/*.repo; do
            [ -e "$repo" ] || continue
            cp -f "$repo" "$REPOS/${repo##*/}"
        done
        ;;
    *)
        echo "usage: ${0##*/} off|on" >&2
        exit 2
        ;;
esac
