Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a progress bar #236

Merged
merged 4 commits into from
Oct 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@
"@test-common"
],
"test-common": [
"@composer validate --strict",
"parallel-lint src tests",
"phpmd src text phpmd.xml",
"phploc src",
"phpcpd src",
"phpunit --colors=always --testdox --coverage-clover=coverage.xml",
"@php bin/churn run src"
"@php bin/churn run src -p -vvv"
]
}
}
46 changes: 37 additions & 9 deletions src/Commands/ChurnCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,37 @@

namespace Churn\Commands;

use Churn\Configuration\Config;
use Churn\Factories\ResultsRendererFactory;
use Churn\Logic\ResultsLogic;
use Churn\Factories\ProcessFactory;
use Churn\Managers\FileManager;
use Churn\Processes\ProcessHandlerFactory;
use Churn\Process\Observer\OnSuccess;
use Churn\Process\Observer\OnSuccessNull;
use Churn\Process\Observer\OnSuccessProgress;
use Churn\Process\ProcessFactory;
use Churn\Process\ProcessHandlerFactory;
use function count;
use function file_get_contents;
use InvalidArgumentException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Churn\Configuration\Config;
use Symfony\Component\Yaml\Yaml;
use InvalidArgumentException;

/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class ChurnCommand extends Command
{
private const LOGO ="
___ _ _ __ __ ____ _ _ ____ _ _ ____
/ __)( )_( )( )( )( _ \( \( )___( _ \( )_( )( _ \
( (__ ) _ ( )(__)( ) / ) ((___))___/ ) _ ( )___/
\___)(_) (_)(______)(_)\_)(_)\_) (__) (_) (_)(__)";

/**
* The results logic.
* @var ResultsLogic
Expand Down Expand Up @@ -68,34 +78,34 @@ protected function configure(): void
->addArgument('paths', InputArgument::IS_ARRAY, 'Path to source to check.')
->addOption('configuration', 'c', InputOption::VALUE_OPTIONAL, 'Path to the configuration file', 'churn.yml') // @codingStandardsIgnoreLine
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format to use', 'text')
->addOption('progress', 'p', InputOption::VALUE_NONE, 'Show progress bar')
->setDescription('Check files')
->setHelp('Checks the churn on the provided path argument(s).');
}

/**
* Execute the command
* @param InputInterface $input Input.
* @param OutputInterface $output Output.
* @param InputInterface $input Input.
* @param OutputInterface $output Output.
* @return integer
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln(self::LOGO);
$content = (string) @file_get_contents($input->getOption('configuration'));
$config = Config::create(Yaml::parse($content) ?? []);
$filesCollection = (new FileManager($config->getFileExtensions(), $config->getFilesToIgnore()))
->getPhpFiles($this->getDirectoriesToScan($input, $config->getDirectoriesToScan()));

$completedProcesses = $this->processHandlerFactory->getProcessHandler($config)->process(
$filesCollection,
new ProcessFactory($config->getCommitsSince()),
$config->getParallelJobs()
$this->getOnSuccessObserver($input, $output, $filesCollection->count())
);
$resultCollection = $this->resultsLogic->process(
$completedProcesses,
$config->getMinScoreToShow(),
$config->getFilesToShow()
);

$renderer = $this->renderFactory->getRenderer($input->getOption('format'));
$renderer->render($output, $resultCollection);
return 0;
Expand Down Expand Up @@ -124,4 +134,22 @@ private function getDirectoriesToScan(InputInterface $input, array $dirsConfigur
'or configure them under "directoriesToScan" in your churn.yml file.'
);
}

/**
* @param InputInterface $input Input.
* @param OutputInterface $output Output.
* @param integer $totalFiles Total number of files to process.
* @return OnSuccess
*/
private function getOnSuccessObserver(InputInterface $input, OutputInterface $output, int $totalFiles): OnSuccess
{
if ((bool)$input->getOption('progress')) {
$output->writeln("\n");
$progressBar = new ProgressBar($output, $totalFiles);
$progressBar->start();
return new OnSuccessProgress($progressBar);
}

return new OnSuccessNull();
}
}
12 changes: 10 additions & 2 deletions src/Processes/ChurnProcess.php → src/Process/ChurnProcess.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?php declare(strict_types = 1);


