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.
113 lines
3.9 KiB
Bash
Executable File
113 lines
3.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
# Copyright (C) 2026 Bryan Joshua Pedini
|
|
|
|
# fake zypper (unit tests). FAKE_ZYPPER_LU=fixture|real|none picks the list-updates XML,
|
|
# FAKE_ZYPPER_DUP=fixture|empty|removes the `dist-upgrade --dry-run` plan (data/zypper/dup-*.xml).
|
|
# addlock writes real zypp lock entries into the locksfile.path of $ZYPP_CONF (default
|
|
# /etc/zypp/locks is never touched: the fake refuses); update/dist-upgrade log that file.
|
|
# info replays data/zypper/info-NAME.txt (exit 104 without one); FAKE_ZYPPER_INFO_RC=7 makes it fail
|
|
# like a zypp lock held by another process.
|
|
# shellcheck source=../fakelib.bash
|
|
. "${BASH_SOURCE[0]%/*}/../fakelib.bash"
|
|
fake_log "${ZYPP_CONF:+ZYPP_CONF=$ZYPP_CONF }$*"
|
|
D=$FAKE_DATA/zypper
|
|
|
|
locksfile() {
|
|
local f=${ZYPP_CONF:-} line l=
|
|
[[ -n $f && -r $f ]] || return 1
|
|
while IFS= read -r line; do
|
|
[[ $line =~ ^[[:space:]]*locksfile\.path[[:space:]]*=[[:space:]]*(.*)$ ]] && l=${BASH_REMATCH[1]}
|
|
done <"$f"
|
|
[[ -n $l ]] || return 1
|
|
printf '%s' "$l"
|
|
}
|
|
|
|
pos=()
|
|
for a in "$@"; do case $a in -*) ;; *) pos+=("$a") ;; esac; done
|
|
verb=${pos[0]:-}
|
|
args=("${pos[@]:1}")
|
|
xml_remove() { # the install-summary of `remove --dry-run` for the given names
|
|
local n
|
|
printf "<?xml version='1.0'?>\n<stream>\n<install-summary download-size=\"0\" space-usage-diff=\"-30\" packages-to-change=\"%s\">\n<to-remove>\n" "$#"
|
|
for n in "$@"; do printf '<solvable type="package" name="%s" edition="1.0-1" arch="noarch" repository="@System" summary="dummy %s"><description>d</description></solvable>\n' "$n" "$n"; done
|
|
printf '</to-remove>\n</install-summary>\n</stream>\n'
|
|
}
|
|
dry=0
|
|
case " $* " in *' --dry-run '*) dry=1 ;; esac
|
|
|
|
case $verb in
|
|
refresh)
|
|
rc=$(fake_rc FAKE_ZYPPER_REFRESH_RC 0)
|
|
((rc == 0)) || echo "Could not refresh the repositories because of errors." >&2
|
|
exit "$rc"
|
|
;;
|
|
list-updates) cat "$D/lu-${FAKE_ZYPPER_LU:-fixture}.xml" ;;
|
|
info)
|
|
p=${args[-1]}
|
|
if [[ -n ${FAKE_ZYPPER_INFO_RC:-} ]]; then
|
|
echo "System management is locked by the application with pid 4242 (zypper)."
|
|
echo "Close this application before trying again."
|
|
exit "$FAKE_ZYPPER_INFO_RC"
|
|
fi
|
|
if [[ -f $D/info-$p.txt ]]; then cat "$D/info-$p.txt"; else
|
|
echo "package '$p' not found."
|
|
exit 104
|
|
fi
|
|
;;
|
|
addlock)
|
|
l=$(locksfile) || {
|
|
echo "fake zypper: addlock without a private ZYPP_CONF/locksfile.path" >&2
|
|
exit 98
|
|
}
|
|
for p in "${args[@]}"; do printf '\ntype: package\nmatch_type: glob\ncase_sensitive: on\nsolvable_name: %s\n\n' "$p" >>"$l"; done
|
|
;;
|
|
dist-upgrade | dup | update)
|
|
if ((dry)); then
|
|
cat "$D/dup-${FAKE_ZYPPER_DUP:-fixture}.xml"
|
|
exit 0
|
|
fi
|
|
if l=$(locksfile); then { echo "--- locks seen by $verb:"; cat "$l"; echo "--- end"; } >>"$FAKE_LOG"; fi
|
|
if [[ -n ${ZYPP_CONF:-} && -n ${SKEPTICAL_UPDATER_STATE_DIR:-} && -e $SKEPTICAL_UPDATER_STATE_DIR/zypper.lock ]]; then
|
|
if flock -n "$SKEPTICAL_UPDATER_STATE_DIR/zypper.lock" true; then l=free; else l=held; fi
|
|
echo "zypper.lock during $verb: $l" >>"$FAKE_LOG"
|
|
fi
|
|
if [[ -n ${FAKE_ZYPPER_UPGRADE_KILL:-} ]]; then
|
|
kill -s "$FAKE_ZYPPER_UPGRADE_KILL" "$PPID"
|
|
sleep 0.2
|
|
fi
|
|
exit "$(fake_rc FAKE_ZYPPER_UPGRADE_RC 0)"
|
|
;;
|
|
remove)
|
|
if ((dry)); then
|
|
set -- "${args[@]}"
|
|
# FAKE_ZYPPER_CLEAN="pkg:dep" (unneeded dependency) / FAKE_ZYPPER_EXTRA="pkg:other" join the plan
|
|
more=()
|
|
for r in ${FAKE_ZYPPER_CLEAN:-} ${FAKE_ZYPPER_EXTRA:-}; do [[ ${r%%:*} == "${1:-}" ]] && more+=("${r#*:}"); done
|
|
case ${1:-} in
|
|
su-dummy-b) xml_remove su-dummy-a su-dummy-b "${more[@]}" ;;
|
|
su-dummy-*) xml_remove "$1" "${more[@]}" ;;
|
|
*)
|
|
echo "'$1' not found in package names. Trying capabilities."
|
|
echo "No provider of '$1' found."
|
|
exit 104
|
|
;;
|
|
esac
|
|
exit 0
|
|
fi
|
|
for p in "${args[@]}"; do
|
|
case $p in su-dummy-*) ;; *)
|
|
echo "'$p' not found in package names. Trying capabilities."
|
|
echo "No provider of '$p' found."
|
|
exit 104
|
|
;;
|
|
esac
|
|
done
|
|
fake_mark_purged "${args[@]}"
|
|
;;
|
|
*)
|
|
echo "fake zypper: unhandled: $*" >&2
|
|
exit 99
|
|
;;
|
|
esac
|