Constrain Cirrus firmware in the package transaction so a stable channel refresh cannot remove the required aliases. Recover old firmware independently of completed migrations, and request reboot only after verifying a successful repair. Preserve package exclusions through native pacman handling while keeping interactive conflict recovery answerable. Co-Authored-By: GPT-6.1-Sol High <noreply@openai.com> Co-Authored-By: GPT-6.1-Sol XHigh <noreply@openai.com>
123 lines
4.3 KiB
Bash
Executable File
123 lines
4.3 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:summary=Run a pacman transaction for the Omarchy update flow, shielded from desktop session teardown.
|
|
# omarchy:args=<pacman-args>
|
|
# omarchy:hidden=true
|
|
# omarchy:requires-sudo=true
|
|
|
|
pacman_args=("$@")
|
|
query_args=()
|
|
declare -A firmware_targets needed_options
|
|
sync=0 upgrades=0 ask_bits=0 repair_reboot=0
|
|
noninteractive=0
|
|
operand="" option=""
|
|
end_options=0
|
|
separator_index=""
|
|
for index in "${!pacman_args[@]}"; do
|
|
arg=${pacman_args[index]}
|
|
if [[ -n $operand ]]; then
|
|
if [[ $operand == "query" ]]; then
|
|
query_args+=("$option" "$arg")
|
|
elif [[ $operand == "ask" ]]; then
|
|
[[ $arg =~ ^[0-9]{1,10}$ ]] || { echo "Invalid pacman question mask: $arg" >&2; exit 2; }
|
|
ask_bits=$((10#$arg))
|
|
noninteractive=1
|
|
fi
|
|
operand=""
|
|
continue
|
|
fi
|
|
if [[ $arg == "--" ]]; then
|
|
end_options=1
|
|
separator_index=$index
|
|
continue
|
|
fi
|
|
if (( end_options )); then
|
|
[[ $arg != "linux-firmware-cirrus" && $arg != */linux-firmware-cirrus ]] || firmware_targets[$index]=1
|
|
continue
|
|
fi
|
|
case "$arg" in
|
|
--sync) sync=1 ;;
|
|
--sysupgrade) ((upgrades += 1)) ;;
|
|
--noconfirm) noninteractive=1 ;;
|
|
--confirm) noninteractive=0 ;;
|
|
--ask) operand=ask ;;
|
|
--ask=*)
|
|
mask=${arg#*=}
|
|
[[ $mask =~ ^[0-9]{1,10}$ ]] || { echo "Invalid pacman question mask: $mask" >&2; exit 2; }
|
|
ask_bits=$((10#$mask))
|
|
noninteractive=1
|
|
;;
|
|
--config|--dbpath|--root|--sysroot|-b|-r) operand=query; option=$arg ;;
|
|
--config=*|--dbpath=*|--root=*|--sysroot=*) query_args+=("$arg") ;;
|
|
--ignore|--ignoregroup|--cachedir|--hookdir|--gpgdir|--logfile|--overwrite) operand=skip ;;
|
|
-b?*|-r?*) query_args+=("$arg") ;;
|
|
--needed) needed_options[$index]=1 ;;
|
|
--*) ;;
|
|
-*)
|
|
[[ $arg != *S* ]] || sync=1
|
|
upgrade_flags=${arg//[^u]/}
|
|
((upgrades += ${#upgrade_flags}))
|
|
;;
|
|
linux-firmware-cirrus|*/linux-firmware-cirrus) firmware_targets[$index]=1 ;;
|
|
esac
|
|
done
|
|
|
|
if (( sync && upgrades )) && omarchy-hw-dell-xps13-dx13260-ptl; then
|
|
cirrus_package=$(pacman "${query_args[@]}" -Q linux-firmware-cirrus 2>/dev/null || true)
|
|
old_firmware=0
|
|
if [[ -z $cirrus_package ]] || (( $(vercmp "${cirrus_package#* }" "20260810-3") < 0 )); then
|
|
old_firmware=1
|
|
fi
|
|
if (( upgrades > 1 || old_firmware || ${#firmware_targets[@]} )); then
|
|
pacman_args=()
|
|
original_args=("$@")
|
|
policy_inserted=0
|
|
for index in "${!original_args[@]}"; do
|
|
arg=${original_args[index]}
|
|
if (( noninteractive )) && [[ $index == "$separator_index" ]]; then
|
|
pacman_args+=(--ask "$((ask_bits | 1))")
|
|
policy_inserted=1
|
|
fi
|
|
[[ ! -v firmware_targets[$index] ]] || continue
|
|
# --needed skips an installed shim before -Suu selects the older core copy.
|
|
(( upgrades < 2 )) || [[ ! -v needed_options[$index] ]] || continue
|
|
pacman_args+=("$arg")
|
|
done
|
|
# Keep exclusions through pacman's own IgnorePkg/IgnoreGroup question handling.
|
|
if (( noninteractive && ! policy_inserted )); then
|
|
pacman_args+=(--ask "$((ask_bits | 1))")
|
|
fi
|
|
pacman_args+=('linux-firmware-cirrus>=20260810-3')
|
|
repair_reboot=$old_firmware
|
|
fi
|
|
fi
|
|
|
|
# Upgrading systemd runs its post_upgrade scriptlet mid-transaction, which
|
|
# reexecs both the system manager and every user manager. A pacman running
|
|
# inside a user-session scope can be SIGKILLed by that reexec, abandoning the
|
|
# transaction halfway. Registering the transaction as a PID 1 scope keeps it
|
|
# out of the user manager's cgroups entirely, and system scopes survive the
|
|
# system manager's own reexec.
|
|
scope=()
|
|
if [[ -d /run/systemd/system && ! -L /run/systemd/system ]]; then
|
|
scope=(systemd-run --scope --quiet --collect)
|
|
fi
|
|
|
|
# LC_ALL passes through so callers that parse pacman's stderr can pin the locale.
|
|
env_args=(OMARCHY_UPDATE_PACMAN=1)
|
|
if [[ -n ${LC_ALL:-} ]]; then
|
|
env_args+=(LC_ALL="$LC_ALL")
|
|
fi
|
|
|
|
if (( repair_reboot )); then
|
|
sudo env "${env_args[@]}" "${scope[@]}" pacman "${pacman_args[@]}" || exit $?
|
|
cirrus_package=$(pacman "${query_args[@]}" -Q linux-firmware-cirrus 2>/dev/null || true)
|
|
if [[ -n $cirrus_package ]] && (( $(vercmp "${cirrus_package#* }" "20260810-3") >= 0 )); then
|
|
omarchy-state set reboot-required
|
|
else
|
|
echo "Speaker firmware was not repaired; check the transaction's package exclusions." >&2
|
|
fi
|
|
else
|
|
exec sudo env "${env_args[@]}" "${scope[@]}" pacman "${pacman_args[@]}"
|
|
fi
|