Skip to content

Commit

Permalink
Decouple \Symfony\Component\Console\Helper\ProgressBar from tasks tha…
Browse files Browse the repository at this point in the history
…t use progress indicators.
  • Loading branch information
greg-1-anderson committed Mar 24, 2016
1 parent f213930 commit 1ae7711
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 39 deletions.
12 changes: 7 additions & 5 deletions RoboFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,13 +304,15 @@ public function tryInput()
/**
* Test parallel execution
*/
public function tryPara()
public function tryPara($options = ['printed' => false])
{
$dir = __DIR__;
$this->taskParallelExec()
->process('php ~/demos/robotests/parascript.php hey')
->process('php ~/demos/robotests/parascript.php hoy')
->process('php ~/demos/robotests/parascript.php gou')
->process('php ~/demos/robotests/parascript.php die')
->process("php $dir/tests/_data/parascript.php hey 4")
->process("php $dir/tests/_data/parascript.php hoy 3")
->process("php $dir/tests/_data/parascript.php gou 2")
->process("php $dir/tests/_data/parascript.php die 1")
->printed($options['printed'])
->run();
}

Expand Down
59 changes: 59 additions & 0 deletions src/Common/ProgressIndicatorAwareTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
namespace Robo\Common;

trait ProgressIndicatorAwareTrait
{
use Timer;

protected $progressIndicator;
protected $progressIndicatorRunning = false;

public function setProgressIndicator($progressIndicator)
{
$this->progressIndicator = $progressIndicator;
}

public function hideProgressIndicator()
{
if ($this->progressIndicatorRunning) {
$this->progressIndicator->clear();
// Hack: progress indicator does not reset cursor to beginning of line on 'clear'
\Robo\Config::output()->write("\x0D");
}
}

public function showProgressIndicator()
{
if ($this->progressIndicatorRunning) {
$this->progressIndicator->display();
}
}

public function startProgressIndicator($totalSteps = 0)
{
$this->startTimer();
if (isset($this->progressIndicator)) {
$this->progressIndicator->start($totalSteps);
$this->progressIndicator->display();
$this->progressIndicatorRunning = true;
}
}

public function stopProgressIndicator()
{
$this->stopTimer();
if ($this->progressIndicatorRunning) {
$this->progressIndicatorRunning = false;
$this->progressIndicator->finish();
// Hack: progress indicator does not always finish cleanly
\Robo\Config::output()->writeln('');
}
}

public function advanceProgressIndicator($steps = 1)
{
if ($this->progressIndicatorRunning) {
$this->progressIndicator->advance($steps);
}
}
}
23 changes: 18 additions & 5 deletions src/Common/TaskIO.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use Consolidation\Log\ConsoleLogLevel;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Robo\Contract\ProgressIndicatorAwareInterface;

/**
* Task input/output methods. TaskIO is 'used' in BaseTask, so any
Expand Down Expand Up @@ -51,7 +53,7 @@ protected function printTaskInfo($text, $context = null)
// The 'note' style is used for both 'notice' and 'info' log levels;
// However, 'notice' is printed at VERBOSITY_NORMAL, whereas 'info'
// is only printed at VERBOSITY_VERBOSE.
$this->logger()->notice($text, $this->getTaskContext($context));
$this->printTaskOutput(LogLevel::NOTICE, $text, $this->getTaskContext($context));
}

/**
Expand All @@ -68,7 +70,7 @@ protected function printTaskSuccess($text, $context = null)
// override in the context so that this message will be
// logged as SUCCESS if that log level is recognized.
$context['_level'] = ConsoleLogLevel::SUCCESS;
$this->logger()->notice($text, $this->getTaskContext($context));
$this->printTaskOutput(LogLevel::NOTICE, $text, $this->getTaskContext($context));
}

/**
Expand All @@ -79,7 +81,7 @@ protected function printTaskSuccess($text, $context = null)
*/
protected function printTaskWarning($text, $context = null)
{
$this->logger()->warning($text, $this->getTaskContext($context));
$this->printTaskOutput(LogLevel::WARNING, $text, $this->getTaskContext($context));
}

