CRUX : Home

Home :: Documentation :: Download :: Development :: Community :: Wiki :: Ports :: Bugs :: Links :: About

Back to wiki start page Categories: Development

Notes on Flyspray Task 1843

Was: Re: Please make the output of prt-get --test more common

teodor observed that prt-get --test gives two different styles of output. The output style was found to be affected by the number of packages requested on the command line (one versus many), and by whether dependency resolution was toggled (install versus depinst).

In the case when one package was requested for installation, an early check of /var/lib/pkg/db for the existence of a previous installation would alert the user to the malformed command. No such check of /var/lib/pkg/db was being performed for multiple packages passed on the command line, and so the program continued all the way through executeTransaction() and evaluateResult(), which produced the more verbose output that teodor noted.

A similar discrepancy could be observed when requesting an update of one package that was not previously installed, versus an update of multiple packages among which there are some not yet installed. You would have seen a terse warning in the first case, and a more verbose output in the second case.

To accommodate the oft-requested feature "inject new dependencies during a sysup", farkuhar's fork of prt-get collapses the distinction between install and update, always bringing up to date all the ports passed as argument (and their dependencies, unless --nodeps is given), so it can postpone the scan of /var/lib/pkg/db until the step of customizing pkgadd flags for each target. Hence there is no corresponding code in this fork to perform a preliminary scan of /var/lib/pkg/db and exit early with an error message if none of the arguments is a valid target for the requested operation.

teodor's second observation is more interesting. During dependency resolution, the invalid arguments (ports not found in the active repos) were silently being dropped, rather than being kept in memory for a post-transaction report. If all ports passed to a depinst command are nowhere among the active repositories, then the empty set is what gets used for executeTransaction(), with the predictable result "no package specified for install". Why did we see a different result when running install? Because the calculateDependencies() method was never called, and so executeTransaction() received the entire list of nowhere-to-be-found ports! Iterating through this list of nonexistent ports would populate the missingPackages list, which would then be displayed nicely during the post-transaction summary. This side-effect of toggling dependency resolution could still be observed in farkuhar's forked prt-get until the commits of 2023-09-15.

Although we do populate a missingPackages list during calculateDependencies(), the contents of this list were not being included in the post-transaction summary. As the code was originally conceived, executeTransaction() would get a filtered list, with missing packages omitted. This side-effect of depinst violates the principle of least surprise, because users like teodor might justifiably expect toggling dependency resolution to generate a superset of their argument list @ARGV, not just a superset of the valid ports in @ARGV. To be more faithful to the principle of least surprise, farkuhar's fork now propagates into executeTransaction() even the ports that are not in the repos, so that the post-transaction summary can display them. But because it merges install and update, any requested targets that are already installed and up-to-date will appear in the post-transaction summary under the header "Packages already installed before this run (ignored)".

With dependency resolution enabled, the list of "Packages already installed before this run (ignored)" often fills up the entire height of a terminal. If we implemented teodor's suggestion and united the list of "Packages not found" with this list --- already often big enough on its own --- then readability of the post-transaction summary would suffer. Two separate lists would offer greater readability in most cases, both for the human eye and for a shell script.

teodor's proposed heading for a united list, "The following ports were not found/already installed:", did inspire a new way for the (now deleted) softdeps branch to handle FS#1843. All arguments to install and depinst were tested against /var/lib/pkg/db to ensure that they were not already installed, and if all the tests failed then the user was immediately alerted to the malformed command. This preliminary check was simply jw's original design, but extended from one port to many. However, if any of the requested ports was not yet installed, the softdeps branch went ahead with initRepo() and attempted a less ambitious transaction (limited to a subset of the user's argument list). The program reached evaluateTransaction() and displayed what succeeded, as well as what was wrong with the original command.

The softdeps branch had no corresponding leniency in handling an update command, because the typical scenario for using that command is after running prt-get diff, at which point the user can be expected to know what's on their system and to pass as arguments only the names of packages already installed. So the early exit behaviour of the first proposed solution to FS#1843 was retained for the update command. But it's easy to imagine a user passing invalid targets to an install command, in the absence of any cues from running prt-get listinst | grep -E "(package1|package2|...|packageN)", and to handle that possibility it makes sense to parse leniently the arguments passed to install. Users then obtained on the first try, most of what they intended, while also getting an informative list of already-installed packages in the post-transaction report. If they really intended to force the rebuild of those already-installed packages, they could issue a revised command after the first command succeeded.