Skip to content

Commit

Permalink
propagate errors (#15)
Browse files Browse the repository at this point in the history
This PR fixes errror propagation. At the moment commands like `uenv run store.squashfs -- my_cmd` will always look successful, independent of the status of `my_cmd`.

With this PR it will be possible to propaget the error, and chain commands in the shell with `&&` or `||`.

There is a tight integration of `uenv-impl` and the `uenv` function, because `uenv-impl` sets variables that will be returned from the `uenv` function.
This is not great, but I could not figure out a way how else I could make it happen.

Here are two examples that would work with the suggested changes:
```bash
if uenv run store.squashfs -- false ; then
  echo "Success status"
else
  echo "Failure status"
```

and also
```bash
if uenv start store.squashfs ; then
  echo "Success status"
else
  echo "Failure status"
fi
```

The latter will have the exit status of the last run command, which is the default behaviour for subshells, where the last command's exit status defines the subshell's exit status.
  • Loading branch information
finkandreas authored Feb 13, 2024
1 parent eeb16f9 commit 9dc2934
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 12 deletions.
3 changes: 3 additions & 0 deletions activate
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export UENV_CMD=@@impl@@
export UENV_VERSION=@@version@@

function uenv {
local _last_exitcode=$?

function uenv_usage {
echo "uenv - for using user environments [version @@version@@]"
echo ""
Expand All @@ -31,6 +33,7 @@ function uenv {
fi

unset -f uenv_usage
return $_exitcode
}

export -f uenv
28 changes: 16 additions & 12 deletions uenv-impl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import subprocess
VERSION="@@version@@"

shell_noop=" :"
shell_error="local _exitcode=1"

def make_argparser():
parser = argparse.ArgumentParser()
Expand Down Expand Up @@ -384,7 +385,7 @@ def generate_command(args):
env = environment()
if env.old_api:
print_error(f"the version of squashfs-mount on this system is too old.")
return shell_noop
return shell_error

if args.command == "run":
return generate_run_command(args, env)
Expand All @@ -400,7 +401,7 @@ def generate_command(args):
return generate_modules_command(args, env)

print_error(f"unknown command '{args.command}'")
return shell_noop
return shell_error

"""
uenv start gromacs.squashfs ddt.squashfs
Expand Down Expand Up @@ -538,7 +539,7 @@ def generate_run_command(args, env):
print_debug(f"parsing run command with arguments: {args.command}")
if env.active:
print_error("a uenv is already running")
return shell_noop
return shell_error

images, cmd, cmdargs = split_runline(args.runline)

Expand All @@ -548,7 +549,7 @@ def generate_run_command(args, env):

mount_pairs=parse_image_descriptions(images)
if mount_pairs==[]:
return shell_noop
return shell_error

mount_string = ' '.join(mount_pairs)
cmdargs_string = ' '.join([f'"{arg}"' for arg in cmdargs])
Expand All @@ -558,18 +559,19 @@ def generate_run_command(args, env):
return [f"export UENV_MOUNT_FILE={main_mount[0]}",
f"export UENV_MOUNT_POINT={main_mount[1]}",
f"squashfs-mount {mount_string} -- {cmd} {cmdargs_string}",
'local _exitcode=$?',
"unset UENV_MOUNT_FILE; unset UENV_MOUNT_POINT;"]


def generate_start_command(args, env):
print_debug(f"parsing start command with arguments: {args.image}")
if env.active:
print_error("a uenv is already running")
return shell_noop
return shell_error

mount_pairs=parse_image_descriptions(args.image)
if mount_pairs==[]:
return shell_noop
return shell_error

mount_string = ' '.join(mount_pairs)

Expand All @@ -578,6 +580,7 @@ def generate_start_command(args, env):
return [f"export UENV_MOUNT_FILE={main_mount[0]}",
f"export UENV_MOUNT_POINT={main_mount[1]}",
f"squashfs-mount {mount_string} -- bash",
"local _exitcode=$?",
"unset UENV_MOUNT_FILE; unset UENV_MOUNT_POINT;"]

def generate_modules_command(args, env):
Expand All @@ -586,7 +589,7 @@ def generate_modules_command(args, env):

if not env.active:
print_error(f'there is no environment loaded')
return shell_noop
return shell_error

# generate a list of all the mounted environments that provide modules
module_envs = [
Expand Down Expand Up @@ -631,7 +634,7 @@ def generate_modules_command(args, env):
and (e.is_native_mounted)]
if len(matches)==0:
print_error(f"no uenv matching {i} provides modules")
return shell_noop
return shell_error
print_debug(f" uenv {i} mounted at {matches[0]}")
mounts.append(matches[0])

Expand All @@ -649,11 +652,11 @@ def generate_view_command(args, env):

if not env.active:
print_error(f'there is no environment loaded')
return shell_noop
return shell_error

if env.loaded_view is not None:
print_error(f'a view is already loaded: {env.loaded_view}')
return shell_noop
return shell_error

uenv = env.uenvs[0]
name = args.view_name
Expand All @@ -668,6 +671,7 @@ def generate_view_command(args, env):
f"export UENV_VIEW={uenv.mount}:{name}",]
else:
print_error(f'the view "{name}" is not one of the available views: {available_views}')
return shell_error

return shell_noop

Expand Down Expand Up @@ -734,9 +738,9 @@ def generate_stop_command(args, env):

if not env.active:
print_error(f"there is no running environment to stop")
return shell_noop
return shell_error

return "exit 0"
return "exit $_last_exitcode"


if __name__ == "__main__":
Expand Down

0 comments on commit 9dc2934

Please sign in to comment.