#!/bin/bash
# Puts Flatpak into the runtime, with Flathub as a per-user remote. Run by the app under proot's
# fake root (pacman and pacman-key refuse any other uid), outside a session.
#
# The runtime's pacman database lists only the base image: the desktop and emulator packages were
# unpacked over it without registering. Asked for flatpak the usual way, pacman "reinstalls" about
# a hundred of those - Mesa among them, over the runtime's own Turnip build with its KGSL backend -
# and then runs every hook in the image, mkinitcpio included. So pacman only fetches and checks the
# few packages Flatpak needs on top of this image, verifying each against the Arch Linux ARM
# keyring, and they are unpacked here without hooks or scripts, like the desktop package itself.
#
#   droiddeck-flatpak-setup        install or repair; prints "== STEP ..." milestones
set -u
export LANG=C.UTF-8
step() { echo "== STEP $*"; }
fail() { echo "== FAIL $*"; exit 1; }

# Flatpak, the libraries it and appstream add to this image, and the D-Bus proxy flatpak run puts
# between an app and the session bus. bubblewrap is not among them: Android gives an app no user
# namespaces, and droiddeck-bwrap stands in for it (FLATPAK_BWRAP).
PACKAGES="flatpak ostree appstream libxmlb libmalcontent libfyaml accountsservice composefs xdg-dbus-proxy"
# Libraries Flatpak and the store's helper also need, which the Desktop package brings but a
# runtime without it may lack: each is fetched only when its file is not already there.
while read -r pkg probe; do
  [ -n "$pkg" ] || continue
  compgen -G "$probe" >/dev/null || PACKAGES="$PACKAGES $pkg"
done <<'NEEDS'
json-glib /usr/lib/libjson-glib-1.0.so.0
fuse3 /usr/lib/libfuse3.so.4
fuse-common /etc/fuse.conf
libsodium /usr/lib/libsodium.so.*
libstemmer /usr/lib/libstemmer.so.*
polkit /usr/lib/libpolkit-gobject-1.so.0
mpdecimal /usr/lib/libmpdec.so.*
python /usr/bin/python3
libgirepository /usr/lib/libgirepository-2.0.so.0
gobject-introspection-runtime /usr/lib/girepository-1.0/GObject-2.0.typelib
python-gobject /usr/lib/python3*/site-packages/gi/__init__.py
NEEDS
WORK=/var/cache/droiddeck-flatpak
CONF=$WORK/pacman.conf
mkdir -p "$WORK/pkg" "$WORK/db" || fail "cannot create $WORK"

# The image's pacman.conf names a download user this rootfs does not have (only root exists) and a
# sandbox proot cannot set up. Its one mirror is plain HTTP; these serve the same repos over TLS.
{ for m in https://ca.us.mirror.archlinuxarm.org https://fl.us.mirror.archlinuxarm.org \
           https://de3.mirror.archlinuxarm.org https://nl.mirror.archlinuxarm.org; do
    echo "Server = $m/\$arch/\$repo"; done
  grep '^Server' /etc/pacman.d/mirrorlist 2>/dev/null; } > "$WORK/mirrorlist"
sed -e 's/^DownloadUser/#DownloadUser/' \
    -e 's/^\[options\]/[options]\nDisableSandbox/' \
    -e "s#^Include *= */etc/pacman.d/mirrorlist#Include = $WORK/mirrorlist#" \
    /etc/pacman.conf > "$CONF" || fail "no /etc/pacman.conf"

if [ ! -f /etc/pacman.d/gnupg/pubring.gpg ] && [ ! -f /etc/pacman.d/gnupg/pubring.kbx ]; then
  step "Preparing the package keyring"
  pacman-key --init >/dev/null 2>&1 || fail "pacman-key --init failed"
  pacman-key --populate archlinuxarm >/dev/null 2>&1 || fail "pacman-key --populate failed"
fi

