feat(show): merge the installed record with the upstream candidate
N?? and `show PKG` now print the installed record in the package
manager's own key/value layout, after one line explaining the format:
# lines starting with > come from the upstream candidate: a differing
value, or a field the installed record lacks
After each field whose candidate value differs comes the candidate's
line prefixed with "> "; fields only the candidate has are appended the
same way; installed-only fields stay; identical fields print once.
Multi-line values (pacman Optional Deps, dnf Description, RFC-822
continuation lines) are compared as blocks and a differing candidate
block gets "> " on every line. A package that is not installed shows the
candidate alone ("# not installed: this is the upstream candidate").
Merged where the backend gives comparable records for both sides:
- pacman: -Qi vs -Si REPO/PKG, REPO = the first repository -Sl lists
- apt: dpkg-query -s (Status, Conffiles, the long description; richer
than apt-cache show PKG=<installed>, which gives the archive record
when that version is still listed) vs apt-cache show --no-all-versions;
Description-xx pairs with Description and a one-line candidate
Description equal to the installed first line counts as identical
(the archives ship the long text in Translation files)
- dnf: info --installed vs info --upgrades (--available lists other
architectures first and nothing for an up-to-date package); not
installed: --available; dnf5's differently padded keys are re-padded
zypper keeps `zypper info --requires`: rpm -qi and zypper info share
almost no keys and zypper cannot print the installed record itself.
No candidate, or not exactly one record per side, keeps the old output.
Formats verified in containers and recorded in discovery/*.md. Unit
tests replay recorded pacman, apt, dnf4 and dnf5 records; the E2E suite
checks 2?? on su-dummy-b on all 12 distros.
This commit is contained in:
1 parent
296c77e319
commit
875c8294bf
30 files changed
+857
-45
No files matched your search
@@ -56,10 +56,33 @@ zypper_verb() { case $(. /etc/os-release && printf '%s' "$ID") in opensuse-tumbl
|
||||
assert_line 'Quit: nothing was upgraded.'
|
||||
}
|
||||
|
||||
@test "N?? prints the native full info" {
|
||||
run skeptical-updater --no-refresh <<<$'1??\nq'
|
||||
@test "N?? shows the installed record merged with the upstream candidate (zypper: zypper info)" {
|
||||
run skeptical-updater --no-refresh <<<$'2??\nq'
|
||||
assert_success
|
||||
assert_line --regexp '^(Package: su-dummy-a|Name +: su-dummy-a)$'
|
||||
if [[ $BE == zypper ]]; then # no comparable records: the plain zypper info --requires
|
||||
assert_line 'Information for package su-dummy-b:'
|
||||
refute_line --partial '# lines starting with >'
|
||||
return 0
|
||||
fi
|
||||
assert_line '# lines starting with > come from the upstream candidate: a differing value, or a field the installed record lacks'
|
||||
case $BE in
|
||||
apt)
|
||||
assert_line 'Package: su-dummy-b'
|
||||
assert_line 'Status: install ok installed'
|
||||
assert_output --partial "$(printf '%s\n' 'Version: 1.0' '> Version: 2.0')"
|
||||
assert_line --regexp '^> Filename: .*su-dummy-b_2\.0_all\.deb$'
|
||||
;;
|
||||
pacman)
|
||||
assert_output --partial "$(printf '%s\n' 'Version : 1.0-1' '> Version : 2.0-1')"
|
||||
assert_line 'Install Reason : Installed as a dependency for another package'
|
||||
assert_line '> Repository : su-dummy'
|
||||
;;
|
||||
dnf)
|
||||
assert_output --partial "$(printf '%s\n' 'Version : 1.0' '> Version : 2.0')"
|
||||
assert_output --partial "$(printf '%s\n' 'Repository : @System' '> Repository : su-dummy')"
|
||||
;;
|
||||
esac
|
||||
[[ $(grep -c '^> ' <<<"$output") -ge 2 ]]
|
||||
}
|
||||
|
||||
@test "N+ writes the user row and the dep row; list hides both and counts them" {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
Package: perl-base
|
||||
Source: perl
|
||||
Version: 5.36.0-7+deb12u4
|
||||
Installed-Size: 7643
|
||||
Maintainer: Niko Tyni <ntyni@debian.org>
|
||||
Architecture: amd64
|
||||
Replaces: libfile-path-perl (<< 2.18), libfile-temp-perl (<< 0.2311), libio-socket-ip-perl (<< 0.41), libscalar-list-utils-perl (<< 1:1.62), libsocket-perl (<< 2.033), libxsloader-perl (<< 0.31), perl (<< 5.10.1-12), perl-modules (<< 5.20.1-3)
|
||||
Provides: libfile-path-perl (= 2.18), libfile-temp-perl (= 0.2311), libio-socket-ip-perl (= 0.41), libscalar-list-utils-perl (= 1:1.62), libsocket-perl (= 2.033), libxsloader-perl (= 0.31), perlapi-5.36.0
|
||||
Suggests: perl, sensible-utils
|
||||
Conflicts: defoma (<< 0.11.12), doc-base (<< 0.10.3), mono-gac (<< 2.10.8.1-3), safe-rm (<< 0.8), update-inetd (<< 4.41)
|
||||
Breaks: amanda-common (<< 1:3.3.9-2), backuppc (<< 4.4.0-7~), bucardo (<< 5.5.0-1.1), debconf (<< 1.5.61), dh-haskell (<< 0.3), duck (<< 0.14.1), intltool (<< 0.51.0-4), kio-perldoc (<< 20.04.1-1), latexml (<< 0.8.4-2), libdevel-mat-dumper-perl (<< 0.42-3), libencode-arabic-perl (<< 14.2-2), libexception-class-perl (<< 1.42), libfile-path-perl (<< 2.18), libfile-spec-perl (<< 3.8400), libfile-temp-perl (<< 0.2311), libio-socket-ip-perl (<< 0.41), libmp3-tag-perl (<< 1.13-1.2), libsbuild-perl (<< 0.67.0-1), libscalar-list-utils-perl (<< 1:1.62), libsocket-perl (<< 2.033), libxsloader-perl (<< 0.31), mailagent (<< 1:3.1-81-2), perl (<< 5.36.0~), perl-modules (<< 5.36.0~), pod2pdf (<< 0.42-5.1), slic3r (<< 1.2.9+dfsg-6.1), slic3r-prusa (<< 1.37.0+dfsg-1.1), texinfo (<< 6.1.0.dfsg.1-8)
|
||||
Description: minimal Perl system
|
||||
Description-md5: 6f98ca50727514fe6b19872d5ede03ec
|
||||
Homepage: http://dev.perl.org/perl5/
|
||||
Essential: yes
|
||||
Pre-Depends: libc6 (>= 2.35), libcrypt1 (>= 1:4.1.0), dpkg (>= 1.17.17)
|
||||
Section: perl
|
||||
Priority: required
|
||||
Filename: pool/updates/main/p/perl/perl-base_5.36.0-7+deb12u4_amd64.deb
|
||||
Size: 1609596
|
||||
SHA256: d7d1943aec9597629bf73075efcc5ef6dc9bda96d78e80d843156ecd448478b8
|
||||
@@ -0,0 +1,21 @@
|
||||
Package: zsh
|
||||
Source: zsh (5.9-4)
|
||||
Version: 5.9-4+b15
|
||||
Installed-Size: 2461
|
||||
Maintainer: Debian Zsh Maintainers <pkg-zsh-devel@lists.alioth.debian.org>
|
||||
Architecture: amd64
|
||||
Depends: zsh-common (= 5.9-4), libc6 (>= 2.34), libcap2 (>= 1:2.10), libtinfo6 (>= 6), debianutils (>= 5.3-1~)
|
||||
Recommends: libc6 (>= 2.35), libgdbm6 (>= 1.16), libncursesw6 (>= 6), libpcre3
|
||||
Suggests: zsh-doc
|
||||
Description: shell with lots of features
|
||||
Description-md5: a129d6b2d23d2d5d3a6b822d3f8f856d
|
||||
Homepage: https://www.zsh.org/
|
||||
Tag: devel::interpreter, implemented-in::c, interface::shell,
|
||||
network::client, protocol::ftp, role::program, scope::utility
|
||||
Section: shells
|
||||
Priority: optional
|
||||
Filename: pool/main/z/zsh/zsh_5.9-4+b15_amd64.deb
|
||||
Size: 907512
|
||||
MD5sum: 831903f59bf1ed613a5beeef9fc787ad
|
||||
SHA256: 8362cc8bbb530d393950522dc8a9df5a860a61227d62ff669a7524056e6289a8
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
Package: perl-base
|
||||
Essential: yes
|
||||
Status: install ok installed
|
||||
Priority: required
|
||||
Section: perl
|
||||
Installed-Size: 7639
|
||||
Maintainer: Niko Tyni <ntyni@debian.org>
|
||||
Architecture: amd64
|
||||
Source: perl
|
||||
Version: 5.36.0-7+deb12u3
|
||||
Replaces: libfile-path-perl (<< 2.18), libfile-temp-perl (<< 0.2311), libio-socket-ip-perl (<< 0.41), libscalar-list-utils-perl (<< 1:1.62), libsocket-perl (<< 2.033), libxsloader-perl (<< 0.31), perl (<< 5.10.1-12), perl-modules (<< 5.20.1-3)
|
||||
Provides: libfile-path-perl (= 2.18), libfile-temp-perl (= 0.2311), libio-socket-ip-perl (= 0.41), libscalar-list-utils-perl (= 1:1.62), libsocket-perl (= 2.033), libxsloader-perl (= 0.31), perlapi-5.36.0
|
||||
Pre-Depends: libc6 (>= 2.35), libcrypt1 (>= 1:4.1.0), dpkg (>= 1.17.17)
|
||||
Suggests: perl, sensible-utils
|
||||
Breaks: amanda-common (<< 1:3.3.9-2), backuppc (<< 4.4.0-7~), bucardo (<< 5.5.0-1.1), debconf (<< 1.5.61), dh-haskell (<< 0.3), duck (<< 0.14.1), intltool (<< 0.51.0-4), kio-perldoc (<< 20.04.1-1), latexml (<< 0.8.4-2), libdevel-mat-dumper-perl (<< 0.42-3), libencode-arabic-perl (<< 14.2-2), libexception-class-perl (<< 1.42), libfile-path-perl (<< 2.18), libfile-spec-perl (<< 3.8400), libfile-temp-perl (<< 0.2311), libio-socket-ip-perl (<< 0.41), libmp3-tag-perl (<< 1.13-1.2), libsbuild-perl (<< 0.67.0-1), libscalar-list-utils-perl (<< 1:1.62), libsocket-perl (<< 2.033), libxsloader-perl (<< 0.31), mailagent (<< 1:3.1-81-2), perl (<< 5.36.0~), perl-modules (<< 5.36.0~), pod2pdf (<< 0.42-5.1), slic3r (<< 1.2.9+dfsg-6.1), slic3r-prusa (<< 1.37.0+dfsg-1.1), texinfo (<< 6.1.0.dfsg.1-8)
|
||||
Conflicts: defoma (<< 0.11.12), doc-base (<< 0.10.3), mono-gac (<< 2.10.8.1-3), safe-rm (<< 0.8), update-inetd (<< 4.41)
|
||||
Description: minimal Perl system
|
||||
Perl is a scripting language used in many system scripts and utilities.
|
||||
.
|
||||
This package provides a Perl interpreter and the small subset of the
|
||||
standard run-time library required to perform basic tasks. For a full
|
||||
Perl installation, install "perl" (and its dependencies, "perl-modules-5.36"
|
||||
and "perl-doc").
|
||||
Homepage: http://dev.perl.org/perl5/
|
||||
@@ -0,0 +1,14 @@
|
||||
Package: su-dummy-a
|
||||
Status: install ok installed
|
||||
Priority: optional
|
||||
Section: misc
|
||||
Maintainer: Skeptical Updater Fixture <su-fixture@example.invalid>
|
||||
Architecture: all
|
||||
Version: 1.0
|
||||
Depends: su-dummy-b
|
||||
Conffiles:
|
||||
/etc/su-dummy/su-dummy-a.conf 607e2d3a119dfe832d937ce579ef1079
|
||||
Description: dummy package su-dummy-a for skeptical-updater tests
|
||||
This package only exists to exercise the package manager.
|
||||
.
|
||||
It ships one data file and one conffile (version 1.0).
|
||||
@@ -0,0 +1,13 @@
|
||||
Package: su-dummy-b
|
||||
Status: install ok installed
|
||||
Priority: optional
|
||||
Section: misc
|
||||
Maintainer: Skeptical Updater Fixture <su-fixture@example.invalid>
|
||||
Architecture: all
|
||||
Version: 1.0
|
||||
Conffiles:
|
||||
/etc/su-dummy/su-dummy-b.conf 607e2d3a119dfe832d937ce579ef1079
|
||||
Description: dummy package su-dummy-b for skeptical-updater tests
|
||||
This package only exists to exercise the package manager.
|
||||
.
|
||||
It ships one data file and one conffile (version 1.0).
|
||||
@@ -0,0 +1,13 @@
|
||||
Package: su-dummy-c
|
||||
Status: install ok installed
|
||||
Priority: optional
|
||||
Section: misc
|
||||
Maintainer: Skeptical Updater Fixture <su-fixture@example.invalid>
|
||||
Architecture: all
|
||||
Version: 1.0
|
||||
Conffiles:
|
||||
/etc/su-dummy/su-dummy-c.conf 607e2d3a119dfe832d937ce579ef1079
|
||||
Description: dummy package su-dummy-c for skeptical-updater tests
|
||||
This package only exists to exercise the package manager.
|
||||
.
|
||||
It ships one data file and one conffile (version 1.0).
|
||||
@@ -0,0 +1,17 @@
|
||||
Available Packages
|
||||
Name : zsh
|
||||
Version : 5.8
|
||||
Release : 9.el9
|
||||
Architecture : x86_64
|
||||
Size : 2.9 M
|
||||
Source : zsh-5.8-9.el9.src.rpm
|
||||
Repository : baseos
|
||||
Summary : Powerful interactive shell
|
||||
URL : http://zsh.sourceforge.net/
|
||||
License : MIT
|
||||
Description : The zsh shell is a command interpreter usable as an interactive login
|
||||
: shell and as a shell script command processor. Zsh resembles the ksh
|
||||
: shell (the Korn shell), but includes many enhancements. Zsh supports
|
||||
: command line editing, built-in spelling correction, programmable
|
||||
: command completion, shell functions (with autoloading), a history
|
||||
: mechanism, and more.
|
||||
@@ -0,0 +1,19 @@
|
||||
Installed Packages
|
||||
Name : glibc
|
||||
Version : 2.34
|
||||
Release : 275.el9_8
|
||||
Architecture : x86_64
|
||||
Size : 6.2 M
|
||||
Source : glibc-2.34-275.el9_8.src.rpm
|
||||
Repository : @System
|
||||
From repo : baseos
|
||||
Summary : The GNU libc libraries
|
||||
URL : http://www.gnu.org/software/glibc/
|
||||
License : LGPL-2.1-or-later AND SunPro AND LGPL-2.1-or-later WITH GCC-exception-2.0 AND BSD-3-Clause AND GPL-2.0-or-later AND LGPL-2.1-or-later WITH GNU-compiler-exception AND GPL-2.0-only AND ISC AND LicenseRef-Fedora-Public-Domain AND HPND AND CMU-Mach AND LGPL-2.0-or-later AND Unicode-3.0 AND GFDL-1.1-or-later AND GPL-1.0-or-later AND FSFUL AND MIT AND Inner-Net-2.0 AND X11 AND GPL-2.0-or-later WITH GCC-exception-2.0 AND GFDL-1.3-only AND GFDL-1.1-only AND GPL-3.0-or-later AND GPL-3.0-or-later WITH Autoconf-exception-generic-3.0 AND GPL-3.0-or-later WITH Texinfo-exception
|
||||
Description : The glibc package contains standard libraries which are used by
|
||||
: multiple programs on the system. In order to save disk space and
|
||||
: memory, as well as to make upgrading easier, common system code is
|
||||
: kept in one place and shared between programs. This particular package
|
||||
: contains the most important sets of shared libraries: the standard C
|
||||
: library and the standard math library. Without these two libraries, a
|
||||
: Linux system will not function.
|
||||
@@ -0,0 +1,13 @@
|
||||
Installed Packages
|
||||
Name : su-dummy-a
|
||||
Version : 1.0
|
||||
Release : 1
|
||||
Architecture : noarch
|
||||
Size : 15
|
||||
Source : su-dummy-a-1.0-1.src.rpm
|
||||
Repository : @System
|
||||
Summary : skeptical-updater dummy su-dummy-a (v1.0)
|
||||
License : MIT
|
||||
Description : Dummy package su-dummy-a version 1.0 for skeptical-updater tests.
|
||||
:
|
||||
: Second paragraph of su-dummy-a 1.0 (blank line above on purpose).
|
||||
@@ -0,0 +1,13 @@
|
||||
Installed Packages
|
||||
Name : su-dummy-b
|
||||
Version : 1.0
|
||||
Release : 1
|
||||
Architecture : noarch
|
||||
Size : 15
|
||||
Source : su-dummy-b-1.0-1.src.rpm
|
||||
Repository : @System
|
||||
Summary : skeptical-updater dummy su-dummy-b (v1.0)
|
||||
License : MIT
|
||||
Description : Dummy package su-dummy-b version 1.0 for skeptical-updater tests.
|
||||
:
|
||||
: Second paragraph of su-dummy-b 1.0 (blank line above on purpose).
|
||||
@@ -0,0 +1,16 @@
|
||||
Installed packages
|
||||
Name : su-dummy-b
|
||||
Epoch : 0
|
||||
Version : 1.0
|
||||
Release : 1
|
||||
Architecture : noarch
|
||||
Installed size : 15.0 B
|
||||
Source : su-dummy-b-1.0-1.src.rpm
|
||||
From repository : <unknown>
|
||||
Summary : skeptical-updater dummy su-dummy-b (v1.0)
|
||||
URL :
|
||||
License : MIT
|
||||
Description : Dummy package su-dummy-b version 1.0 for skeptical-updater tests.
|
||||
:
|
||||
: Second paragraph of su-dummy-b 1.0 (blank line above on purpose).
|
||||
Vendor : <NULL>
|
||||
@@ -0,0 +1,18 @@
|
||||
Available Upgrades
|
||||
Name : glibc
|
||||
Version : 2.34
|
||||
Release : 283.el9_8
|
||||
Architecture : x86_64
|
||||
Size : 2.0 M
|
||||
Source : glibc-2.34-283.el9_8.src.rpm
|
||||
Repository : baseos
|
||||
Summary : The GNU libc libraries
|
||||
URL : http://www.gnu.org/software/glibc/
|
||||
License : LGPL-2.1-or-later AND SunPro AND LGPL-2.1-or-later WITH GCC-exception-2.0 AND BSD-3-Clause AND GPL-2.0-or-later AND LGPL-2.1-or-later WITH GNU-compiler-exception AND GPL-2.0-only AND ISC AND LicenseRef-Fedora-Public-Domain AND HPND AND CMU-Mach AND LGPL-2.0-or-later AND Unicode-3.0 AND GFDL-1.1-or-later AND GPL-1.0-or-later AND FSFUL AND MIT AND Inner-Net-2.0 AND X11 AND GPL-2.0-or-later WITH GCC-exception-2.0 AND GFDL-1.3-only AND GFDL-1.1-only AND GPL-3.0-or-later AND GPL-3.0-or-later WITH Autoconf-exception-generic-3.0 AND GPL-3.0-or-later WITH Texinfo-exception
|
||||
Description : The glibc package contains standard libraries which are used by
|
||||
: multiple programs on the system. In order to save disk space and
|
||||
: memory, as well as to make upgrading easier, common system code is
|
||||
: kept in one place and shared between programs. This particular package
|
||||
: contains the most important sets of shared libraries: the standard C
|
||||
: library and the standard math library. Without these two libraries, a
|
||||
: Linux system will not function.
|
||||
@@ -0,0 +1,13 @@
|
||||
Available Upgrades
|
||||
Name : su-dummy-a
|
||||
Version : 2.0
|
||||
Release : 1
|
||||
Architecture : noarch
|
||||
Size : 6.3 k
|
||||
Source : su-dummy-a-2.0-1.src.rpm
|
||||
Repository : su-dummy
|
||||
Summary : skeptical-updater dummy su-dummy-a (v2.0)
|
||||
License : MIT
|
||||
Description : Dummy package su-dummy-a version 2.0 for skeptical-updater tests.
|
||||
:
|
||||
: Second paragraph of su-dummy-a 2.0 (blank line above on purpose).
|
||||
@@ -0,0 +1,13 @@
|
||||
Available Upgrades
|
||||
Name : su-dummy-b
|
||||
Version : 2.0
|
||||
Release : 1
|
||||
Architecture : noarch
|
||||
Size : 6.5 k
|
||||
Source : su-dummy-b-2.0-1.src.rpm
|
||||
Repository : su-dummy
|
||||
Summary : skeptical-updater dummy su-dummy-b (v2.0)
|
||||
License : MIT
|
||||
Description : Dummy package su-dummy-b version 2.0 for skeptical-updater tests.
|
||||
:
|
||||
: Second paragraph of su-dummy-b 2.0 (blank line above on purpose).
|
||||
@@ -0,0 +1,17 @@
|
||||
Available upgrades
|
||||
Name : su-dummy-b
|
||||
Epoch : 0
|
||||
Version : 2.0
|
||||
Release : 1
|
||||
Architecture : noarch
|
||||
Download size : 6.6 KiB
|
||||
Installed size : 15.0 B
|
||||
Source : su-dummy-b-2.0-1.src.rpm
|
||||
Repository : su-dummy
|
||||
Summary : skeptical-updater dummy su-dummy-b (v2.0)
|
||||
URL :
|
||||
License : MIT
|
||||
Description : Dummy package su-dummy-b version 2.0 for skeptical-updater tests.
|
||||
:
|
||||
: Second paragraph of su-dummy-b 2.0 (blank line above on purpose).
|
||||
Vendor :
|
||||
@@ -264,3 +264,27 @@ Install Reason : Explicitly installed
|
||||
Install Script : No
|
||||
Validated By : None
|
||||
|
||||
|
||||
Name : glib2
|
||||
Version : 2.88.3-1
|
||||
Description : Low level core library
|
||||
Architecture : x86_64
|
||||
URL : https://gitlab.gnome.org/GNOME/glib
|
||||
Licenses : LGPL-2.1-or-later
|
||||
Groups : None
|
||||
Provides : libglib-2.0.so=0-64 libgio-2.0.so=0-64 libgirepository-2.0.so=0-64 libgmodule-2.0.so=0-64 libgobject-2.0.so=0-64 libgthread-2.0.so=0-64
|
||||
Depends On : bash glibc libffi libsysprof-capture pcre2 util-linux-libs zlib libffi.so=8-64 libmount.so=1-64
|
||||
Optional Deps : dconf: GSettings storage backend
|
||||
glib2-devel: development tools
|
||||
gvfs: most gio functionality
|
||||
Required By : libsecret pinentry
|
||||
Optional For : None
|
||||
Conflicts With : None
|
||||
Replaces : None
|
||||
Installed Size : 37.89 MiB
|
||||
Packager : Jan Alexander Steffens (heftig) <heftig@archlinux.org>
|
||||
Build Date : Wed Jul 29 14:57:16 2026
|
||||
Install Date : Sun Oct 4 00:00:00 2026
|
||||
Install Reason : Installed as a dependency for another package
|
||||
Install Script : No
|
||||
Validated By : Signature
|
||||
@@ -93,3 +93,25 @@ Packager : su-fixture <su-fixture@example.invalid>
|
||||
Build Date : Tue Nov 14 22:13:20 2023
|
||||
Validated By : None
|
||||
|
||||
|
||||
Repository : core
|
||||
Name : glib2
|
||||
Version : 2.90.1-1
|
||||
Description : Low level core library
|
||||
Architecture : x86_64
|
||||
URL : https://gitlab.gnome.org/GNOME/glib
|
||||
Licenses : LGPL-2.1-or-later
|
||||
Groups : None
|
||||
Provides : libglib-2.0.so=0-64 libgio-2.0.so=0-64 libgirepository-2.0.so=0-64 libgmodule-2.0.so=0-64 libgobject-2.0.so=0-64 libgthread-2.0.so=0-64
|
||||
Depends On : bash glibc libffi libsysprof-capture pcre2 util-linux-libs zlib libffi.so=8-64 libmount.so=1-64
|
||||
Optional Deps : dconf: GSettings storage backend
|
||||
glib2-devel: development tools
|
||||
gvfs: most gio functionality
|
||||
python: gdbus-codegen
|
||||
Conflicts With : None
|
||||
Replaces : None
|
||||
Download Size : 5.12 MiB
|
||||
Installed Size : 38.39 MiB
|
||||
Packager : Jan Alexander Steffens (heftig) <heftig@archlinux.org>
|
||||
Build Date : Tue Oct 6 16:19:12 2026
|
||||
Validated By : SHA-256 Sum Signature
|
||||
@@ -6,4 +6,5 @@ extra pacman-contrib 1.13.1-1
|
||||
su-dummy su-dummy-a 2.0-1 [installed: 1.0-1]
|
||||
su-dummy su-dummy-b 2.0-1 [installed: 1.0-1]
|
||||
su-dummy su-dummy-c 2.0-1 [installed: 1.0-1]
|
||||
su-dummy su-dummy-new 1.0-1
|
||||
su-dummy2 su-dummy-b 3.0-1
|
||||
@@ -2,8 +2,9 @@
|
||||
# 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, and
|
||||
# `-W -f '${db:Status-Abbrev}' NAME` (the status of one package; purged = unknown to dpkg)
|
||||
# fake dpkg-query (unit tests): the dpkg database dump used for dependency closures,
|
||||
# `-W -f '${db:Status-Abbrev}' NAME` (the status of one package; purged = unknown to dpkg) and
|
||||
# `-s NAME` (dpkg's record: data/apt/status/NAME; none or purged = not installed)
|
||||
# shellcheck source=../fakelib.bash
|
||||
. "${BASH_SOURCE[0]%/*}/../fakelib.bash"
|
||||
fake_log "$@"
|
||||
@@ -21,6 +22,15 @@ while (($#)); do
|
||||
esac
|
||||
shift
|
||||
done
|
||||
if [[ $args == *' -s '* ]]; then
|
||||
n=${names[0]%:amd64}
|
||||
if [[ ! -f $FAKE_DATA/apt/status/$n ]] || fake_purged "$n"; then
|
||||
echo "dpkg-query: package '$n' is not installed and no information is available" >&2
|
||||
exit 1
|
||||
fi
|
||||
cat "$FAKE_DATA/apt/status/$n"
|
||||
exit 0
|
||||
fi
|
||||
if ((${#names[@]})); then
|
||||
rc=0
|
||||
for n in "${names[@]}"; do
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
# "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.
|
||||
# it, FAKE_DNF_REPOQUERY_RC=N makes repoquery fail. `info --installed|--upgrades|--available PKG`
|
||||
# replays data/dnf/info-<which>-PKG-dnf<major>.txt (none: no match); FAKE_DNF_INFO_TWICE=<which>
|
||||
# prints that block twice (two installed architectures, ...). Plain `info PKG`: data/dnf/info-PKG.txt.
|
||||
# shellcheck source=../fakelib.bash
|
||||
. "${BASH_SOURCE[0]%/*}/../fakelib.bash"
|
||||
# shellcheck source=../../data/rpm/db.bash
|
||||
@@ -72,10 +74,23 @@ case " $* " in
|
||||
;;
|
||||
*' 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
|
||||
f=$D/info-$p.txt
|
||||
w=''
|
||||
case " $* " in
|
||||
*' --installed '*) w=installed ;;
|
||||
*' --upgrades '*) w=upgrades ;;
|
||||
*' --available '*) w=available ;;
|
||||
esac
|
||||
[[ -z $w ]] || f=$D/info-$w-$p-dnf$major.txt
|
||||
if [[ ! -f $f ]] || { [[ $w == installed ]] && fake_purged "$p"; }; then
|
||||
if ((major == 5)); then echo "No matching packages to list" >&2; else echo "Error: No matching Packages to list" >&2; fi
|
||||
exit 1
|
||||
fi
|
||||
cat "$f"
|
||||
if [[ -n $w && ${FAKE_DNF_INFO_TWICE:-} == "$w" ]]; then
|
||||
echo
|
||||
sed '1d' "$f"
|
||||
fi
|
||||
;;
|
||||
*' --assumeno '*remove*)
|
||||
# the removal table: the target, its dependents (su-dummy-a for su-dummy-b; FAKE_DNF_DEPENDENT=
|
||||
|
||||
@@ -20,23 +20,26 @@
|
||||
fake_log "$@"
|
||||
D=$FAKE_DATA/pacman
|
||||
|
||||
# blocks FILE NAME...: print the blank-line separated blocks whose Name is one of NAME
|
||||
# (all blocks when no NAME); exit 1 (after printing the others) if a NAME is missing
|
||||
# blocks FILE NAME...: print the blank-line separated blocks whose Name is one of NAME, or whose
|
||||
# Repository/Name is (-Si repo/name); all blocks when no NAME; exit 1 (after printing the others)
|
||||
# if a NAME is missing
|
||||
blocks() {
|
||||
local f=$1 line block='' name='' rc=0 n
|
||||
local f=$1 line block='' name='' repo='' rc=0 n
|
||||
shift
|
||||
local -A want=() found=()
|
||||
for n in "$@"; do want[$n]=1; done
|
||||
while IFS= read -r line || [[ -n $block ]]; do
|
||||
if [[ -z $line ]]; then
|
||||
if [[ -n $block ]] && { (($# == 0)) || [[ -n ${want[$name]:-} ]]; } && ! fake_purged "$name"; then
|
||||
if [[ -n $block ]] && { (($# == 0)) || [[ -n ${want[$name]:-} || -n ${want[$repo/$name]:-} ]]; } && ! fake_purged "$name"; then
|
||||
printf '%s\n' "$block"
|
||||
found[$name]=1
|
||||
found[$repo/$name]=1
|
||||
fi
|
||||
block='' name=''
|
||||
block='' name='' repo=''
|
||||
continue
|
||||
fi
|
||||
[[ $line =~ ^Name\ +:\ (.*)$ ]] && name=${BASH_REMATCH[1]}
|
||||
[[ $line =~ ^Repository\ +:\ (.*)$ ]] && repo=${BASH_REMATCH[1]}
|
||||
block+=$line$'\n'
|
||||
done <"$f"
|
||||
for n in "$@"; do
|
||||
@@ -121,11 +124,7 @@ case $op in
|
||||
{ print }' <<<"$out"
|
||||
exit "$rc"
|
||||
;;
|
||||
-Si)
|
||||
t=()
|
||||
for a in "${targets[@]}"; do t+=("${a#*/}"); done
|
||||
blocks "$D/Si.txt" "${t[@]}"
|
||||
;;
|
||||
-Si) blocks "$D/Si.txt" "${targets[@]}" ;;
|
||||
-Su | -Syu)
|
||||
echo "real sync at $op: $(cat "$FAKE_PACMAN_DBPATH/sync/su-dummy.db" 2>/dev/null || echo none) / $(cat "$FAKE_PACMAN_DBPATH/sync/su-dummy.db.sig" 2>/dev/null || echo no-sig)" >>"$FAKE_LOG"
|
||||
if [[ -e $FAKE_PACMAN_DBPATH/db.lck ]]; then echo "db.lck at $op: yes" >>"$FAKE_LOG"; else echo "db.lck at $op: no" >>"$FAKE_LOG"; fi
|
||||
|
||||
@@ -90,14 +90,25 @@ UPGRADE='apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--forc
|
||||
log_lacks '^dpkg-query -W -f \$\{db:Status-Abbrev\} '
|
||||
}
|
||||
|
||||
@test "N?? prints the native full info" {
|
||||
@test "N?? prints the installed record merged with the candidate" {
|
||||
run skup --no-refresh <<<$'1??\nq'
|
||||
assert_success
|
||||
assert_line '# lines starting with > come from the upstream candidate: a differing value, or a field the installed record lacks'
|
||||
assert_line 'Package: su-dummy-a'
|
||||
assert_line 'Depends: su-dummy-b (>= 2.0)'
|
||||
assert_line 'Version: 1.0'
|
||||
assert_line '> Version: 2.0'
|
||||
assert_line '> Depends: su-dummy-b (>= 2.0)'
|
||||
log_has 'dpkg-query -s -- su-dummy-a'
|
||||
log_has 'apt-cache show --no-all-versions su-dummy-a'
|
||||
}
|
||||
|
||||
@test "N?? on a new dependency (old version -) never looks for an installed record" {
|
||||
FAKE_APT_SIM=real run skup --no-refresh <<<$'9??\nq'
|
||||
assert_success
|
||||
log_lacks '^dpkg-query -s'
|
||||
log_has 'apt-cache show --no-all-versions su-dummy-newdep'
|
||||
}
|
||||
|
||||
@test "N- toggles the exclusion and the '-' marker" {
|
||||
run skup --no-refresh <<<$'2-\nl\n2-\nl\n2-\n'
|
||||
assert_success
|
||||
|
||||
+208
-14
@@ -111,17 +111,70 @@ setup() { common_setup; }
|
||||
assert_line 'no-such-pkg-xyz: (no description available: unknown package?)'
|
||||
}
|
||||
|
||||
@test "apt: show is apt-cache show --no-all-versions (the candidate)" {
|
||||
@test "apt: show merges dpkg's installed record (dpkg-query -s) with the candidate (apt-cache show)" {
|
||||
# changed Version, local-only Status/Conffiles, identical fields once, a differing multi-line
|
||||
# Description (prefixed on every line), candidate-only fields appended
|
||||
run skup show su-dummy-b
|
||||
assert_success
|
||||
assert_output "$(cat <<'EOF'
|
||||
# lines starting with > come from the upstream candidate: a differing value, or a field the installed record lacks
|
||||
Package: su-dummy-b
|
||||
Status: install ok installed
|
||||
Priority: optional
|
||||
Section: misc
|
||||
Maintainer: Skeptical Updater Fixture <su-fixture@example.invalid>
|
||||
Architecture: all
|
||||
Version: 1.0
|
||||
> Version: 2.0
|
||||
Conffiles:
|
||||
/etc/su-dummy/su-dummy-b.conf 607e2d3a119dfe832d937ce579ef1079
|
||||
Description: dummy package su-dummy-b for skeptical-updater tests
|
||||
This package only exists to exercise the package manager.
|
||||
.
|
||||
It ships one data file and one conffile (version 1.0).
|
||||
> Description: dummy package su-dummy-b for skeptical-updater tests
|
||||
> This package only exists to exercise the package manager.
|
||||
> .
|
||||
> It ships one data file and one conffile (version 2.0).
|
||||
> Description-md5: 36da7dcdaf4ec207be2937d1f5dfa408
|
||||
> Filename: ./su-dummy-b_2.0_all.deb
|
||||
> Size: 840
|
||||
EOF
|
||||
)"
|
||||
log_has 'dpkg-query -s -- su-dummy-b'
|
||||
log_has 'apt-cache show --no-all-versions su-dummy-b'
|
||||
run skup show su-dummy-a
|
||||
assert_success
|
||||
assert_line 'Package: su-dummy-a'
|
||||
assert_line 'Version: 2.0'
|
||||
assert_line 'Depends: su-dummy-b (>= 2.0)'
|
||||
assert_line 'Depends: su-dummy-b'
|
||||
assert_line '> Depends: su-dummy-b (>= 2.0)'
|
||||
run skup show no-such-pkg-xyz
|
||||
assert_failure 1
|
||||
assert_output --partial "no package information for 'no-such-pkg-xyz' (apt exited 100)"
|
||||
}
|
||||
|
||||
@test "apt: a one-line candidate Description (the archives' short form) equals the installed long one" {
|
||||
# real debian:12 records: perl-base 5.36.0-7+deb12u3 installed, +deb12u4 from bookworm-security
|
||||
run skup show perl-base
|
||||
assert_success
|
||||
[[ $(grep -c '^Description: minimal Perl system$' <<<"$output") -eq 1 ]]
|
||||
refute_line --partial '> Description:'
|
||||
assert_output --partial "$(printf '%s\n' 'Installed-Size: 7639' '> Installed-Size: 7643')"
|
||||
assert_output --partial "$(printf '%s\n' 'Version: 5.36.0-7+deb12u3' '> Version: 5.36.0-7+deb12u4')"
|
||||
[[ $(grep -c '^Breaks: ' <<<"$output") -eq 1 ]]
|
||||
refute_line --regexp '^> (Breaks|Pre-Depends|Essential|Source):'
|
||||
assert_line --index -1 '> SHA256: d7d1943aec9597629bf73075efcc5ef6dc9bda96d78e80d843156ecd448478b8'
|
||||
}
|
||||
|
||||
@test "apt: show of a package that is not installed prints the candidate alone, with a note" {
|
||||
run skup show zsh
|
||||
assert_success
|
||||
assert_line --index 0 '# not installed: this is the upstream candidate'
|
||||
assert_line --index 1 'Package: zsh'
|
||||
assert_line --index 3 'Version: 5.9-4+b15'
|
||||
refute_line --partial '> '
|
||||
log_has 'dpkg-query -s -- zsh'
|
||||
}
|
||||
|
||||
# ---- pacman -------------------------------------------------------------------------------------
|
||||
|
||||
@test "pacman: -Qu joined with the FIRST -Sl repo; [ignored] => held" {
|
||||
@@ -219,15 +272,73 @@ setup() { common_setup; }
|
||||
assert_output 'trusted su-dummy-a (+1 dependency: su-dummy-b)'
|
||||
}
|
||||
|
||||
@test "pacman: show prints the installed (-Qi) and the candidate (-Si) records" {
|
||||
@test "pacman: show merges -Qi with -Si of the candidate's repository: '>' lines for what differs" {
|
||||
# real archlinux records (glib2 2.88.3-1 installed, core 2.90.1-1), one Optional Deps entry
|
||||
# added to the candidate: changed fields, identical ones once, -Qi-only fields kept, a differing
|
||||
# multi-line block, -Si-only fields appended
|
||||
use_fakes pacman
|
||||
run skup show su-dummy-a
|
||||
run skup show glib2
|
||||
assert_success
|
||||
assert_line 'Install Reason : Explicitly installed'
|
||||
assert_line 'Repository : su-dummy'
|
||||
assert_line 'Version : 2.0-1'
|
||||
log_has 'pacman -Qi -- su-dummy-a'
|
||||
log_has 'pacman -Si -- su-dummy-a'
|
||||
assert_output "$(cat <<'EOF'
|
||||
# lines starting with > come from the upstream candidate: a differing value, or a field the installed record lacks
|
||||
Name : glib2
|
||||
Version : 2.88.3-1
|
||||
> Version : 2.90.1-1
|
||||
Description : Low level core library
|
||||
Architecture : x86_64
|
||||
URL : https://gitlab.gnome.org/GNOME/glib
|
||||
Licenses : LGPL-2.1-or-later
|
||||
Groups : None
|
||||
Provides : libglib-2.0.so=0-64 libgio-2.0.so=0-64 libgirepository-2.0.so=0-64 libgmodule-2.0.so=0-64 libgobject-2.0.so=0-64 libgthread-2.0.so=0-64
|
||||
Depends On : bash glibc libffi libsysprof-capture pcre2 util-linux-libs zlib libffi.so=8-64 libmount.so=1-64
|
||||
Optional Deps : dconf: GSettings storage backend
|
||||
glib2-devel: development tools
|
||||
gvfs: most gio functionality
|
||||
> Optional Deps : dconf: GSettings storage backend
|
||||
> glib2-devel: development tools
|
||||
> gvfs: most gio functionality
|
||||
> python: gdbus-codegen
|
||||
Required By : libsecret pinentry
|
||||
Optional For : None
|
||||
Conflicts With : None
|
||||
Replaces : None
|
||||
Installed Size : 37.89 MiB
|
||||
> Installed Size : 38.39 MiB
|
||||
Packager : Jan Alexander Steffens (heftig) <heftig@archlinux.org>
|
||||
Build Date : Wed Jul 29 14:57:16 2026
|
||||
> Build Date : Tue Oct 6 16:19:12 2026
|
||||
Install Date : Sun Oct 4 00:00:00 2026
|
||||
Install Reason : Installed as a dependency for another package
|
||||
Install Script : No
|
||||
Validated By : Signature
|
||||
> Validated By : SHA-256 Sum Signature
|
||||
> Repository : core
|
||||
> Download Size : 5.12 MiB
|
||||
EOF
|
||||
)"
|
||||
log_has 'pacman -Qi -- glib2'
|
||||
log_has 'pacman -Si -- core/glib2'
|
||||
}
|
||||
|
||||
@test "pacman: the candidate comes from the first repository -Sl lists; no -Si record = the plain -Qi" {
|
||||
use_fakes pacman
|
||||
run skup show su-dummy-b
|
||||
assert_success
|
||||
assert_output --partial "$(printf '%s\n' 'Version : 1.0-1' '> Version : 2.0-1')"
|
||||
assert_line 'Required By : su-dummy-a'
|
||||
refute_output --partial '3.0-1'
|
||||
log_has 'pacman -Si -- su-dummy/su-dummy-b'
|
||||
# bash: in the sync list, but no -Si record - the output stays what it was (-Qi, then -Si)
|
||||
run skup show bash
|
||||
assert_success
|
||||
assert_line --index 0 'Name : bash'
|
||||
refute_line --partial '# lines starting with >'
|
||||
# not installed: the candidate alone
|
||||
run skup show su-dummy-new
|
||||
assert_success
|
||||
assert_line --index 0 '# not installed: this is the upstream candidate'
|
||||
assert_line --index 1 'Repository : su-dummy'
|
||||
refute_line --partial '> '
|
||||
run skup show nope
|
||||
assert_failure 1
|
||||
}
|
||||
@@ -238,6 +349,7 @@ setup() { common_setup; }
|
||||
run skup info glibc
|
||||
run skup list --no-refresh
|
||||
run skup trust bash
|
||||
run skup show glib2
|
||||
run grep -v ' 0$' "$FAKE_DIR/pacman-columns"
|
||||
assert_output ''
|
||||
}
|
||||
@@ -391,12 +503,93 @@ setup() { common_setup; }
|
||||
log_has 'dnf -y remove su-dummy-a su-dummy-b'
|
||||
}
|
||||
|
||||
@test "dnf: show is dnf -q info" {
|
||||
@test "dnf4: show merges info --installed with info --upgrades (headings dropped)" {
|
||||
use_fakes dnf rpm
|
||||
run skup show su-dummy-a
|
||||
run skup show su-dummy-b
|
||||
assert_success
|
||||
assert_output "$(cat <<'EOF'
|
||||
# lines starting with > come from the upstream candidate: a differing value, or a field the installed record lacks
|
||||
Name : su-dummy-b
|
||||
Version : 1.0
|
||||
> Version : 2.0
|
||||
Release : 1
|
||||
Architecture : noarch
|
||||
Size : 15
|
||||
> Size : 6.5 k
|
||||
Source : su-dummy-b-1.0-1.src.rpm
|
||||
> Source : su-dummy-b-2.0-1.src.rpm
|
||||
Repository : @System
|
||||
> Repository : su-dummy
|
||||
Summary : skeptical-updater dummy su-dummy-b (v1.0)
|
||||
> Summary : skeptical-updater dummy su-dummy-b (v2.0)
|
||||
License : MIT
|
||||
Description : Dummy package su-dummy-b version 1.0 for skeptical-updater tests.
|
||||
:
|
||||
: Second paragraph of su-dummy-b 1.0 (blank line above on purpose).
|
||||
> Description : Dummy package su-dummy-b version 2.0 for skeptical-updater tests.
|
||||
> :
|
||||
> : Second paragraph of su-dummy-b 2.0 (blank line above on purpose).
|
||||
EOF
|
||||
)"
|
||||
log_has 'dnf -q info --installed su-dummy-b'
|
||||
log_has 'dnf -q info --upgrades su-dummy-b'
|
||||
# real almalinux:9 records: an identical multi-line Description once, "From repo" (installed only) kept
|
||||
run skup show glibc
|
||||
assert_success
|
||||
assert_output --partial "$(printf '%s\n' 'Release : 275.el9_8' '> Release : 283.el9_8')"
|
||||
assert_line 'From repo : baseos'
|
||||
[[ $(grep -c '^Description : The glibc package contains' <<<"$output") -eq 1 ]]
|
||||
[[ $(grep -c 'Linux system will not function\.$' <<<"$output") -eq 1 ]]
|
||||
}
|
||||
|
||||
@test "dnf5: show merges records whose keys are padded differently (re-padded, extra fields appended)" {
|
||||
use_fakes dnf rpm
|
||||
FAKE_DNF_MAJOR=5 run skup show su-dummy-b
|
||||
assert_success
|
||||
assert_output "$(cat <<'EOF'
|
||||
# lines starting with > come from the upstream candidate: a differing value, or a field the installed record lacks
|
||||
Name : su-dummy-b
|
||||
Epoch : 0
|
||||
Version : 1.0
|
||||
> Version : 2.0
|
||||
Release : 1
|
||||
Architecture : noarch
|
||||
Installed size : 15.0 B
|
||||
Source : su-dummy-b-1.0-1.src.rpm
|
||||
> Source : su-dummy-b-2.0-1.src.rpm
|
||||
From repository : <unknown>
|
||||
Summary : skeptical-updater dummy su-dummy-b (v1.0)
|
||||
> Summary : skeptical-updater dummy su-dummy-b (v2.0)
|
||||
URL :
|
||||
License : MIT
|
||||
Description : Dummy package su-dummy-b version 1.0 for skeptical-updater tests.
|
||||
:
|
||||
: Second paragraph of su-dummy-b 1.0 (blank line above on purpose).
|
||||
> Description : Dummy package su-dummy-b version 2.0 for skeptical-updater tests.
|
||||
> :
|
||||
> : Second paragraph of su-dummy-b 2.0 (blank line above on purpose).
|
||||
Vendor : <NULL>
|
||||
> Vendor :
|
||||
> Download size : 6.6 KiB
|
||||
> Repository : su-dummy
|
||||
EOF
|
||||
)"
|
||||
}
|
||||
|
||||
@test "dnf: not installed = info --available alone; not one record per side = the plain dnf -q info" {
|
||||
use_fakes dnf rpm
|
||||
run skup show zsh
|
||||
assert_success
|
||||
assert_line --index 0 '# not installed: this is the upstream candidate'
|
||||
assert_line --index 1 'Name : zsh'
|
||||
refute_line 'Available Packages'
|
||||
log_has 'dnf -q info --available zsh'
|
||||
# two installed records (e.g. two architectures): nothing to pair, the output stays dnf -q info
|
||||
FAKE_DNF_INFO_TWICE=installed run skup show su-dummy-a
|
||||
assert_success
|
||||
refute_line --partial '# lines starting with >'
|
||||
assert_line 'Installed Packages'
|
||||
assert_line 'Available Upgrades'
|
||||
assert_line 'Version : 2.0'
|
||||
log_has 'dnf -q info su-dummy-a'
|
||||
}
|
||||
|
||||
@@ -481,6 +674,7 @@ setup() { common_setup; }
|
||||
run skup show su-dummy-a
|
||||
assert_success
|
||||
assert_line 'Information for package su-dummy-a:'
|
||||
refute_line --partial '# lines starting with >'
|
||||
log_has 'zypper --non-interactive --quiet info --requires su-dummy-a'
|
||||
run skup show nothing-like-this
|
||||
assert_failure 1
|
||||
|
||||
Reference in new issue
Block a user