Commit graph

4,654 commits

Author SHA1 Message Date
3e36e5f8ff Release 1.0.0-196@suse-tumbleweed/x86_64
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-30 06:16:28 +00:00
cf71367aa5 Release 1.0.0-196@kali-rolling/amd64
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-30 06:15:26 +00:00
706b74a20b Start version: 1.0.0-196
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-30 06:14:36 +00:00
e589cdbdbf cmds and lib: Don't print() log messages

print() should be used to output information requested by a certain command, but not for logging the process to achieve it. log() should be used for the latter. The current code has the distinction not down clearly, fix that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-30 08:11:39 +02:00
6ba76ea44b Release 1.0.0-195@suse-tumbleweed/x86_64
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-29 15:59:07 +00:00
e3773cc180 Release 1.0.0-195@kali-rolling/amd64
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-29 15:46:48 +00:00
c402f70415 Start version: 1.0.0-195
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-29 15:45:54 +00:00
7cfe2c4775 lib.App._run(): default_completer=NoopCompleter()

By default, argcomplete uses argcomplete.FilesCompleter as default for every argument. This mixes accessible files into the list of possible completions. For most of jw-pkg's commands, that's unwanted, so turn it off by defining a NoopCompleter class which does nothing, and by set every arguments's default completer to a NoopCompleter instance. If desired, completing files can be restored for an argument by

parser.add_argument("some-arg").completer = FilesCompleter()

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-28 12:45:50 +01:00
ce1b8b6744 lib.App: Fully parse argparse tree if _ARGCOMPLETE

Every module derived from lib.Cmd implements its own parser.add_argument() logic. As a consequence, all Cmd derived modules need to be loaded to have the full argument tree available. This is avoided during normal program startup because it takes some time. It's not necessary during normal program execution, nor for showing help messages. It is, however, needed for argcomplete to do its thing, so fully parse the command line if the program runs in argcomplete mode, as determined by checking if _ARGCOMPLETE is present in the environment.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-27 09:16:14 +01:00
9b208ecc1e lib.ExecContext.log_delim(): No interactive footer

lib.ExecContext.log_delim() logs a header not designed for enclosing command output, and, hence, no footer should be output. This commit suppresses it.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-27 09:16:14 +01:00
9b6ec109a1 cmds and lib: Don't print() log messages

print() should be used to output information requested by a certain command, but not for logging the process to achieve it. log() should be used for the latter. The current code has the distinction not down clearly, fix that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-27 09:16:14 +01:00
27bf98f747 pgit.sh: Beautify logging

Log to stderr and add some ASCII-art around the output. Also, add a --porcelain option to allow more stable output parsing. Subsequently, use that option in make targets parsing the output, notably make diff and make git-show-xxx.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-27 09:16:14 +01:00
0ca51e16ee Release 1.0.0-194@suse-tumbleweed/x86_64 2026-03-25 10:03:15 +00:00
d3344fedc0 Release 1.0.0-194@kali-rolling/amd64
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-25 09:51:15 +00:00
b62366d0df Start version: 1.0.0-194
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-25 09:50:30 +00:00
e461b2815d cmds.projects.BaseCmdPkgRelations: Fix Debian simple deps

Simple dependencies (i.e. non-triplet dependencies, e.g gcc > 15.0) raise an exception on Debian, fix that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 09:50:28 +00:00
0a19f3173a Release 1.0.0-193@kali-rolling/amd64
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-25 07:38:43 +00:00
47a8230701 Start version: 1.0.0-193
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-25 07:37:58 +00:00
6d876e88f6 lib.util.run_sudo(): Pass argument list on unchanged

run_sudo() is a thin wrapper around ExecContext.sudo(), so don't try to make sense more arguments than necessary.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:37:56 +00:00
6d9adfb5ff Release 1.0.0-192@kali-rolling/amd64
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-25 06:55:45 +00:00
97d6421f27 Start version: 1.0.0-192
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-25 06:54:57 +00:00
b21d2d1c21 lib.ec.ssh.AsyncSSH: Add interactivity