namespace Churn\Processes;
namespace Churn\Process;

use Churn\Values\File;
use Symfony\Component\Process\Exception\ProcessFailedException;
Expand Down Expand Up @@ -83,6 +82,15 @@ public function getFilename(): string
return $this->file->getDisplayPath();
}

/**
* Gets the file the process is being executed on.
* @return File
*/
public function getFile(): File
{
return $this->file;
}

/**
* Gets a unique key used for storing the process in data structures.
* @return string
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
<?php declare(strict_types = 1);

namespace Churn\Processes\Handler;
namespace Churn\Process\Handler;

use Churn\Collections\FileCollection;
use Churn\Factories\ProcessFactory;
use Churn\Process\Observer\OnSuccess;
use Churn\Process\ProcessFactory;
use Churn\Values\File;
use function count;
use Illuminate\Support\Collection;

class ParallelProcessHandler implements ProcessHandler
Expand Down Expand Up @@ -51,28 +54,31 @@ public function __construct(int $numberOfParallelJobs)
* Run the processes to gather information.
* @param FileCollection $filesCollection Collection of files.
* @param ProcessFactory $processFactory Process Factory.
* @param OnSuccess $onSuccess The OnSuccess event observer.
* @return Collection
*/
public function process(
FileCollection $filesCollection,
ProcessFactory $processFactory
ProcessFactory $processFactory,
OnSuccess $onSuccess
): Collection {
$this->filesCollection = $filesCollection;
$this->processFactory = $processFactory;
$this->runningProcesses = new Collection;
$this->completedProcessesArray = [];
while ($filesCollection->hasFiles() || $this->runningProcesses->count()) {
$this->getProcessResults($this->numberOfParallelJobs);
$this->getProcessResults($this->numberOfParallelJobs, $onSuccess);
}
return new Collection($this->completedProcessesArray);
}

/**
* Get the results of the processes.
* @param integer $numberOfParallelJobs Number of parallel jobs to run.
* @param integer $numberOfParallelJobs Number of parallel jobs to run.
* @param OnSuccess $onSuccess The OnSuccess event observer.
* @return void
*/
private function getProcessResults(int $numberOfParallelJobs): void
private function getProcessResults(int $numberOfParallelJobs, OnSuccess $onSuccess): void
{
$index = $this->runningProcesses->count();
for (; $index < $numberOfParallelJobs && $this->filesCollection->hasFiles() > 0; $index++) {
Expand All @@ -89,7 +95,20 @@ private function getProcessResults(int $numberOfParallelJobs): void
if ($process->isSuccessful()) {
$this->runningProcesses->forget($process->getKey());
$this->completedProcessesArray[$process->getFileName()][$process->getType()] = $process;
$this->sendEventIfComplete($process->getFile(), $onSuccess);
}
}
}

