testsAndMisc/linux_configuration/periodic_background/digital_wellbeing/pacman/makepkg_wrapper.sh
Krzysztof kuhy Rudnicki 4f2b0ccdf7 Dissolve linux_configuration/scripts/ and single_use/
Two levels of pure taxonomy carrying no information, and a 2-directory
cap leaves no room for them. Categories now sit directly under
linux_configuration/: features, fixes, utils, misc, fresh-install,
installers, diagnostics, gaming, boot_recovery, periodic_background, lib,
meta, tests. A script's own lib/ and tests/ are exempt from the cap, so
those stay put.

Depth violations 248 -> 139; roughly 40 of the remainder are inside
digital_wellbeing and hosts, deferred until the guard-lib repoint.

The moves are the easy half. What breaks is every path that counted
levels, and three classes of it had to be found by resolving paths rather
than reading diffs:

  - 52 relative `source` lines for lib/common.sh and lib/android.sh. The
    correct prefix differs per file: 40 were ../../ and 12 were ../../../,
    so a blanket replace would have fixed one set and broken the other.
  - REPO_ROOT in 7 fixes/lib/tests harnesses and setup_syncyomi_guard.sh,
    each walking up four levels from a directory now two levels shallower.
    This caused a real regression -- the fixes suite went red with
    "log_warn: command not found" -- caught by running it and comparing
    against the pre-move baseline worktree.
  - conftest.py's sys.path entries, which took the pytest gate down with
    14 collection errors, and the `# shellcheck source=` directives, which
    took shellcheck down with SC1091.

16 symlinks in $HOME broke, including the entire i3blocks bar. All
repointed, and cpu_monitor/memory/disk/time/volume were run to confirm
they emit real output rather than merely resolving.

Verified: 1798 tests pass at 100% coverage, 8 of 9 lib/tests suites pass
(the ninth needs the coverage jail, identically at baseline), pre-commit
is clean, and the two untracked secret configs are still ignored after
their gitignore paths changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJrqKERAo5QUeEHWS5Asgp
2026-08-23 18:53:30 +02:00

70 lines
3.0 KiB
Bash
Executable File

#!/bin/bash
# makepkg_wrapper.sh — thin wrapper around /usr/bin/makepkg.
#
# WHY THIS EXISTS
# ---------------
# Vendored makepkg (shipped by the `pacman` package) has its own DB-lock wait in
# run_pacman(): `while [[ -f $lockfile ]]; do ... done`. It checks ONLY whether
# /var/lib/pacman/db.lck exists — never whether a live pacman actually owns it —
# and the outer loop has no timeout. So an ORPHANED lock (left by a pacman that
# was killed mid-transaction) makes `makepkg -i` hang forever, printing
# "Pacman is currently in use, please wait..." every ~30s.
#
# makepkg blocks in that loop BEFORE it ever invokes pacman, so the system's
# pacman_wrapper (which clears stale locks correctly) never gets a turn. This
# wrapper closes the gap: for install-bound invocations it clears an *orphaned*
# lock up front, then execs the real makepkg. A legitimate lock (held by a live
# pacman) is left untouched so makepkg waits as designed.
#
# makepkg is vendored and overwritten on `pacman-git` upgrades, so it must not be
# edited directly — wrapping it (mirroring the pacman_wrapper pattern) is the
# upgrade-safe fix.
set -euo pipefail
# Real makepkg, preserved by install_makepkg_wrapper.sh. Overridable via env so
# the shell test harness can point it at a stub (mirrors $PACMAN_LOCK_FILE);
# unset in production, so the default holds.
MAKEPKG_BIN="${MAKEPKG_BIN:-/usr/bin/makepkg.orig}"
# Source shared stale-lock helpers (co-located next to this wrapper). Fail SAFE:
# if the lib is missing/unreadable, do NOT break makepkg — exec the real binary
# and skip the pre-flight. A broken helper must never take down all builds.
_LIB_DIR="$(dirname "$(readlink -f "$0")")"
if [[ -r "$_LIB_DIR/pacman_lock_lib.sh" ]]; then
# shellcheck source=pacman_lock_lib.sh
source "$_LIB_DIR/pacman_lock_lib.sh"
else
exec "$MAKEPKG_BIN" "$@"
fi
# Does this invocation ask makepkg to install (-i / --install)? Only install
# invocations reach makepkg's pacman lock-wait, so only then do we pre-clear.
# Handles bundled short flags (-i, -si, -sif, -if, ...). Stops at `--`.
invocation_installs() {
local arg
for arg in "$@"; do
[[ $arg == "--" ]] && return 1
[[ $arg == "--install" ]] && return 0
# Single-dash short-flag cluster containing 'i' (makepkg's -i = install).
[[ $arg == -[!-]* && $arg == *i* ]] && return 0
done
return 1
}
# Bypass fast-path: inside a fakeroot build sandbox (makepkg re-execs itself for
# the package() stage — FAKEROOTKEY is set), or for any invocation that won't
# install (won't hit the lock-wait). Mirrors the pacman_wrapper FAKEROOTKEY
# guard. Exec real makepkg unchanged.
if [[ -n ${FAKEROOTKEY:-} ]] || ! invocation_installs "$@"; then
exec "$MAKEPKG_BIN" "$@"
fi
# Best-effort pre-flight clear. `check_and_handle_db_lock` removes the lock only
# when no live pacman owns it; if a real pacman holds it, it returns non-zero and
# we deliberately DO NOT abort — makepkg's own wait will (correctly) wait it out.
# Hence `|| true`: a live-holder verdict is not a makepkg failure here.
check_and_handle_db_lock "$@" || true
exec "$MAKEPKG_BIN" "$@"