first commit

This commit is contained in:
bryanpedini committed 2026-10-10 10:37:53 +02:00
commit 1354db6c39
90 files changed
+13123

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Bryan Joshua Pedini
# fake apt-cache (unit tests): show / rdepends / policy from data/apt/
# shellcheck source=../fakelib.bash
. "${BASH_SOURCE[0]%/*}/../fakelib.bash"
fake_log "$@"
pkgs=()
for a in "$@"; do case $a in -*) ;; *) pkgs+=("$a") ;; esac; done
verb=${pkgs[0]}
pkgs=("${pkgs[@]:1}")
case $verb in
show)
f=$FAKE_DATA/apt/show/${pkgs[0]}
if [[ ! -f $f ]] || fake_purged "${pkgs[0]}"; then
echo "E: No packages found" >&2
exit 100
fi
cat "$f"
;;
rdepends)
f=$FAKE_DATA/apt/rdepends/${pkgs[0]}
if [[ -f $f ]]; then cat "$f"; else printf '%s\nReverse Depends:\n' "${pkgs[0]}"; fi
;;
policy)
# print the stanzas of the requested packages
want=" ${pkgs[*]} "
show=0
while IFS= read -r line; do
if [[ $line =~ ^([^ ].*):$ ]]; then
if [[ $want == *" ${BASH_REMATCH[1]} "* ]]; then show=1; else show=0; fi
fi
((show)) && printf '%s\n' "$line"
done <"$FAKE_DATA/apt/policy.txt"
exit 0
;;
*)
echo "fake apt-cache: unhandled: $*" >&2
exit 99
;;
esac
+128
View File
@@ -0,0 +1,128 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Bryan Joshua Pedini
# fake apt-get (unit tests). Scenario: FAKE_APT_SIM=fixture|held|real|none|purge (data/apt/sim-*.txt).
# Purge simulation: installed = the "ii" rows of data/apt/dpkg-status.tsv; reverse dependencies from
# data/apt/purge-rdeps.txt; pre-existing orphans from data/apt/autoremovable.txt (added by
# --auto-remove, which is system-wide like the real one); FAKE_APT_AUTO_ORPHANS="pkg:dep ..." are
# the auto-installed dependencies a purge of pkg orphans; FAKE_APT_SIM_EXTRA="pkg:other ..." makes a
# simulated purge of pkg also remove other (a dependent apt-cache rdepends did not report).
# shellcheck source=../fakelib.bash
. "${BASH_SOURCE[0]%/*}/../fakelib.bash"
fake_log "$@"
args=" $* "
D=$FAKE_DATA/apt
installed() { grep -q "^.i *"$'\t'"$1"$'\t' "$D/dpkg-status.tsv" && ! fake_purged "$1"; }
orphans() { while IFS= read -r o; do installed "$o" && printf '%s\n' "$o"; done <"$D/autoremovable.txt"; }
# purge_set [--auto-remove] NAME...: the packages a purge removes, sorted
purge_set() {
local auto=0 n r line
if [[ $1 == --auto-remove ]]; then
auto=1
shift
fi
{
for n in "$@"; do
installed "$n" || continue
echo "$n"
while IFS= read -r line; do
[[ $line == "$n: "* ]] || continue
for r in ${line#*: }; do installed "$r" && echo "$r"; done
done <"$D/purge-rdeps.txt"
if ((auto)); then
for r in ${FAKE_APT_AUTO_ORPHANS:-}; do [[ ${r%%:*} == "$n" ]] && installed "${r#*:}" && echo "${r#*:}"; done
fi
for r in ${FAKE_APT_SIM_EXTRA:-}; do [[ ${r%%:*} == "$n" ]] && installed "${r#*:}" && echo "${r#*:}"; done
done
if ((auto)); then orphans; fi
} | sort -u
}
case $args in
*' update '*)
rc=$(fake_rc FAKE_APT_UPDATE_RC 0)
if ((rc)); then
echo "E: Failed to fetch http://deb.debian.org/debian/dists/bookworm/InRelease Temporary failure resolving 'deb.debian.org'" >&2
echo "E: Some index files failed to download. They have been ignored, or old ones used instead." >&2
fi
exit "$rc"
;;
*' -s '*autoremove*)
while IFS= read -r o; do [[ -n $o ]] && echo "Remv $o [1.0]"; done < <(orphans)
exit 0
;;
*' -s '*purge*)
names=()
auto=()
for a in "$@"; do
case $a in --auto-remove) auto=(--auto-remove) ;; -* | purge) ;; *) names+=("$a") ;; esac
done
rc=$(fake_rc FAKE_APT_SIM_PURGE_RC 0)
if ((rc)); then
echo "E: Unable to correct problems, you have held broken packages." >&2
exit "$rc"
fi
for n in "${names[@]}"; do
if ! grep -q $'\t'"$n"$'\t' "$D/dpkg-status.tsv" && [[ $n != su-dummy-newdep ]]; then
echo "E: Unable to locate package $n" >&2
exit 100
fi
done
while IFS= read -r p; do [[ -n $p ]] && echo "Purg $p [1.0]"; done < <(purge_set "${auto[@]}" "${names[@]}")
exit 0
;;
*' -s '*' upgrade '*)
f=$D/sim-${FAKE_APT_SIM:-fixture}.txt
while IFS= read -r line; do
name=
case $line in Inst\ * | Conf\ *) name=${line#* }; name=${name%% *} ;; esac
if [[ -n $name ]] && fake_purged "$name"; then continue; fi
if [[ $line == ' '* && -f $FAKE_DIR/purged ]]; then
while IFS= read -r p; do line=${line//$p/}; done <"$FAKE_DIR/purged"
fi
printf '%s\n' "$line"
done <"$f"
exit 0
;;
*' upgrade '*)
echo "holds during upgrade: $(sort "$FAKE_DIR/holds" 2>/dev/null | tr '\n' ' ')" >>"$FAKE_LOG"
# which of our lock files does the package manager have open (it must have none)?
if [[ -d /proc/$$/fd ]]; then
n=0
for fd in "/proc/$$/fd"/*; do
[[ $(readlink "$fd" 2>/dev/null) == *.lock ]] && n=$((n + 1))
done
echo "lock fds in the upgrade: $n" >>"$FAKE_LOG"
fi
if [[ -n ${FAKE_APT_UPGRADE_KILL:-} ]]; then
kill -s "$FAKE_APT_UPGRADE_KILL" "$PPID"
sleep 0.2
fi
if [[ -n ${FAKE_KILL_READER:-} ]]; then
# close the applet's stdout: kill the process reading it, then keep writing
pid=$(cat "$FAKE_DIR/reader.pid")
kill -9 "$pid"
while kill -0 "$pid" 2>/dev/null; do sleep 0.05; done
fi
echo "Reading package lists..." 2>/dev/null
echo "0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." 2>/dev/null
exit "$(fake_rc FAKE_APT_UPGRADE_RC 0)"
;;
*' purge '*)
rc=$(fake_rc FAKE_APT_PURGE_RC 0)
if ((rc == 0)); then
for a in "$@"; do case $a in -* | purge) ;; *) fake_mark_purged "$a" ;; esac; done
# FAKE_APT_PURGE_ALSO: packages that disappear although the plan did not name them
read -r -a also <<<"${FAKE_APT_PURGE_ALSO:-}"
((${#also[@]} == 0)) || fake_mark_purged "${also[@]}"
else
echo "E: Held packages were changed and -y was used without --allow-change-held-packages." >&2
fi
exit "$rc"
;;
esac
echo "fake apt-get: unhandled: $*" >&2
exit 99
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Bryan Joshua Pedini
# fake apt-mark (unit tests): hold state in $FAKE_DIR/holds (one name per line).
# FAKE_APT_MARK_LOCKED=N: the first N hold/unhold calls fail like dpkg's busy frontend lock.
# FAKE_APT_MARK_UNHOLD_SIGNAL=SIG: send SIG to the applet before an unhold (a second Ctrl-C).
# FAKE_APT_MARK_UNHOLD_RC=N: unhold fails (nothing released). FAKE_APT_MARK_FAIL_MSG: the message a
# failing hold prints. Every unhold logs whether $STATE_DIR/holds.lock is held by someone.
# shellcheck source=../fakelib.bash
. "${BASH_SOURCE[0]%/*}/../fakelib.bash"
fake_log "$@"
h=$FAKE_DIR/holds
touch "$h"
verb=$1
shift
case $verb in hold | unhold)
if [[ -n ${FAKE_APT_MARK_LOCKED:-} ]]; then
n=$(cat "$FAKE_DIR/locked-calls" 2>/dev/null || echo 0)
if ((n < FAKE_APT_MARK_LOCKED)); then
echo $((n + 1)) >"$FAKE_DIR/locked-calls"
echo "${FAKE_APT_MARK_LOCK_MSG:-dpkg: error: dpkg frontend lock was locked by another process with pid 4242}"
echo "E: Sub-process dpkg --set-selections returned an error code (2)"
echo "E: Executing dpkg failed. Are you root?"
exit 100
fi
fi
;;
esac
case $verb in
showhold) sort "$h" ;;
hold)
for p in "$@"; do
if grep -qxF -- "$p" "$h"; then echo "$p was already set on hold."; else
echo "$p" >>"$h"
echo "$p set on hold."
fi
done
[[ -z ${FAKE_APT_MARK_FAIL_MSG:-} ]] || echo "$FAKE_APT_MARK_FAIL_MSG" >&2
exit "$(fake_rc FAKE_APT_MARK_HOLD_RC 0)"
;;
unhold)
if [[ -n ${SKEPTICAL_UPDATER_STATE_DIR:-} && -e $SKEPTICAL_UPDATER_STATE_DIR/holds.lock ]] && command -v flock >/dev/null; then
if flock -n "$SKEPTICAL_UPDATER_STATE_DIR/holds.lock" true; then l=free; else l=held; fi
echo "holds.lock during unhold: $l" >>"$FAKE_LOG"
fi
if [[ -n ${FAKE_APT_MARK_UNHOLD_RC:-} ]]; then
echo "E: Unable to correct problems" >&2
exit "$FAKE_APT_MARK_UNHOLD_RC"
fi
if [[ -n ${FAKE_APT_MARK_UNHOLD_SIGNAL:-} ]]; then
kill -s "$FAKE_APT_MARK_UNHOLD_SIGNAL" "$(cat "$FAKE_DIR/applet.pid" 2>/dev/null || echo "$PPID")" 2>/dev/null
sleep 0.2
fi
for p in "$@"; do
if grep -qxF -- "$p" "$h"; then
grep -vxF -- "$p" "$h" >"$h.new" || true
mv "$h.new" "$h"
echo "Canceled hold on $p."
else echo "$p was already not on hold."; fi
done
;;
*)
echo "fake apt-mark: unhandled: $verb $*" >&2
exit 99
;;
esac
+19
View File
@@ -0,0 +1,19 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Bryan Joshua Pedini
# fake dpkg-query (unit tests): the dpkg database dump used for dependency closures
# shellcheck source=../fakelib.bash
. "${BASH_SOURCE[0]%/*}/../fakelib.bash"
fake_log "$@"
# FAKE_STATE_APPEND / FAKE_STATE_SED: simulate another process writing the statefile meanwhile
st=${SKEPTICAL_UPDATER_STATE_DIR:-}/trusted.tsv
if [[ -n ${FAKE_STATE_APPEND:-} ]]; then printf '%s\n' "$FAKE_STATE_APPEND" >>"$st"; fi
if [[ -n ${FAKE_STATE_SED:-} ]]; then sed -i "$FAKE_STATE_SED" "$st"; fi
case " $* " in
*' -W '*) cat "$FAKE_DATA/apt/dpkg-status.tsv" ;;
*)
echo "fake dpkg-query: unhandled: $*" >&2
exit 99
;;
esac