Rename jw.pkg.cmds.distro.backend.BackendCmd to Backend, because it's not necessarily a command, i.e. doesn't necessarily have a run() method. It's more of a distribution abstraction of the steps needed for for a specific command, the run() method itself is implemented in jw.pkg.cmds.distro.CmdXxx.
This commit is the beginning of a bigger move to change the distribution backend class hierarchy. At the end of this change set, the backend command should not derive the backend classes from a base specific to the respective distribution, but from an abstract base class specific to the command run. The distribution specifics are then going to be encapsulated in another class called "Util", an instance of which is going to be provided to the backend as .util member.
Move the body of BackendCmd.sudo() into a function. The rationale behind that is that its functionality is independent of the calling object for the most part, so having it in a function instead of a method is the more modular pattern.
Add more fields to the OS cascade returned by App.os_cascade, based on the ID field in /etc/os-release. This includes some new ones, prefixed by pkg-, revealing which package format is used.
apt-get install suggests it wants to be called with -f to clean up some mess left behind from a previous install. Adding -f in the hope add it to the install options by default. OTOH, it wants to be called that without arguments, not sure if always passing it along is a good idea.
The man page says:
-f, --fix-broken
Fix; attempt to correct a system with broken dependencies in place. This option, when used with install/remove, can omit any packages to permit APT to deduce a likely solution. If packages are specified, these have to completely correct the problem. The option is sometimes necessary when running APT for the first time; APT itself does not allow broken package dependencies to exist on a system. It is possible that a system's dependency structure can be so corrupt as to require manual intervention (which usually means using dpkg --remove to eliminate some of the offending packages). Use of this option together with -m may produce an error in some situations. Configuration Item: APT::Get::Fix-Broken.
Also turn the short options -yq into long options --yes --quiet for more obvious debugging if something goes awry.
CmdGetAuthInfo calls run_cmd() with a list instead of a *-expanded list of arguments. Fix this to match the current run_cmd() prototype.
And think again if the current prototype conforms to the priciple of least surprise: Most exec- / run- / whatever- functions do expect ether a string to be run by the shell, or an argv list.
Prepending --login to the argument list of BackendCmd.sudo() fails if run as root, because BackendCmd.sudo() detects that and leaves the /usr/bin/sudo out from the exec call. Fix that by adding an opts: list[str] parameter to sudo, defaulting to an empty list, with options that should be passed to /usr/bin/sudo.
Define run(), which calls _run() in the abstract base class Cmd, not in lib.Cmd. Otherwise lib.Cmd is not abstract, which will predictably confuse including code outside of jw-pkg.
Major - but not yet sufficient - code beautification starting from jw.pkg.App.
- Make more methods private
- Rename methods to be more self-explanatory
- Same for method arguments, notably clean up some inconsistent
uses of "module" vs "project"
- Add more type hints
--quote puts double quotation marks around the listed dependencies, protecting version requirements (>= 1.0) and parenthesis "perl(GD)" from the shell.
A "username" in jw-pkg terms, as in $(CLONE_FROM_USER), is not sufficient to identify a remote API URL on a Forgejo server, it can denote both an organization and a user, so try organizations first, then users, and stop on the first occasion found.
Add a hand-coded __init__.py into jw.pkg.cmds.distro. Auto-generation works fine, but has to run before it can work. For a freshly downloaded toplevel Makefile / project-dirs-minimal.mk, the targets pkg-install-xxx-deps requires a working package manager without jw-pkg built.
Cmd._run(), as conceived for working with lib.App, is meant to be an async method. To be conservative about changes, jw-pkg's legacy way of handling _run() was kept when deriving from libApp, and async was not propagated down to the _run() implementations. This commit rectifies that before adding additional subcommands.
During __init__(), commands have no idea of their parent. This is not a problem as of now, but is easy to fix, and it's architecturally desirable to be prepared just in case, so add the parent argument to the ctor before more commands are added.
ResultCache is a home-grown result cache. The @lru_cache decorator, now available in Python 3, accomplishes the same thing, so try to ditch ResultCache for it.
Sadly, this doesn't entirely work as of now, because it uses hash() to hash the arguments, which won't work for the two list-type arguments to add_modules_from_project_txt() (buf and visited).
App.res_cache should be private. It's needed here to cache the results of a function which is private to CmdBuild anyway, so solve that with lru_cache, to allow App to do it's private thing with caching.
Add support for --topdir-format. The option supports several different values, affecting the console output of App wherever it knows that the output contains a reference to the projects' toplevel directory.
- "unaltered" will have it print the toplevel directory in the same
format as passed to the commandline
- "absolute" will try to resolve it to an absolute path before
printing
- make:XXX will return the make-varible $(XXX) instead
To implement this, the proj_dir() member function is turned into the private member function __proj_dir(), and a new member function find_dir() is supplied, with two additional parameters: search_subdirs and search_absdirs, which will try to find an existing directory relative to the toplevel directory of the given module, or in the search_absdirs list, respectively.
Command modules in cmds.projects have been updated to use the new function.