From de08c14aa1c79c7ba471d8a7ce139b4922e7bc34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Mon, 28 Mar 2016 21:47:16 +0200 Subject: [PATCH] [enh] Allow to set script execution directory in hook_exec --- data/actionsmap/yunohost.yml | 3 +++ src/yunohost/hook.py | 28 +++++++++++++++++----------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index fd206603d..f749c2eb4 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -1395,3 +1395,6 @@ hook: full: --no-trace help: Do not print each command that will be executed action: store_true + -d: + full: --chdir + help: The directory from where the script will be executed diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index a095efb6f..e6e2e797e 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -275,7 +275,8 @@ def hook_callback(action, hooks=[], args=None): return result -def hook_exec(path, args=None, raise_on_error=False, no_trace=False): +def hook_exec(path, args=None, raise_on_error=False, no_trace=False, + chdir=None): """ Execute hook from a file with arguments @@ -284,6 +285,7 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False): args -- A list of arguments to pass to the script raise_on_error -- Raise if the script returns a non-zero exit code no_trace -- Do not print each command that will be executed + chdir -- The directory from where the script will be executed """ from moulinette.utils.process import call_async_output @@ -296,36 +298,40 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False): raise MoulinetteError(errno.EIO, m18n.g('file_not_exist')) # Construct command variables - cmd_fdir, cmd_fname = os.path.split(path) - cmd_fname = './{0}'.format(cmd_fname) - cmd_args = '' if args and isinstance(args, list): # Concatenate arguments and escape them with double quotes to prevent # bash related issue if an argument is empty and is not the last cmd_args = '"{:s}"'.format('" "'.join(str(s) for s in args)) + if not chdir: + # use the script directory as current one + chdir, cmd_script = os.path.split(path) + cmd_script = './{0}'.format(cmd_script) + else: + cmd_script = path # Construct command to execute - command = ['sudo', '-u', 'admin', '-H', 'sh', '-c'] + command = ['sudo', '-n', '-u', 'admin', '-H', 'sh', '-c'] if no_trace: - cmd = 'cd "{0:s}" && /bin/bash "{1:s}" {2:s}' + cmd = '/bin/bash "{script}" {args}' else: # use xtrace on fd 7 which is redirected to stdout - cmd = 'cd "{0:s}" && BASH_XTRACEFD=7 /bin/bash -x "{1:s}" {2:s} 7>&1' - command.append(cmd.format(cmd_fdir, cmd_fname, cmd_args)) + cmd = 'BASH_XTRACEFD=7 /bin/bash -x "{script}" {args} 7>&1' + command.append(cmd.format(script=cmd_script, args=cmd_args)) if logger.isEnabledFor(log.DEBUG): logger.info(m18n.n('executing_command', command=' '.join(command))) else: - logger.info(m18n.n('executing_script', script='{0}/{1}'.format( - cmd_fdir, cmd_fname))) + logger.info(m18n.n('executing_script', script=path)) # Define output callbacks and call command callbacks = ( lambda l: logger.info(l.rstrip()), lambda l: logger.warning(l.rstrip()), ) - returncode = call_async_output(command, callbacks, shell=False) + returncode = call_async_output( + command, callbacks, shell=False, cwd=chdir + ) # Check and return process' return code if returncode is None: