If Python's autocomplete is not installed, jw-pkg.py fails to run
commands. Fix that in order stay compatible with minimal excecution
environments.
Signed-off-by: Jan Lindemann <jan@janware.com>
.cache-projects.mk is not installed / packaged, which makes builds
against an installed jw-pkg considerably slower. Change that, at the
risk of making the installed jw-pkg-devel less versatile. This commit
installs a cache file cache-projects.mk, renamed from
.cache-projects.mk, because there's no justification for hiding an
installed makefile. At least I can't think of one.
Signed-off-by: Jan Lindemann <jan@janware.com>
Before merging the remote branch, do a rebase. This may fail and
prompt conflict resolution, but that seems the canonical outcome for
the common use case "interactive make git pull-xxx" with master
out-of-sync.
Signed-off-by: Jan Lindemann <jan@janware.com>
There's pkg-manager-refresh already, so by adding pkg-manager-dup the
distribution can be upgraded by distribution agnostic targets only
through the Makefile. This might come in handy for CI, so add it.
Signed-off-by: Jan Lindemann <jan@janware.com>
Better safe than sorry: If things are to happen unattendedly, enforce
the need to explicitly request that.
Signed-off-by: Jan Lindemann <jan@janware.com>
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
Fix API breakage in the command modules.
Signed-off-by: Jan Lindemann <jan@janware.com>
--quote puts double quotation marks around the listed dependencies,
protecting version requirements (>= 1.0) and parenthesis "perl(GD)"
from the shell.
Signed-off-by: Jan Lindemann <jan@janware.com>
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.
Signed-off-by: Jan Lindemann <jan@janware.com>
Retire pkg-manager.sh and replace it by the cleaner "jw-pkg.sh
distro" command, essentially providing the same functionality and
nearly the same command-line interface.
Not-so-fun-fact:
jw-pkg > git diff --stat jw-devops/master
...
71 files changed, 732 insertions(+), 340 deletions(-)
400 LOC more. That's what the move from a shell script to the more
maintainable Python versions costs. Still a good idea, and the
enhanced extensibility might pay off in terms of LOC with other shell
scripts in the future.
Signed-off-by: Jan Lindemann <jan@janware.com>
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.
Signed-off-by: Jan Lindemann <jan@janware.com>
run_cmd() is synchronous. Now that all commands are asynchronous, we
can await it, so rewrite it to be asynchronous, too.
Other changes:
- Make it return stderr as well in case its needed
- Drop into a pseuto-tty if
- cmd_input == "mode:interactive" or
- cmd_input == "mode:auto" and stdin is a TTY
- Add argument env, defaulting to None. If it's a dict, it will be
the environment the command is run in
This entails making all functions using run_cmd() async, too,
including run_curl(), get_username() and get_password().
Signed-off-by: Jan Lindemann <jan@janware.com>
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.
Signed-off-by: Jan Lindemann <jan@janware.com>
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.
Signed-off-by: Jan Lindemann <jan@janware.com>
jw-projects.py is now a multi-call executable, with "projects" being
just one of its subcommands. Rename it to jw-pkg.py to reflect that.
Signed-off-by: Jan Lindemann <jan@janware.com>
As per info make, it turns out that ifndef SOME_VAR is true for
SOME_VAR defined to an empty value. This is unusable for caching, so
replace it with ifeq ($(origin SOME_VAR),undefined).
Signed-off-by: Jan Lindemann <jan@janware.com>
Add the Enum "Scope" to denote the scope argument of
jw.pkg.App.get_modules_from_project_txt(), because it explains itself
better than an integer.
Signed-off-by: Jan Lindemann <jan@janware.com>
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).
Signed-off-by: Jan Lindemann <jan@janware.com>
With the exception of top_name, which cmds.project.GetVal needs
read-access to, all member variables of jw.pkg.App can be made
private.
Signed-off-by: Jan Lindemann <jan@janware.com>
In the os_cascade() function, don't roll own logic, call the richer
jw-projects.py projects os-cascade instead.
Signed-off-by: Jan Lindemann <jan@janware.com>
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.
Signed-off-by: Jan Lindemann <jan@janware.com>
Replace the jw.pkg.App.debug(), .warn() and .err() methods by the
global log() function. There's no obvious benefit in having App know
what's logged.
Signed-off-by: Jan Lindemann <jan@janware.com>
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.
Signed-off-by: Jan Lindemann <jan@janware.com>
Reorganize the Python module structure. Placing the command classes
under jw.cmds.projects instead of jw.build.cmds will allow to add a
nested command structure, with the current commands, being mostly
related to building software, found below a "projects" toplevel
command.
Other conceivable commands could be "package" for packaging, or
"distro" for commands wrapping the distribution's package manager.
Signed-off-by: Jan Lindemann <jan@janware.com>
Make App.proj_dir() return an absolute path. This looks like a good
idea, because some of the $(call proj_query xxx) paths end up being
relative, because they get proj_dir()'s idea of a directory
prepended. This prohibits caching them in $(TOPDIR)/make/.cache.mk
for make benefit glorious nation of performance.
Signed-off-by: Jan Lindemann <jan@janware.com>
Remove the --debug option, which is superseded by the semantically
richer --log-level debug in the base class.
Signed-off-by: Jan Lindemann <jan@janware.com>
Derive jw.pkg.App from jw.pkg.lib.App. App.run() dissolves as follows:
- Its sub-command invocation logic is left to the base class
- parser.add_arguments() are moved into self._add_arguments()
- So is handling of early-parsed arguments
- async def _run() is reimplemented to set some member variables
Signed-off-by: Jan Lindemann <jan@janware.com>
Add App and Cmd as generic base classes for multi-command
applications. The code is taken from jw-python: The exising
jw.pkg.App is very similar to the more capable jwutils.Cmds class,
so, to avoid code duplication, add it here to allow for jwutils.Cmds
and jw.pkg.App to derive from it at some point in the future.
Both had to be slightly modified to work within jw-pkg's less
equipped context, and will need futher code cleanup.
Signed-off-by: Jan Lindemann <jan@janware.com>
Types is a container for types, notably classes, which are
dynamically loaded from other modules. Which modules are loaded is
based on the following criteria passed to its constructor:
- mod_names: A list of modules to load and investigate
- type_name_filter: A regular filter expression or None (default).
If it's None, all types pass this filter.
- type_filter: A list of types the returned types must match.
Defaults to [], in which case all types pass this filter
Signed-off-by: Jan Lindemann <jan@janware.com>
A dedicated logging module is currently provided by jw-python, but
since it's often needed also in jw-pkg, and it's relatively small and
maintainable, it seems justified to move it into jw-pkg.
Signed-off-by: Jan Lindemann <jan@janware.com>
CmdGetval.add_arguments() uses self.app.top_name, which may or may
not be initialized at the time this runs. Not using it makes
CmdGetval's ctor safe to run in the context of App.__init__().
Signed-off-by: Jan Lindemann <jan@janware.com>