Request a remote PTY from AsyncSSH, and wire the local terminal's stdin up with it if interactive == True. This gives a real interactive session if local stdin belongs to a terminal. Also, thanks to AsyncSSH understanding that, forward terminal size changes to the remote end.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:46 +01:00
737cbc3e24 lib.ec.ssh.AsyncSSH: Add class

Add a SSHClient implementation using AsyncSSH. This is the first and currently only class derived from SSHClient which implements SSHClient.Cap.LogOutput, designed to consume and log command output as it streams in. It felt like the lower hanging fruit not to do that with Paramiko: Paramiko doesn't provide a native async API, so it would need to spawn additional worker threads. I think.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:46 +01:00
279b7789e2 lib.ec.SSHClient: Add property port

Add a port property to SSHClient, parsed from the ctor's URL, to supply the obvious information.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:46 +01:00
3a84408436 lib.ec.SSHClient.__init__(): Add parameter caps

Add an optional caps ("capabilities") argument to the constructor of SSHClient. It is meant to be used by derived classes in order to declare that they don't want the base class to handle a default behaviour for a certain capability, but that they want to implement it themselves instead.

Also, give the _run_ssh() callbacks the necessary info as parameters, so that the derived classes have the means to do so.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:46 +01:00
4393ca21fc App.os_cascade: Don't use platform.system()

Python's platform.system() outputs 'Linux', and to use it is tempting. Sadly, that's wrong, because it reflects the host's idea of the target system, not the execution context's, so replace it with straight 'linux' if the distro is known, or, failing that, the output of uname -s.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:46 +01:00
b2e1e411f1 lib.pm.*.query_packages(): Make it non-interactive

lib.pm.query_packages() uses a TTY for doing its thing and outputs half-digested stuff to the terminal, fix that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:46 +01:00
8280327602 App.os_release: cat os-release non-interactively

Even with --interactive=[true|auto], there's no point in trying to read /etc/os-release interactively, so don't do that. Most notably, this commit keeps the property method from spilling /etc/os-release's content over the terminal.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:46 +01:00
0b05eb4c37 ExecContext: Make mode:xxx an enum

This commit introduces two new types, Input and InputMode. They replace the more error-prone special strings cmd_input could be used with. InputMode is an Enum, and Input can be either IntputMode, a string or None.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:45 +01:00
bb13aea694 lib.ExecContext: Fix ignored --interactive

Whether or not the CallContext.interactive property should be True or False, and hence, a call should be processed interactively, depends on multiple factors, constituting matrix of options with multiple preferences.

--interactive is the application default and can be true, false, or auto
- A call can be explicitly invoked as interactive, non-interactive or auto via the cmd_input parameter to ExecContext.run()

This commit adds more "mode:" options to make the latter more explicit. It takes preference over the global --interactive parameter: Global --interactive is only given a chance to decide if cmd_input is None (default) or mode:opt-interactive.

This commit also fixes a bug: --interactive is ignored because the interactive argument passed to ExecContext's constructor is ignored later on in calls to the wrapped _run() and _sudo() methods.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:45 +01:00
3bda9bc826 lib.ExecContext.sudo(): Default None mod_env to {}

mod_env can be None. Make it an empty dict in that case to take a little burden off the implementations in the derived classes.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:45 +01:00
21e67291b5 Fix: Decode run_cmd() result

Since commit 02697af5, ExecContext.run() returns bytes for stdout and stderr and fixes that in calling code. The thing it did not fix was the code calling run_cmd(), which also made return bytes. This commit catches up on that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-25 07:32:45 +01:00
fd35fa0871 lib.Distro: Add missing async

Distro's sudo() and run() wrappers are not flagged async. It still works, because throughout jw-pkg all callers expect a coroutine return value, but flagging them as async makes the return value obvious.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-23 11:33:35 +01:00
990858e0f9 Release 1.0.0-191@kali-rolling/amd64
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-20 15:07:09 +00:00
e77c08e3d4 Release 1.0.0-191@suse-tumbleweed/x86_64
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-20 13:04:12 +00:00
946b8daa3b Start version: 1.0.0-191
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-20 13:03:07 +00:00
19e6e01c11 Release 1.0.0-190@kali-rolling/amd64
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-20 12:51:02 +00:00
f4c76ebab9 lib.ec.SSHClientInternal|SSHClientCmd: Own .py

