Files
skeptical-updater/tests/unit/fakes/dnf/dnf
T
bryanpedini 71d7f87aa3 feat(info): show the install reason and drop the indentation
N? and `info PKG` now print three lines, none indented:

    PKG: <description>
    reason: explicitly installed | installed as a dependency | unknown | not installed
    required by: <installed dependents, comma separated> | nothing

The reason comes from a new <be>_reason backend function: apt-mark
showauto / showmanual (dpkg decides for a package in neither list), the
Install Reason of pacman -Qi, dnf repoquery --installed %{reason} (dnf4
and dnf5 words) and the Installed line of zypper info (rpm plus libzypp's
AutoInstalled when zypper is locked). A row whose old version is "-" is
not installed and the backend is not asked. The "(installed)" qualifier
moves to --help, README and DESIGN.

The rpm E2E fixture and e2e_reset now also mark su-dummy-a and su-dummy-c
as user-installed on dnf, which records plain rpm installs as "unknown",
so 1? and 2? show both reasons on all 12 distros. The verified commands
are recorded in discovery/{apt,pacman,rpm}.md.
2026-10-10 13:32:42 +02:00

158 lines
5.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2026 Bryan Joshua Pedini
# fake dnf (unit tests). FAKE_DNF_MAJOR=4|5 picks the output dialect; FAKE_DNF_CHECK_RC=0|1 simulates
# "no updates" / an error; FAKE_DNF_CHECK=obsoletes replays a check-update with only an
# "Obsoleting Packages" section; FAKE_DNF_REMOVE_REFUSE=1 makes `--assumeno remove` fail;
# removal tables: see the --assumeno remove branch. `repoquery --installed --qf %{reason}`: REASON of
# data/rpm/db.bash (dnf5's words with FAKE_DNF_MAJOR=5), FAKE_DNF_REASON="pkg=raw value" overrides
# it, FAKE_DNF_REPOQUERY_RC=N makes repoquery fail.
# shellcheck source=../fakelib.bash
. "${BASH_SOURCE[0]%/*}/../fakelib.bash"
# shellcheck source=../../data/rpm/db.bash
. "$FAKE_DATA/rpm/db.bash"
fake_log "$@"
D=$FAKE_DATA/dnf
major=${FAKE_DNF_MAJOR:-4}
pos=()
for a in "$@"; do case $a in -*) ;; *) pos+=("$a") ;; esac; done
installed() { [[ -n ${EVR[$1]:-} ]] && ! fake_purged "$1"; }
case " $* " in
*' --version '*) if ((major == 5)); then echo "dnf5 version 5.4.3.0"; else echo "4.14.0"; fi ;;
*' makecache '*)
rc=$(fake_rc FAKE_DNF_MAKECACHE_RC 0)
((rc == 0)) || echo "Error: Failed to download metadata for repo 'su-dummy': Cannot download repomd.xml" >&2
exit "$rc"
;;
*' check-update '*)
rc=$(fake_rc FAKE_DNF_CHECK_RC 100)
f=$D/check-update-dnf$major.txt
[[ ${FAKE_DNF_CHECK:-} != obsoletes ]] || f=$D/check-update-obsoletes.txt
case $rc in
100)
while IFS= read -r line; do
read -r na _ <<<"$line"
[[ -n $na ]] && fake_purged "${na%.*}" && continue
printf '%s\n' "$line"
done <"$f"
;;
1) echo "Error: Failed to download metadata for repo 'baseos'" >&2 ;;
esac
exit "$rc"
;;
*' repoquery '*)
p=${pos[-1]}
rc=$(fake_rc FAKE_DNF_REPOQUERY_RC 0)
if ((rc)); then
echo "Error: rpmdb open failed" >&2
exit "$rc"
fi
case " $* " in
*' --installed '*'%{reason}'*)
installed "$p" || exit 0
r=${REASON[$p]:-unknown}
if ((major == 5)); then
case $r in
user) r=User ;;
dependency) r=Dependency ;;
weak-dependency) r='Weak Dependency' ;;
group) r=Group ;;
unknown) r='External User' ;;
esac
fi
[[ ${FAKE_DNF_REASON:-} != "$p="* ]] || r=${FAKE_DNF_REASON#*=}
printf '%s\n' "$r"
((major == 5)) || echo
;;
*' --upgrades '*) case $p in su-dummy-[abc]) printf 'skeptical-updater dummy %s (v2.0)\n' "$p"; ((major == 5)) || echo ;; esac ;;
*) case $p in su-dummy-new) printf 'skeptical-updater dummy su-dummy-new (v1.0)\n' ;; esac ;;
esac
exit 0
;;
*' info '*)
p=${pos[-1]}
if [[ -f $D/info-$p.txt ]]; then cat "$D/info-$p.txt"; else
echo "Error: No matching Packages to list" >&2
exit 1
fi
;;
*' --assumeno '*remove*)
# the removal table: the target, its dependents (su-dummy-a for su-dummy-b; FAKE_DNF_DEPENDENT=
# "pkg:other"), its unused dependencies (FAKE_DNF_UNUSED="pkg:dep"); FAKE_DNF_WRAP wraps those rows
p=${pos[-1]}
if [[ -n ${FAKE_DNF_REMOVE_REFUSE:-} ]]; then
echo "Error: Problem: The operation would result in removing the following protected packages: $p"
exit 1
fi
if ! installed "$p"; then
echo "No match for argument: $p"
echo "No packages marked for removal."
echo "Dependencies resolved."
echo "Nothing to do."
echo "Complete!"
exit 0
fi
dependent=() unused=()
[[ $p != su-dummy-b ]] || ! installed su-dummy-a || dependent+=(su-dummy-a)
for r in ${FAKE_DNF_DEPENDENT:-}; do [[ ${r%%:*} == "$p" ]] && dependent+=("${r#*:}"); done
for r in ${FAKE_DNF_UNUSED:-}; do [[ ${r%%:*} == "$p" ]] && unused+=("${r#*:}"); done
row() { # row NAME
if ((major == 5)); then
if [[ -n ${FAKE_DNF_WRAP:-} && $1 != "$p" ]]; then
echo " $1"
echo " noarch 0:1.0-1 <unknown> 15.0 B"
else
echo " $1 noarch 0:1.0-1 <unknown> 15.0 B"
fi
elif [[ -n ${FAKE_DNF_WRAP:-} && $1 != "$p" ]]; then
printf ' %s\n' "$1"
printf ' noarch 1.0-1 @System 15\n'
else
printf ' %-20s noarch 1.0-1 @System 15\n' "$1"
fi
}
if ((major == 5)); then
echo "Package Arch Version Repository Size"
else
echo "Dependencies resolved."
echo "================================================================================"
echo " Package Architecture Version Repository Size"
echo "================================================================================"
fi
echo "Removing:"
row "$p"
if ((${#dependent[@]})); then
echo "Removing dependent packages:"
for r in "${dependent[@]}"; do row "$r"; done
fi
if ((${#unused[@]})); then
echo "Removing unused dependencies:"
for r in "${unused[@]}"; do row "$r"; done
fi
echo
n=$((1 + ${#dependent[@]} + ${#unused[@]}))
if ((major == 5)); then
echo "Transaction Summary:"
echo " Removing: $n packages"
echo "Operation aborted by the user."
else
echo "Transaction Summary"
echo "================================================================================"
echo "Remove $n Packages"
echo
echo "Operation aborted."
fi
exit 1
;;
*' upgrade '*) exit "$(fake_rc FAKE_DNF_UPGRADE_RC 0)" ;;
*' remove '*)
fake_mark_purged "${pos[@]:1}"
exit 0
;;
*)
echo "fake dnf: unhandled: $*" >&2
exit 99
;;
esac