/**
* @param File $file The file processed.
* @param OnSuccess $onSuccess The OnSuccess event observer.
* @return void
*/
private function sendEventIfComplete(File $file, OnSuccess $onSuccess): void
{
if (count($this->completedProcessesArray[$file->getDisplayPath()]) === 2) {
$onSuccess($file);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<?php declare(strict_types = 1);

namespace Churn\Processes\Handler;
namespace Churn\Process\Handler;

use Churn\Collections\FileCollection;
use Churn\Factories\ProcessFactory;
use Churn\Process\Observer\OnSuccess;
use Churn\Process\ProcessFactory;
use Illuminate\Support\Collection;

interface ProcessHandler
Expand All @@ -12,10 +13,12 @@ interface ProcessHandler
* Run the processes to gather information.
* @param FileCollection $filesCollection Collection of files.
* @param ProcessFactory $processFactory Process Factory.
* @param OnSuccess $onSuccess The OnSuccess event observer.
* @return Collection
*/
public function process(
FileCollection $filesCollection,
ProcessFactory $processFactory
ProcessFactory $processFactory,
OnSuccess $onSuccess
): Collection;
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<?php declare(strict_types = 1);

namespace Churn\Processes\Handler;
namespace Churn\Process\Handler;

use Churn\Collections\FileCollection;
use Churn\Factories\ProcessFactory;
use Churn\Process\Observer\OnSuccess;
use Churn\Process\ProcessFactory;
use Illuminate\Support\Collection;

class SequentialProcessHandler implements ProcessHandler
Expand All @@ -12,11 +13,13 @@ class SequentialProcessHandler implements ProcessHandler
* Run the processes sequentially to gather information.
* @param FileCollection $filesCollection Collection of files.
* @param ProcessFactory $processFactory Process Factory.
* @param OnSuccess $onSuccess The OnSuccess event observer.
* @return Collection
*/
public function process(
FileCollection $filesCollection,
ProcessFactory $processFactory
ProcessFactory $processFactory,
OnSuccess $onSuccess
): Collection {
$completedProcessesArray = [];
while ($filesCollection->hasFiles()) {
Expand All @@ -29,6 +32,7 @@ public function process(
$process->start();
while (!$process->isSuccessful());
$completedProcessesArray[$process->getFileName()][$process->getType()] = $process;
$onSuccess($file);
}
return new Collection($completedProcessesArray);
}
Expand Down
15 changes: 15 additions & 0 deletions src/Process/Observer/OnSuccess.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php declare(strict_types = 1);

namespace Churn\Process\Observer;

use Churn\Values\File;

interface OnSuccess
{
/**
* Triggers an event when a file is successfully processed.
* @param File $file The file successfully processed.
* @return void
*/
public function __invoke(File $file): void;
}
17 changes: 17 additions & 0 deletions src/Process/Observer/OnSuccessNull.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php declare(strict_types = 1);

namespace Churn\Process\Observer;

use Churn\Values\File;

class OnSuccessNull implements OnSuccess
{
/**
* Do nothing.
* @param File $file The file successfully processed.
* @return void
*/
public function __invoke(File $file): void
{
}
}
33 changes: 33 additions & 0 deletions src/Process/Observer/OnSuccessProgress.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php declare(strict_types = 1);

namespace Churn\Process\Observer;

use Churn\Values\File;
use Symfony\Component\Console\Helper\ProgressBar;

class OnSuccessProgress implements OnSuccess
{
/**
* @var ProgressBar The progress bar to advance.
*/
private $progressBar;

/**
* OnSuccessProgress constructor.
* @param ProgressBar $progressBar The progress bar to advance.
*/
public function __construct(ProgressBar $progressBar)
{
$this->progressBar = $progressBar;
}

/**
* Triggers an event when a file is successfully processed.
* @param File $file The file successfully processed.
* @return void
*/
public function __invoke(File $file): void
{
$this->progressBar->advance();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
<?php declare(strict_types = 1);

namespace Churn\Factories;
namespace Churn\Process;

use Churn\Processes\ChurnProcess;
use Churn\Values\File;
use function getcwd;
use Symfony\Component\Process\PhpExecutableFinder;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?php declare(strict_types = 1);

namespace Churn\Processes;
namespace Churn\Process;

use Churn\Configuration\Config;
use Churn\Processes\Handler\ParallelProcessHandler;
use Churn\Processes\Handler\ProcessHandler;
use Churn\Processes\Handler\SequentialProcessHandler;
use Churn\Process\Handler\ParallelProcessHandler;
use Churn\Process\Handler\ProcessHandler;
use Churn\Process\Handler\SequentialProcessHandler;

class ProcessHandlerFactory
{
Expand Down
Loading