Add basic progress bar capability while waiting for jobs to complete
parent
b1e15c7725
commit
9f380d606c
|
@ -14,6 +14,7 @@ namespace Composer\IO;
|
|||
|
||||
use Composer\Question\StrictConfirmationQuestion;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
@ -253,6 +254,15 @@ class ConsoleIO extends BaseIO
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $max
|
||||
* @return ProgressBar
|
||||
*/
|
||||
public function getProgressBar($max = 0)
|
||||
{
|
||||
return new ProgressBar($this->getErrorOutput(), $max);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
namespace Composer\Installer;
|
||||
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\IO\ConsoleIO;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Package\AliasPackage;
|
||||
use Composer\Repository\RepositoryInterface;
|
||||
|
@ -330,7 +331,14 @@ class InstallationManager
|
|||
|
||||
// execute all prepare => installs/updates/removes => cleanup steps
|
||||
if (!empty($promises)) {
|
||||
$this->loop->wait($promises);
|
||||
$progress = null;
|
||||
if ($io instanceof ConsoleIO && !$io->isDebug()) {
|
||||
$progress = $io->getProgressBar();
|
||||
}
|
||||
$this->loop->wait($promises, $progress);
|
||||
if ($progress) {
|
||||
$progress->clear();
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$runCleanup();
|
||||
|
|
|
@ -267,21 +267,12 @@ class HttpDownloader
|
|||
public function markJobDone()
|
||||
{
|
||||
$this->runningJobs--;
|
||||
|
||||
foreach ($this->jobs as $job) {
|
||||
if ($job['status'] === self::STATUS_QUEUED) {
|
||||
$this->startJob($job['id']);
|
||||
if ($this->runningJobs >= $this->maxJobs) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function wait($index = null)
|
||||
{
|
||||
while (true) {
|
||||
if (!$this->hasActiveJob($index)) {
|
||||
if (!$this->countActiveJobs($index)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -299,26 +290,37 @@ class HttpDownloader
|
|||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @return int number of active (queued or started) jobs
|
||||
*/
|
||||
public function hasActiveJob($index = null)
|
||||
public function countActiveJobs($index = null)
|
||||
{
|
||||
if ($this->runningJobs < $this->maxJobs) {
|
||||
foreach ($this->jobs as $job) {
|
||||
if ($job['status'] === self::STATUS_QUEUED && $this->runningJobs < $this->maxJobs) {
|
||||
$this->startJob($job['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->curl) {
|
||||
$this->curl->tick();
|
||||
}
|
||||
|
||||
if (null !== $index) {
|
||||
return $this->jobs[$index]['status'] < self::STATUS_COMPLETED;
|
||||
return $this->jobs[$index]['status'] < self::STATUS_COMPLETED ? 1 : 0;
|
||||
}
|
||||
|
||||
$active = 0;
|
||||
foreach ($this->jobs as $job) {
|
||||
if ($job['status'] < self::STATUS_COMPLETED) {
|
||||
return true;
|
||||
$active++;
|
||||
} elseif (!$job['sync']) {
|
||||
unset($this->jobs[$job['id']]);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return $active;
|
||||
}
|
||||
|
||||
private function getResponse($index)
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace Composer\Util;
|
|||
|
||||
use Composer\Util\HttpDownloader;
|
||||
use React\Promise\Promise;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
|
@ -36,7 +37,7 @@ class Loop
|
|||
}
|
||||
}
|
||||
|
||||
public function wait(array $promises)
|
||||
public function wait(array $promises, ProgressBar $progress = null)
|
||||
{
|
||||
/** @var \Exception|null */
|
||||
$uncaught = null;
|
||||
|
@ -50,21 +51,32 @@ class Loop
|
|||
|
||||
$this->currentPromises = $promises;
|
||||
|
||||
while (true) {
|
||||
$hasActiveJob = false;
|
||||
|
||||
if ($progress) {
|
||||
$totalJobs = 0;
|
||||
if ($this->httpDownloader) {
|
||||
if ($this->httpDownloader->hasActiveJob()) {
|
||||
$hasActiveJob = true;
|
||||
}
|
||||
$totalJobs += $this->httpDownloader->countActiveJobs();
|
||||
}
|
||||
if ($this->processExecutor) {
|
||||
if ($this->processExecutor->hasActiveJob()) {
|
||||
$hasActiveJob = true;
|
||||
}
|
||||
$totalJobs += $this->processExecutor->countActiveJobs();
|
||||
}
|
||||
$progress->start($totalJobs);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
$activeJobs = 0;
|
||||
|
||||
if ($this->httpDownloader) {
|
||||
$activeJobs += $this->httpDownloader->countActiveJobs();
|
||||
}
|
||||
if ($this->processExecutor) {
|
||||
$activeJobs += $this->processExecutor->countActiveJobs();
|
||||
}
|
||||
|
||||
if (!$hasActiveJob) {
|
||||
if ($progress) {
|
||||
$progress->setProgress($progress->getMaxSteps() - $activeJobs);
|
||||
}
|
||||
|
||||
if (!$activeJobs) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -250,7 +250,7 @@ class ProcessExecutor
|
|||
public function wait($index = null)
|
||||
{
|
||||
while (true) {
|
||||
if (!$this->hasActiveJob($index)) {
|
||||
if (!$this->countActiveJobs($index)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -268,8 +268,10 @@ class ProcessExecutor
|
|||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @return int number of active (queued or started) jobs
|
||||
*/
|
||||
public function hasActiveJob($index = null)
|
||||
public function countActiveJobs($index = null)
|
||||
{
|
||||
// tick
|
||||
foreach ($this->jobs as $job) {
|
||||
|
@ -278,21 +280,28 @@ class ProcessExecutor
|
|||
call_user_func($job['resolve'], $job['process']);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->runningJobs < $this->maxJobs) {
|
||||
if ($job['status'] === self::STATUS_QUEUED) {
|
||||
$this->startJob($job['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $index) {
|
||||
return $this->jobs[$index]['status'] < self::STATUS_COMPLETED;
|
||||
return $this->jobs[$index]['status'] < self::STATUS_COMPLETED ? 1 : 0;
|
||||
}
|
||||
|
||||
$active = 0;
|
||||
foreach ($this->jobs as $job) {
|
||||
if ($job['status'] < self::STATUS_COMPLETED) {
|
||||
return true;
|
||||
$active++;
|
||||
} else {
|
||||
unset($this->jobs[$job['id']]);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return $active;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -301,15 +310,6 @@ class ProcessExecutor
|
|||
public function markJobDone()
|
||||
{
|
||||
$this->runningJobs--;
|
||||
|
||||
foreach ($this->jobs as $job) {
|
||||
if ($job['status'] === self::STATUS_QUEUED) {
|
||||
$this->startJob($job['id']);
|
||||
if ($this->runningJobs >= $this->maxJobs) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function splitLines($output)
|
||||
|
|
Loading…
Reference in New Issue