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.
158 lines
5.2 KiB
Bash
Executable File
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
|