Add the parameter "atomic" to put() / _put(). If instructs the
implementation to take extra precautions to make sure the operation
either succeeds or fails entirely, i.e. doesn't leave a broken target
file behind.
Signed-off-by: Jan Lindemann <jan@janware.com>
.put() has some commands to _run(), and it uses its own CallContext
for them. Since that pattern only replicates what run() does anyway,
we could just as well use run() itself with less code, so do that.
Signed-off-by: Jan Lindemann <jan@janware.com>
Rename class FileTransfer to FileContext because that's the better
name. It's the base class of ExecContext and also a context.
Signed-off-by: Jan Lindemann <jan@janware.com>
ExecContext has get() / _get() and put() / _put(), which make a fine
API for a file transfer class. A class supporting file transfer
should not, however, be forced to implement _run() and _sudo(), so
place this functionality in a new class FileTransfer, and derive
ExecContext from it.
Signed-off-by: Jan Lindemann <jan@janware.com>
Add lib.base to provide basic definitions.
For now, move the definiions of Result, Input and InputMode from
ExecContext into lib.base. Having to import them from the ExecContect
module is too heavy-handed for those simple types.
Signed-off-by: Jan Lindemann <jan@janware.com>
Add ExecContext.close() as a hook to clean up async resources living
longer than an ExecContext method call.
Also, implement __aenter__() and __aexit__(), to allow using
ExecContext as context manager. close() is invoked it goes out of
scope.
Signed-off-by: Jan Lindemann <jan@janware.com>
Add wrapper methods get() and put(), plus their wrapped methods
_get() and _put(). The wrapped methods have default implementations,
using POSIX utilities on the target machine over _run().
Signed-off-by: Jan Lindemann <jan@janware.com>
ExecContext.create() relies on properly formed URLs with a schema for
deciding which backend gets created. Create a Local instance if an
URL doesn't have schema.
Signed-off-by: Jan Lindemann <jan@janware.com>
The Input instance passed as cmd_input to ExecContext.run() and
.sudo() currently may be of type str. Allow to pass bytes, too.
At the same time, disallow None to be passed as cmd_input. Force the
caller to be more explicit how it wants input to be handled, notably
with respect to interactivity.
Along the way fix a bug: Content in cmd_input should result in
CallContext.interactive == False but doesn't. Fix that.
Signed-off-by: Jan Lindemann <jan@janware.com>
- Move _sudo() above sudo()
To have a pattern in lib.ExecContext and avoid future churn: If a
public wrapper calls a protected method, define the protected
method above the respective wrapper.
- sudo(): Make cmd_input default equal to run(): InputMode.OptInteractive
- CallContext: Expose parameters throw, wd, cmd as properties for
later use
Signed-off-by: Jan Lindemann <jan@janware.com>
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>
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>
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>
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>
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>
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>
Take a positional uri argument to the constructor of ExecContext,
forcing SSHClient to follow suit. The latter was instantiated with a
hostname as only argument up to now, which still works as a special
case of an uri.
Signed-off-by: Jan Lindemann <jan@janware.com>
Add the --verbose global option, which is made available as the
App.verbose property.
Some functions still take a verbose parameter, but the type of these
parameters is converted from bool to bool|None. The idea is that, if
they are None, their verbosity falls back to the global default.
Signed-off-by: Jan Lindemann <jan@janware.com>
Remove defaults from protected callback function parameters. They
have to be decided by the base class's public API.
Signed-off-by: Jan Lindemann <jan@janware.com>
Allow to specify the ExecContext in a call to run_cmd(). This
effectively makes run_cmd() an thin wrapper around ExecContext.run(),
which is what's going to be used in the future. The wrapper is for
backwards-compatibility.
Signed-off-by: Jan Lindemann <jan@janware.com>
The code below lib.distro, as left behind by the previous commit, is
geared towards being directly used as a command-line API. This commit
introduces the abstract base class Distro, a proxy for
distribution-specific interactions. The proxy abstracts distro
specifics into an API with proper method prototypes, not
argparse.Namespace contents, and can thus be more easily driven by
arbitrary code.
The Distro class is initialized with a member variable of type
ExecContext, another new class introduced by this commit. It is
designed to abstract the communication channel to the distribution
instance. Currently only one specialization exists, Local, which
interacts with the distribution and root file system it is running
in, but is planned to be subclassed to support interaction via SSH,
serial, chroot, or chains thereof.
Signed-off-by: Jan Lindemann <jan@janware.com>