-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12 from henriquemoody/command
Create Command action
- Loading branch information
Showing
5 changed files
with
356 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
|
||
declare(ticks=1); | ||
|
||
require_once __DIR__ . '/../vendor/autoload.php'; | ||
|
||
use Arara\Process\Action\Command; | ||
use Arara\Process\Child; | ||
use Arara\Process\Context; | ||
use Arara\Process\Control; | ||
|
||
try { | ||
$command = new Command('find', array(__DIR__, '-name' => '*', '-type' => 'f')); | ||
$command->bind(Command::EVENT_FINISH, function (Control $control, Context $context) { | ||
$flags = JSON_UNESCAPED_SLASHES; | ||
if (defined('JSON_PRETTY_PRINT')) { | ||
$flags = ($flags | JSON_PRETTY_PRINT); | ||
} | ||
|
||
echo json_encode($context->toArray(), $flags) . PHP_EOL; | ||
}); | ||
|
||
$child = new Child($command, new Control()); | ||
$child->start(); | ||
$child->wait(); | ||
|
||
} catch (Exception $e) { | ||
echo $e->getMessage() . PHP_EOL; | ||
echo $e->getTraceAsString() . PHP_EOL; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<?php | ||
|
||
namespace Arara\Process\Action; | ||
|
||
use Arara\Process\Context; | ||
use Arara\Process\Control; | ||
use RuntimeException; | ||
|
||
/** | ||
* Handle shell commands. | ||
*/ | ||
class Command extends Callback | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
protected $command; | ||
|
||
/** | ||
* @var array | ||
*/ | ||
protected $arguments = array(); | ||
|
||
/** | ||
* @param string $command | ||
* @param array[optional] $arguments | ||
* @param boolean $prefix | ||
*/ | ||
public function __construct($command, array $arguments = array(), $prefix = true) | ||
{ | ||
$this->command = $prefix ? '/usr/bin/env ' . $command : $command; | ||
$this->arguments = $arguments; | ||
} | ||
|
||
/** | ||
* Gets the value of command. | ||
* | ||
* @return string | ||
*/ | ||
public function getCommand() | ||
{ | ||
return $this->command; | ||
} | ||
|
||
/** | ||
* Gets the value of arguments. | ||
* | ||
* @return array | ||
*/ | ||
public function getArguments() | ||
{ | ||
return $this->arguments; | ||
} | ||
|
||
/** | ||
* Assemble command and arguments. | ||
* | ||
* @return string | ||
*/ | ||
protected function assemble() | ||
{ | ||
$assembled = $this->command; | ||
foreach ($this->arguments as $key => $value) { | ||
if (is_int($key) | ||
&& false === strpos((string) $key, '-')) { | ||
$assembled .= ' ' . escapeshellarg($value); | ||
continue; | ||
} | ||
$assembled .= ' ' . escapeshellarg($key); | ||
$assembled .= ' ' . escapeshellarg($value); | ||
} | ||
|
||
return $assembled; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function execute(Control $control, Context $context) | ||
{ | ||
$context->command = $this->assemble(); | ||
$context->outputTail = exec(sprintf('(%s)2>&1', $context->command), $outputLines, $returnValue); | ||
$context->outputString = implode(PHP_EOL, $outputLines); | ||
$context->outputLines = $outputLines; | ||
$context->returnValue = $returnValue; | ||
|
||
if ($returnValue > 0) { | ||
throw new \RuntimeException($context->outputTail); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
<?php | ||
|
||
namespace Arara\Process\Action; | ||
|
||
function exec($command, &$output = null, &$return_var = null) | ||
{ | ||
$args = func_get_args(); | ||
$return = null; | ||
|
||
$GLOBALS['arara']['exec']['args'] = $args; | ||
|
||
if (array_key_exists('output', $GLOBALS['arara']['exec'])) { | ||
$output = $GLOBALS['arara']['exec']['output']; | ||
$return = end($output); | ||
} else { | ||
\exec($command, $output, $return_var); | ||
} | ||
|
||
if (isset($GLOBALS['arara']['exec']['return_var'])) { | ||
$return_var = $GLOBALS['arara']['exec']['return_var']; | ||
} | ||
|
||
return $return; | ||
} | ||
|
||
use Arara\Process\Context; | ||
use Arara\Process\Control; | ||
|
||
/** | ||
* @covers Arara\Process\Action\Command | ||
*/ | ||
class CommandTest extends \TestCase | ||
{ | ||
protected function init() | ||
{ | ||
$GLOBALS['arara']['exec']['return'] = null; | ||
$GLOBALS['arara']['exec']['output'] = array(''); | ||
$GLOBALS['arara']['exec']['return_var'] = 0; | ||
} | ||
|
||
protected function finish() | ||
{ | ||
unset($GLOBALS['arara']['exec']); | ||
} | ||
|
||
public function testShouldAcceptCommandAndPrefixItOnConstructor() | ||
{ | ||
$action = new Command('whoami'); | ||
|
||
$actualCommand = $action->getCommand(); | ||
$expectedCommand = '/usr/bin/env whoami'; | ||
|
||
$this->assertEquals($expectedCommand, $actualCommand); | ||
} | ||
|
||
public function testShouldAcceptArgumentsOnConstructor() | ||
{ | ||
$arguments = array(__DIR__, '-name' => '*'); | ||
$action = new Command('find', $arguments); | ||
|
||
$this->assertEquals($arguments, $action->getArguments()); | ||
} | ||
|
||
public function testShouldRemoveCommandPrefixOnConstructor() | ||
{ | ||
$action = new Command('echo', array(), false); | ||
|
||
$actualCommand = $action->getCommand(); | ||
$expectedCommand = 'echo'; | ||
|
||
$this->assertEquals($expectedCommand, $actualCommand); | ||
} | ||
|
||
public function testShouldAssembleCommandAndArguments() | ||
{ | ||
$control = new Control(); | ||
$context = new Context(); | ||
$action = new Command('echo', array('Arara', 'Process')); | ||
$action->execute($control, $context); | ||
|
||
$actualCommand = $context->command; | ||
$expectedCommand = "/usr/bin/env echo 'Arara' 'Process'"; | ||
|
||
$this->assertEquals($expectedCommand, $actualCommand); | ||
} | ||
|
||
public function testShouldAssembleCommandAndKeyValueArguments() | ||
{ | ||
$control = new Control(); | ||
$context = new Context(); | ||
$action = new Command('echo', array('-n' => 'Process')); | ||
$action->execute($control, $context); | ||
|
||
$actualCommand = $context->command; | ||
$expectedCommand = "/usr/bin/env echo '-n' 'Process'"; | ||
|
||
$this->assertEquals($expectedCommand, $actualCommand); | ||
} | ||
|
||
public function testShouldNotAssembleWithEnvCommand() | ||
{ | ||
$control = new Control(); | ||
$context = new Context(); | ||
$prefixEnv = false; | ||
$action = new Command('echo', array('Arara\Process'), $prefixEnv); | ||
$action->execute($control, $context); | ||
|
||
$actualCommand = $context->command; | ||
$expectedCommand = "echo 'Arara\Process'"; | ||
|
||
$this->assertEquals($expectedCommand, $actualCommand); | ||
} | ||
|
||
public function testShouldExecuteCommandAndRedirectStderr() | ||
{ | ||
$control = new Control(); | ||
$context = new Context(); | ||
$action = new Command('echo', array('Arara\Process'), false); | ||
$action->execute($control, $context); | ||
|
||
$actualCommand = $GLOBALS['arara']['exec']['args'][0]; | ||
$expectedCommand = "(echo 'Arara\Process')2>&1"; | ||
|
||
$this->assertEquals($expectedCommand, $actualCommand); | ||
} | ||
|
||
/** | ||
* @expectedException RuntimeException | ||
* @expectedExceptionMessage An error has occurred | ||
*/ | ||
public function testShouldThowsAnExceptionWhenCommandGetError() | ||
{ | ||
$GLOBALS['arara']['exec']['output'] = array('echo', 'An error has occurred'); | ||
$GLOBALS['arara']['exec']['return_var'] = 1; | ||
|
||
$control = new Control(); | ||
$context = new Context(); | ||
$action = new Command('echo', array('Arara\nProcess'), false); | ||
$action->execute($control, $context); | ||
} | ||
|
||
public function testShouldStoreLastOutputLine() | ||
{ | ||
$GLOBALS['arara']['exec']['output'] = array('Arara', 'Process'); | ||
|
||
$control = new Control(); | ||
$context = new Context(); | ||
$action = new Command('echo', array('Arara\nProcess')); | ||
$action->execute($control, $context); | ||
|
||
$actualTail = $context->outputTail; | ||
$expectedTail = 'Process'; | ||
|
||
$this->assertEquals($expectedTail, $actualTail); | ||
} | ||
|
||
public function testShouldStoreOutputLines() | ||
{ | ||
$GLOBALS['arara']['exec']['output'] = array('Arara', 'Process'); | ||
|
||
$control = new Control(); | ||
$context = new Context(); | ||
$action = new Command('echo', array('Arara\nProcess')); | ||
$action->execute($control, $context); | ||
|
||
$actualLines = $context->outputLines; | ||
$expectedLines = $GLOBALS['arara']['exec']['output']; | ||
|
||
$this->assertEquals($expectedLines, $actualLines); | ||
} | ||
|
||
public function testShouldStoreOutputString() | ||
{ | ||
$GLOBALS['arara']['exec']['output'] = array('Arara', 'Process'); | ||
|
||
$control = new Control(); | ||
$context = new Context(); | ||
$action = new Command('echo', array('Arara\nProcess')); | ||
$action->execute($control, $context); | ||
|
||
$actualString = $context->outputString; | ||
$expectedString = 'Arara' . PHP_EOL . 'Process'; | ||
|
||
$this->assertEquals($expectedString, $actualString); | ||
} | ||
|
||
public function testShouldStoreReturnValue() | ||
{ | ||
$GLOBALS['arara']['exec']['return_var'] = 0; | ||
|
||
$control = new Control(); | ||
$context = new Context(); | ||
$action = new Command('echo', array('Arara\nProcess')); | ||
$action->execute($control, $context); | ||
|
||
$actualReturn = $context->returnValue; | ||
$expectedReturn = 0; | ||
|
||
$this->assertEquals($expectedReturn, $actualReturn); | ||
} | ||
} |