/**
Expand All @@ -90,7 +92,7 @@ protected function printTaskWarning($text, $context = null)
*/
protected function printTaskError($text, $context = null)
{
$this->logger()->error($text, $this->getTaskContext($context));
$this->printTaskOutput(LogLevel::ERROR, $text, $this->getTaskContext($context));
}

/**
Expand All @@ -99,7 +101,18 @@ protected function printTaskError($text, $context = null)
*/
protected function printTaskDebug($text, $context = null)
{
$this->logger()->debug($text, $this->getTaskContext($context));
$this->printTaskOutput(LogLevel::DEBUG, $text, $this->getTaskContext($context));
}

private function printTaskOutput($level, $text, $context)
{
if ($this instanceof ProgressIndicatorAwareInterface) {
$this->hideProgressIndicator();
}
$this->logger()->log($level, $text, $this->getTaskContext($context));
if ($this instanceof ProgressIndicatorAwareInterface) {
$this->showProgressIndicator();
}
}

/**
Expand Down
21 changes: 21 additions & 0 deletions src/Contract/ProgressIndicatorAwareInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php
namespace Robo\Contract;

/**
* Any Robo task that uses the Timer trait and
* implements ProgressIndicatorAwareInterface will
* display a progress bar while the timer is running.
* Call advanceProgressIndicator to advance the indicator.
*
* Interface ProgressIndicatorAwareInterface
* @package Robo\Contract
*/
interface ProgressIndicatorAwareInterface
{
public function setProgressIndicator($progressIndicator);
public function startProgressIndicator($totalSteps = 0);
public function stopProgressIndicator();
public function hideProgressIndicator();
public function showProgressIndicator();
public function advanceProgressIndicator($steps = 1);
}
4 changes: 4 additions & 0 deletions src/Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ public static function configureContainer($container, $input = null, $output = n
$container->share('logger', \Robo\Log\RoboLogger::class)
->withArgument('output')
->withMethodCall('setLogOutputStyler', ['logStyler']);
$container->add('progressIndicator', \Symfony\Component\Console\Helper\ProgressBar::class)
->withArgument('output');
$container->share('resultPrinter', \Robo\Log\ResultPrinter::class);
$container->add('simulator', \Robo\Task\Simulator::class);
$container->share('globalOptionsEventListener', \Robo\GlobalOptionsEventListener::class);
Expand All @@ -163,6 +165,8 @@ public static function configureContainer($container, $input = null, $output = n
->invokeMethod('setContainer', ['container']);
$container->inflector(\Symfony\Component\Console\Input\InputAwareInterface::class)
->invokeMethod('setInput', ['input']);
$container->inflector(\Robo\Contract\ProgressIndicatorAwareInterface::class)
->invokeMethod('setProgressIndicator', ['progressIndicator']);
}

/**
Expand Down
24 changes: 8 additions & 16 deletions src/Task/Base/ParallelExec.php
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
<?php
namespace Robo\Task\Base;

use Robo\Common\Timer;
use Robo\Contract\ProgressIndicatorAwareInterface;
use Robo\Common\ProgressIndicatorAwareTrait;
use Robo\Contract\CommandInterface;
use Robo\Contract\PrintedInterface;
use Robo\Result;
use Robo\Task\BaseTask;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Exception\ProcessTimedOutException;
use Symfony\Component\Process\Process;

Expand All @@ -28,11 +27,10 @@
* @method \Robo\Task\Base\ParallelExec timeout(int $timeout) stops process if it runs longer then `$timeout` (seconds)
* @method \Robo\Task\Base\ParallelExec idleTimeout(int $timeout) stops process if it does not output for time longer then `$timeout` (seconds)
*/
class ParallelExec extends BaseTask implements CommandInterface, PrintedInterface
class ParallelExec extends BaseTask implements CommandInterface, PrintedInterface, ProgressIndicatorAwareInterface
{
use Timer;
use ProgressIndicatorAwareTrait;
use \Robo\Common\CommandReceiver;
use \Robo\Common\IO;

protected $processes = [];
protected $timeout = null;
Expand Down Expand Up @@ -83,23 +81,18 @@ public function run()
$this->printTaskInfo($process->getCommandLine());
}

$progress = new ProgressBar($this->getOutput());
$progress->start(count($this->processes));
$this->startProgressIndicator(count($this->processes));
$running = $this->processes;
$progress->display();
$this->startTimer();
while (true) {
foreach ($running as $k => $process) {
try {
$process->checkTimeout();
} catch (ProcessTimedOutException $e) {
}
if (!$process->isRunning()) {
$progress->advance();
$this->advanceProgressIndicator();
if ($this->isPrinted) {
$this->getOutput()->writeln("");
$this->printTaskInfo("Output for {command}", ['command' => $process->getCommandLine(), '_style' => ['command' => 'fg=white;bg=magenta']]);
$this->getOutput()->writeln($process->getOutput(), OutputInterface::OUTPUT_RAW);
$this->printTaskInfo("Output for {command}:\n\n{output}", ['command' => $process->getCommandLine(), 'output' => $process->getOutput(), '_style' => ['command' => 'fg=white;bg=magenta']]);
if ($process->getErrorOutput()) {
$this->getOutput()->writeln("<error>" . $process->getErrorOutput() . "</error>");
}
Expand All @@ -112,8 +105,7 @@ public function run()
}
usleep(1000);
}
$this->getOutput()->writeln("");
$this->stopTimer();
$this->stopProgressIndicator();

$errorMessage = '';
$exitCode = 0;
Expand Down
22 changes: 9 additions & 13 deletions src/Task/Development/PackPhar.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<?php
namespace Robo\Task\Development;

use Robo\Common\Timer;
use Robo\Common\IO;
use Robo\Contract\ProgressIndicatorAwareInterface;
use Robo\Common\ProgressIndicatorAwareTrait;
use Robo\Contract\PrintedInterface;
use Robo\Result;
use Robo\Task\BaseTask;
use Symfony\Component\Console\Helper\ProgressBar;

/**
* Creates Phar.
Expand Down Expand Up @@ -39,10 +38,9 @@
* ?>
* ```
*/
class PackPhar extends BaseTask implements PrintedInterface
class PackPhar extends BaseTask implements PrintedInterface, ProgressIndicatorAwareInterface
{
use Timer;
use IO;
use ProgressIndicatorAwareTrait;

/**
* @var \Phar
Expand Down Expand Up @@ -107,16 +105,13 @@ public function run()

$this->printTaskInfo('Packing {file-count} files into phar', ['file-count' => count($this->files)]);

$progress = new ProgressBar($this->getOutput());
$progress->start(count($this->files));
$this->startTimer();
$this->startProgressIndicator(count($this->files)+2);
foreach ($this->files as $path => $content) {
$this->phar->addFromString($path, $content);
$progress->advance();
$this->advanceProgressIndicator();
}
$this->phar->stopBuffering();
$progress->finish();
$this->getOutput()->writeln('');
$this->advanceProgressIndicator();

if ($this->compress and in_array('GZ', \Phar::getSupportedCompression())) {
if (count($this->files) > 1000) {
Expand All @@ -126,7 +121,8 @@ public function run()
$this->phar = $this->phar->compressFiles(\Phar::GZ);
}
}
$this->stopTimer();
$this->advanceProgressIndicator();
$this->stopProgressIndicator();
$this->printTaskSuccess('{filename} produced', ['filename' => $this->filename]);
return Result::success($this, '', ['time' => $this->getExecutionTime()]);
}
Expand Down
8 changes: 8 additions & 0 deletions tests/_data/parascript.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

$message = $argv[1];
$iterations = $argv[2];
for ($i=0; $i < $iterations; ++$i) {
print "$message\n";
sleep(1);
}

0 comments on commit 1ae7711

Please sign in to comment.