From 6c41ded544558d01e87d20000360c682a88303b1 Mon Sep 17 00:00:00 2001 From: Urban Müller Date: Thu, 3 Aug 2023 17:55:27 +0200 Subject: allow echoing and dry-running of it::exec/it::system commands --- it.class | 28 ++++++++++++++++------------ test/exec.t | 16 +++++++++------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/it.class b/it.class index a788de3..858bbe4 100644 --- a/it.class +++ b/it.class @@ -354,7 +354,7 @@ static function error($p = array(), $extra = null) */ static function fatal($p) { - it::error(['fatal' => true, 'backtraceskip' => 2] + (array)$p); + it::error(['fatal' => true, 'backtraceskip' => 1] + (array)$p); } @@ -672,19 +672,23 @@ static function filter_keys($array, $keys, $p = array()) /** * Construct shell command using it::shell_command, log it, execute it and return output as string. - * {keyword} quotes and inserts value from assoc array like ET() - * {0} .. {n} quotes and inserts positional arguments - * {-opts} array of opts => {value,true,false,null}: it::exec('ls {-opts}', ['-opts' => ["-l" => true]]); + * @param $cmd shell command to be executed. String may contain: + * {keyword} quotes and inserts value from assoc array like ET() + * {0} .. {n} quotes and inserts positional arguments + * {-opts} array of opts => {value,true,false,null}: it::exec('ls {-opts}', ['-opts' => ["-l" => true]]); * @param $cmd Format string with {keywords} a la ET() * @param $args varargs, contains key => val arrays or positionals for filling in cmd line. val=null expands to nothing + * 'callback' optional closure, $fn($cmd) => print($cmd) for echo, => !print($cmd) for echo and suppress * @return output of command. shell errors not detectable, consider it::system or see /www/server/log/error_log */ static function exec($cmd, ...$args) { - $cmd = it::shell_command($cmd, ...$args); # NOPHPLINT - + $args = array_reduce($args, fn($carry, $v) => array_merge($carry, (array)$v), []); # varargs to single array + $cmd = it::shell_command($cmd, $args); # NOPHPLINT $before = gettimeofday(true); - $result = EDC('noexec') ? "" : (string)shell_exec("set +o posix\n" . $cmd); + + if ((!($args['callback'] instanceof Closure) || $args['callback']($cmd)) && !EDC('noexec')) + $result = (string)shell_exec("set +o posix\n" . $cmd); @it::log('exec', round((gettimeofday(true) - $before)*1000) . "\t$cmd"); @@ -699,13 +703,13 @@ static function exec($cmd, ...$args) */ static function system($cmd, ...$args) { - $cmd = it::shell_command($cmd, ...$args); # NOPHPLINT - + $args = array_reduce($args, fn($carry, $v) => array_merge($carry, (array)$v), []); # varargs to single array + $cmd = it::shell_command($cmd, $args); # NOPHPLINT $before = gettimeofday(true); - if (!EDC('noexec')) + $result = 0; + + if ((!($args['callback'] instanceof Closure) || $args['callback']($cmd)) && !EDC('noexec')) system("set +o posix\n" . $cmd, $result); - else - $result = 0; @it::log('exec', round((gettimeofday(true) - $before)*1000) . "\t$cmd"); diff --git a/test/exec.t b/test/exec.t index 5f3ebb5..9e55726 100755 --- a/test/exec.t +++ b/test/exec.t @@ -4,14 +4,16 @@ # Tests for getopt in it.class is(it::exec("echo gna"), "gna\n", "basic exec"); -is(it::exec("echo {arg}", ['arg' => 'gna']), "gna\n", "exec with argument"); +is(it::exec("echo {arg}", ['arg' => 'gnu'], ['arg' => "gna"]), "gna\n", "exec with argument"); is(it::exec("echo {0}", 'gna'), "gna\n", "exec with positional argument"); -is(it::shell_command("echo {arg}", ['arg' => 'gna07,-:blah']), "echo gna07,-:blah", "don't quote arguments with only whitelistes characters"); -is(it::shell_command("echo {arg}", ['arg' => '2>&1']), "echo '2>&1'", "quote arguments with dangerous characters"); -is(it::shell_command("echo {arg}", ['arg' => '']), "echo ''", "quote empty arguments"); -is(it::shell_command("echo {arg}", ['arg' => null]), "echo ", "remove null values"); -is(it::shell_command("echo {arg}", ['arg' => false]), "echo ", "remove false values"); -is(it::shell_command("echo {arg}", ['arg' => []]), "echo ", "remove empty arrays"); +is(it::shell_command("echo {arg}", ['arg' => 'gna07,-:blah']), "echo gna07,-:blah", "don't quote arguments with only whitelistes characters"); +is(it::shell_command("echo {arg}", ['arg' => '2>&1']), "echo '2>&1'", "quote arguments with dangerous characters"); +is(it::shell_command("echo {arg}", ['arg' => '']), "echo ''", "quote empty arguments"); +is(it::shell_command("echo {arg}", ['arg' => null]), "echo ", "remove null values"); +is(it::shell_command("echo {arg}", ['arg' => false]), "echo ", "remove false values"); +is(it::shell_command("echo {arg}", ['arg' => []]), "echo ", "remove empty arrays"); +is(it::shell_command("echo {arg}", (object)['arg' => "foo"]) , "echo foo", "allow objects"); +is(it::shell_command("echo {arg}", ['arg' => 1], ['arg' => 2]), "echo 2", "support varargs"); is( -- cgit v1.2.3