Skip to content

Commit

Permalink
Add a configuration to enable caching
Browse files Browse the repository at this point in the history
  • Loading branch information
villfa committed Feb 11, 2021
1 parent 3ad26a4 commit 4da142d
Show file tree
Hide file tree
Showing 28 changed files with 682 additions and 151 deletions.
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ docker run --rm -ti -v $PWD:/app dockerizedphp/churn run src
You may add an optional `churn.yml` file which can be used to configure churn-php. The location of the churn.yml file can be customized using these commands:

```
Default: "churn.yml"
vendor/bin/churn run -c <path>
vendor/bin/churn run --configuration[=CONFIGURATION] <path>
# Default: "churn.yml"
vendor/bin/churn run --configuration=config-dir/ <path>
vendor/bin/churn run --configuration=my-config.yml <path>
```
A sample `churn.yml` file looks like:

Expand Down Expand Up @@ -108,10 +108,21 @@ fileExtensions:
- php
- inc

# This list is used only if there is no argument when running churn.
# Default: <empty>
directoriesToScan:
- src
- tests/

# The version control system used for your project.
# Accepted values: fossil, git, mercurial, subversion, none
# Default: git
vcs: git

# The path of the cache file. It doesn't need to exist before running churn.
# Disabled if null.
# Default: null
cachePath: .churn.cache
```
If a `churn.yml` file is omitted or an individual setting is omitted the default values above will be used.
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"php": ">=7.1.3",
"composer/package-versions-deprecated": "^1.11",
"symfony/console": "^3.4 || ^4.0 || ^5.0",
"symfony/filesystem": "^3.4 || ^4.0 || ^5.0",
"symfony/process": "^3.4 || ^4.0 || ^5.0",
"symfony/yaml": "^3.4 || ^4.0 || ^5.0",
"webmozart/assert": "^1.2"
Expand Down
56 changes: 29 additions & 27 deletions src/Command/RunCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
use Churn\Configuration\Loader;
use Churn\File\FileFinder;
use Churn\File\FileHelper;
use Churn\Process\Observer\OnSuccess;
use Churn\Process\Observer\OnSuccessAccumulate;
use Churn\Process\Observer\OnSuccessCollection;
use Churn\Process\Observer\OnSuccessProgress;
use Churn\Process\CacheProcessFactory;
use Churn\Process\ConcreteProcessFactory;
use Churn\Process\Observer\OnSuccessBuilder;
use Churn\Process\ProcessFactory;
use Churn\Process\ProcessHandlerFactory;
use Churn\Result\ResultAccumulator;
Expand Down Expand Up @@ -97,7 +96,7 @@ protected function configure(): void
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->displayLogo($input, $output);
$this->printLogo($input, $output);
$accumulator = $this->analyze($input, $output, $this->getConfiguration($input));
$this->writeResult($input, $output, $accumulator);

Expand Down Expand Up @@ -140,14 +139,20 @@ private function getConfiguration(InputInterface $input): Config
*/
private function analyze(InputInterface $input, OutputInterface $output, Config $config): ResultAccumulator
{
$observers = [];
if (true === $input->getOption('progress')) {
$observers[] = $progressBar = new ProgressBar($output);
$progressBar->start();
}
$filesFinder = (new FileFinder($config->getFileExtensions(), $config->getFilesToIgnore()))
->getPhpFiles($this->getDirectoriesToScan($input, $config));
$accumulator = new ResultAccumulator($config->getFilesToShow(), $config->getMinScoreToShow());
$this->processHandlerFactory->getProcessHandler($config)->process(
$filesFinder,
new ProcessFactory($config->getVCS(), $config->getCommitsSince()),
$this->getOnSuccessObserver($input, $output, $accumulator)
);
$observers[] = $accumulator = new ResultAccumulator($config->getFilesToShow(), $config->getMinScoreToShow());
$observers[] = $processFactory = $this->getProcessFactory($config);
$observer = (new OnSuccessBuilder())->build($observers);
$this->processHandlerFactory->getProcessHandler($config)->process($filesFinder, $processFactory, $observer);
if ($processFactory instanceof CacheProcessFactory) {
$processFactory->writeCache();
}

return $accumulator;
}
Expand All @@ -172,31 +177,28 @@ private function getDirectoriesToScan(InputInterface $input, Config $config): ar
}

/**
* @param InputInterface $input Input.
* @param OutputInterface $output Output.
* @param ResultAccumulator $accumulator The object accumulating the results.
* @param Config $config The configuration object.
*/
private function getOnSuccessObserver(
InputInterface $input,
OutputInterface $output,
ResultAccumulator $accumulator
): OnSuccess {
$observer = new OnSuccessAccumulate($accumulator);

if (true === $input->getOption('progress')) {
$progressBar = new ProgressBar($output);
$progressBar->start();
$observer = new OnSuccessCollection($observer, new OnSuccessProgress($progressBar));
private function getProcessFactory(Config $config): ProcessFactory
{
$factory = new ConcreteProcessFactory($config->getVCS(), $config->getCommitsSince());

if (null !== $config->getCachePath()) {
$basePath = $config->getPath()
? \dirname($config->getPath())
: \getcwd();
$path = $config->getCachePath();
$factory = new CacheProcessFactory(FileHelper::toAbsolutePath($path, $basePath), $factory);
}

return $observer;
return $factory;
}

/**
* @param InputInterface $input Input.
* @param OutputInterface $output Output.
*/
private function displayLogo(InputInterface $input, OutputInterface $output): void
private function printLogo(InputInterface $input, OutputInterface $output): void
{
if ('text' !== $input->getOption('format') && empty($input->getOption('output'))) {
return;
Expand Down
9 changes: 9 additions & 0 deletions src/Configuration/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Config
private const FILES_TO_IGNORE = [];
private const FILE_EXTENSIONS_TO_PARSE = ['php'];
private const VCS = 'git';
private const CACHE_PATH = null;

/**
* @var array<string, mixed>
Expand Down Expand Up @@ -154,4 +155,12 @@ public function getVCS(): string
{
return $this->configuration['vcs'] ?? self::VCS;
}

/**
* Get the cache file path.
*/
public function getCachePath(): ?string
{
return $this->configuration['cachePath'] ?? self::CACHE_PATH;
}
}
16 changes: 16 additions & 0 deletions src/Configuration/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function validateConfigurationValues(array $configuration): void
$this->validateFilesToIgnore($configuration);
$this->validateFileExtensions($configuration);
$this->validateVCS($configuration);
$this->validateCachePath($configuration);
}

/**
Expand All @@ -33,6 +34,7 @@ private function validateDirectoriesToScan(array $configuration): void
return;
}

Assert::isArray($configuration['directoriesToScan'], 'Directories to scan should be an array of strings');
Assert::allString($configuration['directoriesToScan'], 'Directories to scan should be an array of strings');
}

Expand Down Expand Up @@ -94,6 +96,7 @@ private function validateFilesToIgnore(array $configuration): void
}

Assert::isArray($configuration['filesToIgnore'], 'Files to ignore should be an array of strings');
Assert::allString($configuration['filesToIgnore'], 'Files to ignore should be an array of strings');
}

/**
Expand All @@ -106,6 +109,7 @@ private function validateFileExtensions(array $configuration): void
}

Assert::isArray($configuration['fileExtensions'], 'File extensions should be an array of strings');
Assert::allString($configuration['fileExtensions'], 'File extensions should be an array of strings');
}

/**
Expand All @@ -119,4 +123,16 @@ private function validateVCS(array $configuration): void

Assert::string($configuration['vcs'], 'VCS should be a string');
}

/**
* @param array<mixed> $configuration The array containing the configuration values.
*/
private function validateCachePath(array $configuration): void
{
if (!isset($configuration['cachePath'])) {
return;
}

Assert::string($configuration['cachePath'], 'Cache path should be a string');
}
}
34 changes: 26 additions & 8 deletions src/File/FileHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

namespace Churn\File;

use InvalidArgumentException;
use Symfony\Component\Filesystem\Filesystem;

class FileHelper
{

Expand All @@ -14,20 +17,35 @@ class FileHelper
*/
public static function toAbsolutePath(string $path, string $basePath): string
{
$path = \trim($path);
return (new Filesystem())->isAbsolutePath($path)
? $path
: $basePath . '/' . $path;
}

if (0 === \strpos($path, '/')) {
return $path;
/**
* Check whether the path is writable and create the missing folders if needed.
*
* @param string $filePath The file path to check.
* @throws InvalidArgumentException If the path is invalid.
*/
public static function ensureFileIsWritable(string $filePath): void
{
if ('' === $filePath) {
throw new InvalidArgumentException('Path cannot be empty');
}

if ('\\' === $path[0] || (\strlen($path) >= 3 && \preg_match('#^[A-Z]\:[/\\\]#i', \substr($path, 0, 3)))) {
return $path;
if (\is_dir($filePath)) {
throw new InvalidArgumentException('Path cannot be a folder');
}

if (false !== \strpos($path, '://')) {
return $path;
if (!\is_file($filePath)) {
(new Filesystem())->mkdir(\dirname($filePath));

return;
}

return $basePath . '/' . $path;
if (!\is_writable($filePath)) {
throw new InvalidArgumentException('File is not writable');
}
}
}
Loading

0 comments on commit 4da142d

Please sign in to comment.