# A database of our own, so the image's stays exactly as it was built: -Sy on it would leave the
# rest of the image a partial upgrade behind the repos.
step "Reading the package lists"
pacman --config "$CONF" --dbpath "$WORK/db" --noconfirm -Sy >/dev/null 2>&1 \
  || pacman --config "$CONF" --dbpath "$WORK/db" --noconfirm -Sy 2>&1 | tail -3 \
  || fail "could not reach the Arch Linux ARM mirrors"
[ -f "$WORK/db/sync/extra.db" ] || fail "could not reach the Arch Linux ARM mirrors"

step "Downloading Flatpak"
# -w only downloads; pacman still checks each package's signature against the keyring. -dd: the
# dependencies are already in the image (and checked below by what the binaries actually link).
out=$(pacman --config "$CONF" --dbpath "$WORK/db" --cachedir "$WORK/pkg" --noconfirm -Sw -dd $PACKAGES 2>&1)
rc=$?
echo "$out" | grep -vE '^\s*$' | tail -4
[ $rc -eq 0 ] || fail "download failed"

step "Installing Flatpak"
for name in $PACKAGES; do
  ver=$(pacman --config "$CONF" --dbpath "$WORK/db" -Sp --print-format '%v' -dd "$name" 2>/dev/null | tail -1)
  file=$(ls "$WORK/pkg/$name-$ver-"*.pkg.tar.* 2>/dev/null | grep -v '\.sig$' | head -1)
  [ -n "$file" ] || fail "no package file for $name $ver"
  bsdtar -xpf "$file" -C / --exclude .PKGINFO --exclude .BUILDINFO --exclude .MTREE --exclude .INSTALL \
    || fail "could not unpack $name"
  echo "$name $ver" >> "$WORK/installed.new"
done
mv -f "$WORK/installed.new" "$WORK/installed"
# Only the newest file of each package is worth keeping for a repair.
find "$WORK/pkg" -type f -mtime +1 -delete 2>/dev/null

# What the binaries link is the real dependency list: anything this image lacks shows here.
missing=$(for f in /usr/bin/flatpak /usr/lib/libflatpak.so.0 /usr/lib/libostree-1.so.1 /usr/bin/xdg-dbus-proxy; do
  ldd "$f" 2>&1 | grep -E 'not found|version .* not found'
done | sort -u)
[ -z "$missing" ] || { echo "$missing"; fail "Flatpak is missing libraries"; }
flatpak --version >/dev/null 2>&1 || fail "flatpak does not start"
python3 -c 'import gi; gi.require_version("Flatpak", "1.0"); from gi.repository import Flatpak' 2>/dev/null \
  || fail "the store helper cannot load libflatpak from Python"

step "Adding Flathub"
export FLATPAK_BWRAP=/usr/local/bin/droiddeck-bwrap
# Flathub's descriptor - its URL and the key its commits are signed with - is carried here rather
# than fetched: adding the remote then needs no network, and a descriptor that did not arrive
# whole cannot be what failed. Flathub's own copy: https://dl.flathub.org/repo/flathub.flatpakrepo
cat > "$WORK/flathub.flatpakrepo" <<'REPO'
[Flatpak Repo]
Title=Flathub
Url=https://dl.flathub.org/repo/
Homepage=https://flathub.org/
Comment=Central repository of Flatpak applications
Description=Central repository of Flatpak applications
Icon=https://dl.flathub.org/repo/logo.svg
GPGKey=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
REPO
if ! flatpak remote-list --user --columns=name 2>/dev/null | grep -qx flathub; then
  out=$(flatpak remote-add --user --if-not-exists flathub "$WORK/flathub.flatpakrepo" 2>&1)
  rc=$?
  echo "$out"
  # What Flatpak said goes up with the failure, so the app can show it rather than a guess.
  [ $rc -eq 0 ] || fail "could not add the Flathub remote: $(echo "$out" | grep -v '^[[:space:]]*$' | tail -1)"
fi
echo "== DONE $(flatpak --version)"
