lsupg Progress
I have made some progress on lsupg over the past few days. I made significant changes to the (internal) design as well as the (external) interface. Here is the current CLI:
Usage: lsupg [--debug] [-f|--format FORMAT] [--docker IMAGE] [COMPONENT ...]
list items that can be upgraded
Available options:
-h,--help show help and exit
--version show version and exit
--debug show debug output
-f,--format FORMAT output format (default: human)
--docker IMAGE Docker image
COMPONENT ... components (default: all)
FORMATs:
human, csv, json, yaml
COMPONENTs:
apk Alpine Linux packages
apt Debian packages
dnf Fedora packages
nix Nix packages
pacman Arch Linux packages
Exit codes:
0 no upgrades available
1 program error
2 program usage error
3 one or more upgrades available
Components
apk
Parsing apk
output is very straightforward. I do not
know what the output looks like in the case that an upgrade requires the
installation of a new package, however. Currently, the new package will
simply not be listed.
Demonstration:
[lsupg] build$ ./lsupg --docker alpine:latest
apk musl 1.2.2-r0 1.2.2-r1
apk musl-utils 1.2.2-r0 1.2.2-r1
apt
Parsing apt
output is very straightforward. New packages
that are to be installed as a dependency of an upgrade are parsed
correctly.
Demonstration:
[lsupg] build$ ./lsupg --docker debian:buster
apt liblz4-1 1.8.3-1 1.8.3-1+deb10u1
dnf
Parsing dnf
output is very straightforward, but it
unfortunately does not include the version that is currently installed.
This information could be obtained by running additional commands, but I
am currently simply not showing that information. I also do not know
what the output looks like in the case that an upgrade requires the
installation of a new package. Currently, the new package will simply
not be listed.
The dnf
software is a replacement for yum
,
which it a replacement for rpm
. In the
fedora:34
image, either dnf
or
yum
can be used to manage installed packages! Currently, I
am just supporting dnf
. If I find a system that still uses
yum
, I will implement support for it. In doing so, I should
only run yum
in cases where dnf
has not
already been run. If rpm
support is added, it will likely
need similar checks. There are various ways to implement this, but I
will not worry about it until I have a need to do so.
Most Linux package managers have separate “update” and “upgrade”
steps. The “update” step synchronizes the package database, and the
“upgrade” step uses this database to determine which packages should be
upgraded. Automated tools usually have a setting to avoid doing the
“update” step too frequently, and the initial lsupg
design
included such an --update
flag. The dnf
software does not match this design, however, as it has the
functionality built in. There is likely a setting in
/etc/dnf
to configure. Considering the options, I decided
to remove the --update
flag completely.
Demonstration:
[lsupg] build$ ./lsupg --docker fedora:34
dnf coreutils.x86_64 8.32-27.fc34
dnf coreutils-common.x86_64 8.32-27.fc34
dnf curl.x86_64 7.76.1-4.fc34
dnf dnf.noarch 4.7.0-1.fc34
dnf dnf-data.noarch 4.7.0-1.fc34
dnf elfutils-default-yama-scope.noarch 0.185-2.fc34
dnf elfutils-libelf.x86_64 0.185-2.fc34
dnf elfutils-libs.x86_64 0.185-2.fc34
dnf file-libs.x86_64 5.39-6.fc34
dnf glib2.x86_64 2.68.2-1.fc34
dnf glibc.x86_64 2.33-15.fc34
dnf glibc-common.x86_64 2.33-15.fc34
dnf glibc-minimal-langpack.x86_64 2.33-15.fc34
dnf gnutls.x86_64 3.7.2-1.fc34
dnf krb5-libs.x86_64 1.19.1-8.fc34
dnf libcurl.x86_64 7.76.1-4.fc34
dnf libdnf.x86_64 0.62.0-1.fc34
dnf libgcc.x86_64 11.1.1-3.fc34
dnf libgomp.x86_64 11.1.1-3.fc34
dnf libidn2.x86_64 2.3.1-1.fc34
dnf librepo.x86_64 1.14.0-1.fc34
dnf libreport-filesystem.noarch 2.15.2-2.fc34
dnf libsss_idmap.x86_64 2.5.0-2.fc34
dnf libsss_nss_idmap.x86_64 2.5.0-2.fc34
dnf libstdc++.x86_64 11.1.1-3.fc34
dnf libtirpc.x86_64 1.3.2-0.fc34
dnf libxml2.x86_64 2.9.12-4.fc34
dnf libzstd.x86_64 1.5.0-1.fc34
dnf mpfr.x86_64 4.1.0-7.fc34
dnf python-pip-wheel.noarch 21.0.1-3.fc34
dnf python3.x86_64 3.9.5-2.fc34
dnf python3-dnf.noarch 4.7.0-1.fc34
dnf python3-hawkey.x86_64 0.62.0-1.fc34
dnf python3-libdnf.x86_64 0.62.0-1.fc34
dnf python3-libs.x86_64 3.9.5-2.fc34
dnf sssd-client.x86_64 2.5.0-2.fc34
dnf systemd-libs.x86_64 248.3-1.fc34
dnf tpm2-tss.x86_64 3.1.0-1.fc34
dnf vim-minimal.x86_64 2:8.2.2956-1.fc34
dnf yum.noarch 4.7.0-1.fc34
dnf zchunk-libs.x86_64 1.1.15-1.fc34
nix
Parsing nix
output is not as straightforward. The issue
is that it does not display package names and versions separately. For
example, it displays nix-2.3.11
instead of nix
and 2.3.11
. Unless there are specific rules about package
names and versions, it is impossible to parse perfectly. Currently, I
split one the -
character and assume that the version
starts at the first chunk that starts with a digit. I may need to change
this implementation in the future. Due to the way that Nix works, new
packages are not (should not be) listed.
Demonstration:
[lsupg] build$ ./lsupg --docker nixos/nix:latest
apk musl 1.2.2-r0 1.2.2-r1
apk musl-utils 1.2.2-r0 1.2.2-r1
nix nix 2.3.11 2.3.12
Notice that apk
packages are listed as well, as the
nixos/nix
image is built using Alpine Linux.
pacman
Parsing pacman
output is very straightforward. I do not
know what the output looks like in the case that an upgrade requires the
installation of a new package, however. Currently, the new package will
simply not be listed.
Demonstration:
[lsupg] build$ ./lsupg --docker archlinux:latest
pacman ca-certificates 20181109-4 20210603-1
pacman ca-certificates-mozilla 3.64-1 3.67-1
pacman ca-certificates-utils 20181109-4 20210603-1
pacman cryptsetup 2.3.5-4 2.3.6-1
pacman curl 7.76.1-1 7.77.0-1
pacman expat 2.3.0-1 2.4.1-1
pacman file 5.40-3 5.40-5
pacman filesystem 2021.01.19-1 2021.05.31-1
pacman gcc-libs 10.2.0-6 11.1.0-1
pacman glibc 2.33-4 2.33-5
pacman gnutls 3.7.1-1 3.7.2-2
pacman kmod 28-1 29-1
pacman libcap 2.49-1 2.50-2
pacman libelf 0.184-1 0.185-1
pacman libidn2 2.3.0-1 2.3.1-1
pacman libldap 2.4.58-2 2.4.58-3
pacman libnftnl 1.1.9-1 1.2.0-1
pacman libnl 3.5.0-2 3.5.0-3
pacman libp11-kit 0.23.22-1 0.24.0-1
pacman libpcap 1.10.0-1 1.10.1-1
pacman libtasn1 4.16.0-1 4.17.0-1
pacman libtirpc 1.3.1-1 1.3.2-1
pacman libxcrypt 4.4.20-1 4.4.22-4
pacman linux-api-headers 5.10.13-1 5.12.3-1
pacman lz4 1:1.9.3-1 1:1.9.3-2
pacman nettle 3.7.2-1 3.7.3-1
pacman p11-kit 0.23.22-1 0.24.0-1
pacman pacman 5.2.2-3 6.0.0-3
pacman pambase 20200721.1-2 20210605-2
pacman pcre2 10.36-1 10.37-1
pacman sqlite 3.35.5-1 3.35.5-2
pacman systemd 248.2-2 248.3-2
pacman systemd-libs 248.2-2 248.3-2
pacman systemd-sysvcompat 248.2-2 248.3-2
pacman util-linux 2.36.2-1 2.37-3
pacman util-linux-libs 2.36.2-1 2.37-3
pacman zstd 1.4.9-1 1.5.0-1
Output Formats
human
The human
format is for when a human reads the output in
the terminal or when only the exit code is used. It displays a table
with the following columns. Note that the headings are not
displayed.
Column | Heading | Description |
---|---|---|
1 | Component Name | lsupg component |
2 | Item Name | thing that can be upgraded |
3 | Installed Version | version that is currently installed |
4 | Available Version | version available for upgrade |
The installed version and available version may be empty. I would like to use the following interpretations:
Installed Version | Available Version | Interpretation |
---|---|---|
Shown | Shown | upgrade/downgrade |
Shown | Empty | removal |
Empty | Shown | new install |
Unfortunately, the current implementation of the dnf
component does not include the installed versions of packages. I either
need to get that information or not use these interpretations.
Demonstration:
[lsupg] build$ ./lsupg --docker alpine:latest
apk musl 1.2.2-r0 1.2.2-r1
apk musl-utils 1.2.2-r0 1.2.2-r1
csv
The csv
format displays the information in CSV
format.
Demonstration:
[lsupg] build$ ./lsupg --docker alpine:latest -f csv
apk,musl,1.2.2-r0,1.2.2-r1
apk,musl-utils,1.2.2-r0,1.2.2-r1
json
The json
format displays the information in JSON format.
Since it is intended to be machine-parsed, it it minimized.
Demonstration, with external reformatting for humans:
[lsupg] build$ ./lsupg --docker alpine:latest -f json | python3 -m json.tool
[
{
"available_version": "1.2.2-r1",
"installed_version": "1.2.2-r0",
"item_name": "musl",
"component_name": "apk"
},
{
"available_version": "1.2.2-r1",
"installed_version": "1.2.2-r0",
"item_name": "musl-utils",
"component_name": "apk"
}
]
yaml
The yaml
format displays the information in YAML
format.
Demonstration:
[lsupg] build$ ./lsupg --docker alpine:latest -f yaml
- available_version: 1.2.2-r1
installed_version: 1.2.2-r0
item_name: musl
component_name: apk
- available_version: 1.2.2-r1
installed_version: 1.2.2-r0
item_name: musl-utils
component_name: apk