Move the code of SSHClientInternal and SSCClientCmd into lib.ec.ssh, as "Paramiko" and "Exec", respectively. This makes the class layout a little more modular, and along the way fixes a bug where SSHClientInternal could be instantiated but was unusable (if the Paramiko is not installed).

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 13:35:50 +01:00
f37f025b17 lib.SSHClient: Move to lib.ec

SSHClient in an ExecContext, hence it's better off in lib.ec, move it there and adapt the references.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 13:35:11 +01:00
54a6053cc2 Release 1.0.0-190@suse-tumbleweed/x86_64
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-20 09:45:39 +00:00
cbe5da4c7a Start version: 1.0.0-190
Signed-off-by: janware DevOps <devops@janware.com>
2026-03-20 09:44:55 +00:00
5078c27682 cmds.projects.CmdListRepos.run(): Fix trailing newline

projects list-repos prints a traling newline, remove that.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 10:30:25 +01:00
02697af568 lib.ExecContext: Align .sudo() prototype to .run()

ExecContext's .sudo() omits many of run()'s parameters, and this commit adds them. To avoid redundancy around repeating and massaging the long parameter list of both functions and their return values, it also adds some deeper changes:

- Make run(), _run(), sudo() and _sudo() always return instances of Result. Before it was allowed to return a triplet of stdout, stderr, and exit status.
- Have ExecContext stay out of the business of decoding the result entirely. Result provides a convenience method .decode() operating on stdout and stderr and leaves the decision to the caller.
This entails miniscule adaptations in calling code, namely in App.os_release, util.get_profile_env() and CmdListRepos._run().
- Wrap the _run() and _sudo() callbacks in a context manager object of type CallContext to avoid code duplication.
- Consistently name the first argument to run(), _run(), sudo() and _sudo() "cmd", not "args". The latter suggests that the caller is omitting the executable, which is not the case.
Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 10:30:25 +01:00
37af0a05e9 lib.SSHClient: Implement verbose logging
Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 10:30:25 +01:00
e924f34441 pkg.App.os_release: Call cat /etc/os-release

Don't open and parse /etc/os-release with Python built-in functions. Spawn "cat /etc/os-release" as a subprocess and capture the output for parsing instead. The obvious advantage is that this also works with a remote shell.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 10:30:25 +01:00
df40af9fc3 lib.App.call_async(): Add method

Use the AsyncRunner class introduced in the previous commit to add a call_async() method, allowing to run async functions from sync functions by spawning an extra event loop.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 10:30:25 +01:00
67e51cf07c lib.AsyncRunner: Add class

Add class AsyncRunner. This is a wrapper around the ceremony needed to spawn an extra event loop in a synchronous function which wants to call an async function.

Guido van Rossum considers it bad design that such a function exists in the first place. While that may be true in the long run also for jw-pkg, at this point I'm unwilling to flag every lazyly initialized App property as async. It's not clear, yet, which will be async and which not, and I dread the churn. So I will accept this as a minimally invasive helper for now. When the API has stabilized, a design without it may be better.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 10:30:25 +01:00
95a384bfff lib.App.eloop: Add property

Expose App's __eloop member containing the application's main event loop to allow outside async event loop trickery.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 10:30:25 +01:00
52dd3b8f21 lib.ExecContext.run(): Push code up into base class

Take implementation burden from the derived classes _run() callback by moving the respective code into the run() wrapper methods of the base class.

Signed-off-by: Jan Lindemann <jan@janware.com>
2026-03-20 10:30:25 +01:00
f2ffe85b61 lib.SSHClientInternal: No key_filename in connect()

Remove the key_filename parameter from the call to Paramiko's connect(). It's user-dependent, and the current DevOps implementation relies on having a SSH_AUTH_SOCK in the environment, anyway.

Signed-off-by: janware DevOps <devops@janware.com>
2026-03-20 10:30:25 +01:00