Skip to content
This repository has been archived by the owner on Jan 16, 2019. It is now read-only.

Commit

Permalink
provide better api for collecting command output in a variable
Browse files Browse the repository at this point in the history
  • Loading branch information
Frank Kleine committed Jun 22, 2016
1 parent 35a35b6 commit f78088e
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 14 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
6.1.0 (2016-06-22)
------------------

### BC breaks

* deprecated `stubbles\console\Executor::executeDirect($command)`, use `$executor->execute($command, collect($array))` or `iterator_to_array($executor->outputOf($command))` instead, will be removed with 7.0.0


### Other changes

* added `stubbles\console\collect()`, but only available when `stubbles\console\Executor` is used


6.0.1 (2016-06-17)
------------------

Expand Down
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ _stubbles/console_ is distributed as [Composer](https://getcomposer.org/)
package. To install it as a dependency of your package use the following
command:

composer require "stubbles/console": "^6.0"
composer require "stubbles/console": "^6.1"


Requirements
Expand Down Expand Up @@ -373,17 +373,15 @@ From time to time it is necessary to run another command line program from withi
your application. Stubbles Console provides a convenient way to do this via the
`stubbles\console\Executor` class.

It provides four different ways to run a command line program:
It provides three different ways to run a command line program:

1. `execute($command, callable $out = null)`: This will simply execute the
given command. If the executor receives an callable the callable will be
executed for each single line of the command's output.
2. `executeAsync($command)`: This will execute the command, but reading the
output of the command can be done later via the returned `CommandInputStream`
instance which is a normal [input stream](https://github.com/stubbles/stubbles-streams).
3. `executeDirect($command)`: The will execute the given command, and return its
output as array, where one entry resembles one line of the output.
4. `outputOf($command)`: This will execute the given command and return a
3. `outputOf($command)`: This will execute the given command and return a
[Generator](http://php.net/manual/en/language.generators.php) which yields
each single line from the command's output as it occurs. (_Available since
release 6.0.0._)
Expand Down Expand Up @@ -429,3 +427,17 @@ foreach ($executor->outputOf('git clone git://github.com/stubbles/stubbles-conso
echo $line;
}
```

### Collect output in a variable

Sometimes it's sufficient to collect the output of a command in a separate
variable. This can be done using the `stubbles\console\collect()` function:

```php
$out = '';
$executor->execute('git clone git://github.com/stubbles/stubbles-console.git', collect($out));
```

Afterwards, `$out` contains all output from the command, separated by `PHP_EOL`.
Alternatively, an array can be used, each element in the array will be a line
from the command output then.
35 changes: 29 additions & 6 deletions src/main/php/Executor.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,30 @@
* @package stubbles\console
*/
namespace stubbles\console;

use function stubbles\values\typeOf;
/**
* creates a callable to collect output in given reference
*
* @param string|array &$out something which will receive each line from the command output
* @return callable
* @throws \InvalidArgumentException in case $out is neither a string nor an array
* @since 6.1.0
*/
function collect(&$out)
{
if (is_string($out)) {
return function($line) use(&$out) { $out .= $line . PHP_EOL; };
} elseif (is_array($out)) {
return function($line) use(&$out) { $out[] = $line; };
}

throw new \InvalidArgumentException(
'Parameter $out must be a string or an array, but was of type '
. typeOf($out)
);
}

/**
* Execute commands on the command line.
*
Expand All @@ -18,18 +42,16 @@ class Executor
/**
* executes given command
*
* If no callable is passed the output of the command is simply ignored.
*
* @param string $command
* @param callable $out optional callable which will receive each line from the command output
* @param callable $collect optional callable which will receive each line from the command output
* @param string $redirect optional how to redirect error output
* @return \stubbles\console\Executor
*/
public function execute($command, callable $out = null, $redirect = '2>&1')
public function execute($command, callable $collect = null, $redirect = '2>&1')
{
foreach ($this->outputOf($command, $redirect) as $line) {
if (null !== $out) {
$out($line);
if (null !== $collect) {
$collect($line);
}
}

Expand Down Expand Up @@ -64,6 +86,7 @@ public function executeAsync($command, $redirect = '2>&1')
* @param string $command
* @param string $redirect optional how to redirect error output
* @return string[]
* @deprecated since 6.1.0, use $executor->execute($command, collect($array)) or iterator_to_array($executor->outputOf($command)) instead, will be removed with 7.0.0
*/
public function executeDirect($command, $redirect = '2>&1')
{
Expand Down
42 changes: 39 additions & 3 deletions src/test/php/ExecutorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use stubbles\streams\memory\MemoryOutputStream;

use function bovigo\assert\assert;
use function bovigo\assert\expect;
use function bovigo\assert\predicate\equals;
use function bovigo\assert\predicate\isSameAs;
/**
Expand Down Expand Up @@ -46,11 +47,44 @@ public function executeWithoutOutputStream()
/**
* @test
*/
public function executeWithOutputStreamWritesResponseDataToOutputStream()
public function executeWithCallableCallsCallableWithCommandOutput()
{
$memory = new MemoryOutputStream();
$this->executor->execute('echo foo', [$memory, 'writeLine']);
assert($memory->buffer(), equals("foo\n"));
$this->executor->execute('echo foo;echo bar', [$memory, 'writeLine']);
assert($memory->buffer(), equals("foo\nbar\n"));
}

/**
* @test
* @since 6.1.0
*/
public function executeWithCollectStringAppendsCommandOutputToString()
{
$out = '';
$this->executor->execute('echo foo;echo bar', collect($out));
assert($out, equals("foo\nbar\n"));
}

/**
* @test
* @since 6.1.0
*/
public function executeWithCollectArrayAppendsCommandOutputToArray()
{
$out = [];
$this->executor->execute('echo foo;echo bar', collect($out));
assert($out, equals(['foo', 'bar']));
}

/**
* @test
* @since 6.1.0
*/
public function collectInNonStringAndNonArrayThrowsInvalidArgumentException()
{
expect(function() { $var = 0; collect($var); })
->throws(\InvalidArgumentException::class)
->withMessage('Parameter $out must be a string or an array, but was of type integer');
}

/**
Expand Down Expand Up @@ -110,6 +144,7 @@ public function readAfterCloseThrowsIllegalStateException()

/**
* @test
* @deprecated since 6.1.0, will be removed with 7.0.0
*/
public function executeDirectReturnsOutputAsArray()
{
Expand All @@ -119,6 +154,7 @@ public function executeDirectReturnsOutputAsArray()
/**
* @test
* @expectedException RuntimeException
* @deprecated since 6.1.0, will be removed with 7.0.0
*/
public function executeDirectFailsThrowsRuntimeException()
{
Expand Down

0 comments on commit f78088e

Please sign in to comment.