diff --git a/psalm.xml b/psalm.xml
index b173a0333..37204efe1 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -32,5 +32,10 @@
+
+
+
+
+
diff --git a/src/Collection/FilesCollection.php b/src/Collection/FilesCollection.php
index 20aa29d45..f9c9d9905 100644
--- a/src/Collection/FilesCollection.php
+++ b/src/Collection/FilesCollection.php
@@ -7,26 +7,17 @@
use Closure;
use Doctrine\Common\Collections\ArrayCollection;
use GrumPHP\Util\Regex;
-use Symfony\Component\Finder\Comparator;
-use Symfony\Component\Finder\Iterator;
use SplFileInfo;
-use Symfony\Component\Finder\SplFileInfo as SymfonySplFileInfo;
use Traversable;
/**
- * @extends ArrayCollection
+ * @extends ArrayCollection
*/
class FilesCollection extends ArrayCollection
{
/**
- * @param \Traversable $iterator
- */
- public static function fromTraversable(\Traversable $iterator): FilesCollection
- {
- return new self(array_values(iterator_to_array($iterator)));
- }
-
- /**
+ * @deprecated use FilesCollectionFilter::name directly
+ *
* Adds a rule that files must match.
*
* You can use a pattern (delimited with / sign), a glob or a simple string.
@@ -39,10 +30,12 @@ public static function fromTraversable(\Traversable $iterator): FilesCollection
*/
public function name($pattern): self
{
- return $this->names([$pattern]);
+ return FilesCollectionFilter::name($this, $pattern);
}
/**
+ * @deprecated use FilesCollectionFilter::names directly
+ *
* Adds rules that files must match.
*
* You can use patterns (delimited with / sign), globs or simple strings.
@@ -53,12 +46,12 @@ public function name($pattern): self
*/
public function names(array $patterns): self
{
- $filter = new Iterator\FilenameFilterIterator($this->getIterator(), $patterns, []);
-
- return self::fromTraversable($filter);
+ return FilesCollectionFilter::names($this, $patterns);
}
/**
+ * @deprecated use FilesCollectionFilter::notName directly
+ *
* Adds rules that files must match.
*
* You can use patterns (delimited with / sign), globs or simple strings.
@@ -69,36 +62,36 @@ public function names(array $patterns): self
*/
public function notName(string $pattern): self
{
- $filter = new Iterator\FilenameFilterIterator($this->getIterator(), [], [$pattern]);
-
- return self::fromTraversable($filter);
+ return FilesCollectionFilter::notName($this, $pattern);
}
/**
+ * @deprecated use FilesCollectionFilter::path directly
+ *
* Filter by path.
*
* $collection->path('/^spec\/')
*/
public function path(string $pattern): self
{
- return $this->paths([$pattern]);
+ return FilesCollectionFilter::path($this, $pattern);
}
/**
+ * @deprecated use FilesCollectionFilter::paths directly
+ *
* Filter by paths.
*
* $collection->paths(['/^spec\/','/^src\/'])
- *
- * @psalm-suppress ArgumentTypeCoercion - Works on int, \SplFileInfo as well
*/
public function paths(array $patterns): self
{
- $filter = new Iterator\PathFilterIterator($this->getIterator(), $patterns, []);
-
- return self::fromTraversable($filter);
+ return FilesCollectionFilter::paths($this, $patterns);
}
/**
+ * @deprecated use FilesCollectionFilter::notPath directly
+ *
* Adds rules that filenames must not match.
*
* You can use patterns (delimited with / sign) or simple strings.
@@ -107,54 +100,50 @@ public function paths(array $patterns): self
*/
public function notPath(string $pattern): self
{
- return $this->notPaths([$pattern]);
+ return FilesCollectionFilter::notPath($this, $pattern);
}
/**
+ * @deprecated use FilesCollectionFilter::notPaths directly
+ *
* Adds rules that filenames must not match.
*
* You can use patterns (delimited with / sign) or simple strings.
*
* $collection->notPaths(['/^spec\/','/^src\/'])
- *
- * @psalm-suppress ArgumentTypeCoercion - Works on int, \SplFileInfo as well
*/
public function notPaths(array $pattern): self
{
- $filter = new Iterator\PathFilterIterator($this->getIterator(), [], $pattern);
-
- return self::fromTraversable($filter);
+ return FilesCollectionFilter::notPaths($this, $pattern);
}
+ /**
+ * @deprecated use FilesCollectionFilter::extensions directly
+ */
public function extensions(array $extensions): self
{
- if (!\count($extensions)) {
- return new self();
- }
-
- return $this->name(sprintf('/\.(%s)$/i', implode('|', $extensions)));
+ return FilesCollectionFilter::extensions($this, $extensions);
}
/**
+ * @deprecated use FilesCollectionFilter::size directly
+ *
* Adds tests for file sizes.
*
* $collection->filterBySize('> 10K');
* $collection->filterBySize('<= 1Ki');
* $collection->filterBySize(4);
*
- *
- *
* @see NumberComparator
*/
public function size(string $size): self
{
- $comparator = new Comparator\NumberComparator($size);
- $filter = new Iterator\SizeRangeFilterIterator($this->getIterator(), [$comparator]);
-
- return self::fromTraversable($filter);
+ return FilesCollectionFilter::size($this, $size);
}
/**
+ * @deprecated use FilesCollectionFilter::date directly
+ *
* Adds tests for file dates (last modified).
*
* The date must be something that strtotime() is able to parse:
@@ -164,26 +153,21 @@ public function size(string $size): self
* $collection->filterByDate('> now - 2 hours');
* $collection->filterByDate('>= 2005-10-15');
*
- *
- *
* @see DateComparator
*/
public function date(string $date): self
{
- $comparator = new Comparator\DateComparator($date);
- $filter = new Iterator\DateRangeFilterIterator($this->getIterator(), [$comparator]);
-
- return self::fromTraversable($filter);
+ return FilesCollectionFilter::date($this, $date);
}
/**
+ * @deprecated use FilesCollectionFilter::filter directly
+ *
* Filters the iterator with an anonymous function.
*
* The anonymous function receives a \SplFileInfo and must return false
* to remove files.
*
- *
- *
* @see CustomFilterIterator
*
* @psalm-suppress LessSpecificImplementedReturnType
@@ -192,26 +176,20 @@ public function date(string $date): self
*/
public function filter(Closure $p): self
{
- $filter = new Iterator\CustomFilterIterator($this->getIterator(), [$p]);
-
- return self::fromTraversable($filter);
+ return FilesCollectionFilter::filter($this, $p);
}
/**
+ * @deprecated use FilesCollectionFilter::filterByFileList directly
+ *
* @param Traversable $fileList
*/
- public function filterByFileList(Traversable $fileList): FilesCollection
+ public function filterByFileList(Traversable $fileList): self
{
- $allowedFiles = array_map(function (SplFileInfo $file) {
- return $file->getPathname();
- }, iterator_to_array($fileList));
-
- return $this->filter(function (SplFileInfo $file) use ($allowedFiles) {
- return \in_array($file->getPathname(), $allowedFiles, true);
- });
+ return FilesCollectionFilter::filterByFileList($this, $fileList);
}
- public function ensureFiles(self $files): FilesCollection
+ public function ensureFiles(self $files): self
{
$newFiles = new self($this->toArray());
@@ -224,49 +202,27 @@ public function ensureFiles(self $files): FilesCollection
return $newFiles;
}
- public function ignoreSymlinks(): FilesCollection
+ /**
+ * @deprecated use FilesCollectionFilter::ignoreSymlinks directly
+ */
+ public function ignoreSymlinks(): self
{
- return $this->filter(function (SplFileInfo $file) {
- return !$file->isLink();
- });
+ return FilesCollectionFilter::ignoreSymlinks($this);
}
- /**
- * SplFileInfo cannot be serialized. Therefor, we help PHP a bit.
- * This stuff is used for running tasks in parallel.
- */
public function __serialize(): array
{
- return $this->map(function (SplFileInfo $fileInfo): string {
- return $fileInfo instanceof SymfonySplFileInfo
- ? $fileInfo->getRelativePathname()
- : $fileInfo->getPathname();
- })->toArray();
+ return $this->toArray();
}
- /**
- * SplFileInfo cannot be serialized. Therefor, we help PHP a bit.
- * This stuff is used for running tasks in parallel.
- */
public function __unserialize(array $data): void
{
- $files = $data;
$this->clear();
- foreach ($files as $file) {
- $this->add(new SymfonySplFileInfo($file, dirname($file), $file));
+ foreach ($data as $path) {
+ $this->add($path);
}
}
- /**
- * Help Psalm out a bit:
- *
- * @return \ArrayIterator
- */
- public function getIterator(): \ArrayIterator
- {
- return new \ArrayIterator($this->toArray());
- }
-
public function toFileList(): string
{
return \implode(PHP_EOL, $this->toArray());
diff --git a/src/Collection/FilesCollectionFilter.php b/src/Collection/FilesCollectionFilter.php
new file mode 100644
index 000000000..1483c7478
--- /dev/null
+++ b/src/Collection/FilesCollectionFilter.php
@@ -0,0 +1,221 @@
+ 10K');
+ * FilesCollectionFilter::size($collection, '<= 1Ki');
+ * FilesCollectionFilter::size($collection, '4');
+ *
+ * @see NumberComparator
+ */
+ public static function size(FilesCollection $files, string $size): FilesCollection
+ {
+ $comparator = new Comparator\NumberComparator($size);
+ $filter = new Iterator\SizeRangeFilterIterator(self::toFileInfoIterator($files), [$comparator]);
+
+ return self::toFilesCollection($filter);
+ }
+
+ /**
+ * Adds tests for file dates (last modified).
+ *
+ * The date must be something that strtotime() is able to parse:
+ *
+ * FilesCollectionFilter::date($collection, 'since yesterday');
+ * FilesCollectionFilter::date($collection, 'until 2 days ago');
+ * FilesCollectionFilter::date($collection, '> now - 2 hours');
+ * FilesCollectionFilter::date($collection, '>= 2005-10-15');
+ *
+ * @see DateComparator
+ */
+ public static function date(FilesCollection $files, string $date): FilesCollection
+ {
+ $comparator = new Comparator\DateComparator($date);
+ $filter = new Iterator\DateRangeFilterIterator(self::toFileInfoIterator($files), [$comparator]);
+
+ return self::toFilesCollection($filter);
+ }
+
+ /**
+ * Filters the iterator with an anonymous function.
+ *
+ * @see CustomFilterIterator
+ */
+ public static function filter(FilesCollection $files, Closure $p): FilesCollection
+ {
+ $filter = new Iterator\CustomFilterIterator(self::toFileInfoIterator($files), [$p]);
+
+ return self::toFilesCollection($filter);
+ }
+
+ public static function ignoreSymlinks(FilesCollection $files): FilesCollection
+ {
+ return self::filter($files, static function (\SplFileInfo $file): bool {
+ return !$file->isLink();
+ });
+ }
+
+ /**
+ * Keeps only files whose pathname is present in the given file list.
+ *
+ * @param Traversable $fileList
+ */
+ public static function filterByFileList(FilesCollection $files, Traversable $fileList): FilesCollection
+ {
+ $allowedFiles = [];
+ foreach ($fileList as $file) {
+ $allowedFiles[$file->getPathname()] = true;
+ }
+
+ return self::filter($files, static function (\SplFileInfo $file) use ($allowedFiles): bool {
+ return isset($allowedFiles[$file->getPathname()]);
+ });
+ }
+
+ /**
+ * @return \Generator
+ */
+ private static function toFileInfoIterator(FilesCollection $files): \Generator
+ {
+ foreach ($files as $path) {
+ yield $path => new SymfonySplFileInfo($path, \dirname($path), $path);
+ }
+ }
+
+ /**
+ * @param Traversable $iterator
+ */
+ private static function toFilesCollection(Traversable $iterator): FilesCollection
+ {
+ $paths = [];
+ foreach ($iterator as $file) {
+ $paths[] = $file->getPathname();
+ }
+
+ return new FilesCollection($paths);
+ }
+}
diff --git a/src/Collection/ProcessArgumentsCollection.php b/src/Collection/ProcessArgumentsCollection.php
index 3a0f19db5..ad66e35ce 100644
--- a/src/Collection/ProcessArgumentsCollection.php
+++ b/src/Collection/ProcessArgumentsCollection.php
@@ -93,35 +93,18 @@ public function addRequiredArgument(string $argument, string $value): void
public function addFiles(FilesCollection $files): void
{
foreach ($files as $file) {
- $this->addFile($file);
+ $this->add($file);
}
}
- public function addFile(\SplFileInfo $file): void
- {
- $this->add($file->getPathname());
- }
-
public function addCommaSeparatedFiles(FilesCollection $files): void
{
- $paths = [];
-
- foreach ($files as $file) {
- $paths[] = $file->getPathname();
- }
-
- $this->add(implode(',', $paths));
+ $this->add(implode(',', $files->toArray()));
}
public function addArgumentWithCommaSeparatedFiles(string $argument, FilesCollection $files): void
{
- $paths = [];
-
- foreach ($files as $file) {
- $paths[] = $file->getPathname();
- }
-
- $this->add(sprintf($argument, implode(',', $paths)));
+ $this->add(sprintf($argument, implode(',', $files->toArray())));
}
public function addOptionalBooleanArgument(
diff --git a/src/Console/Command/Git/CommitMsgCommand.php b/src/Console/Command/Git/CommitMsgCommand.php
index 1f907fa82..77ac86745 100644
--- a/src/Console/Command/Git/CommitMsgCommand.php
+++ b/src/Console/Command/Git/CommitMsgCommand.php
@@ -119,6 +119,16 @@ public function execute(InputInterface $input, OutputInterface $output): int
$results = $this->taskRunner->run($context);
+ if ($this->io->isVerbose()) {
+ $this->io->write([
+ PHP_EOL,
+ sprintf(
+ 'Peak memory usage: %.1f MB',
+ (float) memory_get_peak_usage(true) / 1024.0 / 1024.0
+ )
+ ]);
+ }
+
return $results->isFailed() ? self::EXIT_CODE_NOK : self::EXIT_CODE_OK;
}
diff --git a/src/Console/Command/Git/PreCommitCommand.php b/src/Console/Command/Git/PreCommitCommand.php
index 2e00bba15..e0e5143e3 100644
--- a/src/Console/Command/Git/PreCommitCommand.php
+++ b/src/Console/Command/Git/PreCommitCommand.php
@@ -90,6 +90,16 @@ public function execute(InputInterface $input, OutputInterface $output): int
$results = $this->taskRunner->run($context);
+ if ($this->io->isVerbose()) {
+ $this->io->write([
+ PHP_EOL,
+ sprintf(
+ 'Peak memory usage: %.1f MB',
+ (float) memory_get_peak_usage(true) / 1024.0 / 1024.0
+ )
+ ]);
+ }
+
return $results->isFailed() ? self::EXIT_CODE_NOK : self::EXIT_CODE_OK;
}
diff --git a/src/Console/Command/RunCommand.php b/src/Console/Command/RunCommand.php
index e65ade451..03118d012 100644
--- a/src/Console/Command/RunCommand.php
+++ b/src/Console/Command/RunCommand.php
@@ -102,6 +102,16 @@ public function execute(InputInterface $input, OutputInterface $output): int
$results = $this->taskRunner->run($context);
+ if ($this->io->isVerbose()) {
+ $this->io->write([
+ PHP_EOL,
+ sprintf(
+ 'Peak memory usage: %.1f MB',
+ (float) memory_get_peak_usage(true) / 1024.0 / 1024.0
+ )
+ ]);
+ }
+
return $results->isFailed() ? self::EXIT_CODE_NOK : self::EXIT_CODE_OK;
}
diff --git a/src/Linter/Json/JsonLintError.php b/src/Linter/Json/JsonLintError.php
index c5f837829..f6bd3dd3e 100644
--- a/src/Linter/Json/JsonLintError.php
+++ b/src/Linter/Json/JsonLintError.php
@@ -10,9 +10,9 @@
class JsonLintError extends LintError
{
- public static function fromParsingException(SplFileInfo $file, ParsingException $exception): self
+ public static function fromParsingException(string $file, ParsingException $exception): self
{
- return new self(LintError::TYPE_ERROR, $exception->getMessage(), $file->getPathname(), 0);
+ return new self(LintError::TYPE_ERROR, $exception->getMessage(), $file, 0);
}
public function __toString(): string
diff --git a/src/Linter/Json/JsonLinter.php b/src/Linter/Json/JsonLinter.php
index 05da8106e..2bc969665 100644
--- a/src/Linter/Json/JsonLinter.php
+++ b/src/Linter/Json/JsonLinter.php
@@ -37,13 +37,13 @@ public function __construct(Filesystem $filesystem, JsonParser $jsonParser)
/**
* @throws ParsingException
*/
- public function lint(SplFileInfo $file): LintErrorsCollection
+ public function lint(string $file): LintErrorsCollection
{
$errors = new LintErrorsCollection();
$flags = $this->calculateFlags();
try {
- $json = $this->filesystem->readFromFileInfo($file);
+ $json = $this->filesystem->readPath($file);
$this->jsonParser->parse($json, $flags);
} catch (ParsingException $exception) {
$errors->add(JsonLintError::fromParsingException($file, $exception));
diff --git a/src/Linter/LinterInterface.php b/src/Linter/LinterInterface.php
index 7767548a7..1d9b43608 100644
--- a/src/Linter/LinterInterface.php
+++ b/src/Linter/LinterInterface.php
@@ -9,7 +9,7 @@
interface LinterInterface
{
- public function lint(SplFileInfo $file): LintErrorsCollection;
+ public function lint(string $file): LintErrorsCollection;
public function isInstalled(): bool;
}
diff --git a/src/Linter/Xml/XmlLinter.php b/src/Linter/Xml/XmlLinter.php
index 905bf4234..24b85aa56 100644
--- a/src/Linter/Xml/XmlLinter.php
+++ b/src/Linter/Xml/XmlLinter.php
@@ -33,7 +33,7 @@ class XmlLinter implements LinterInterface
*/
private $schemeValidation = false;
- public function lint(SplFileInfo $file): LintErrorsCollection
+ public function lint(string $file): LintErrorsCollection
{
$errors = new LintErrorsCollection();
$useInternalErrors = $this->useInternalXmlLoggin(true);
@@ -96,7 +96,7 @@ private function useInternalXmlLoggin(bool $useInternalErrors = false): bool
return libxml_use_internal_errors($useInternalErrors);
}
- private function loadDocument(SplFileInfo $file): ?DOMDocument
+ private function loadDocument(string $file): ?DOMDocument
{
$this->registerXmlStreamContext();
@@ -104,7 +104,7 @@ private function loadDocument(SplFileInfo $file): ?DOMDocument
$document->resolveExternals = $this->loadFromNet;
$document->preserveWhiteSpace = false;
$document->formatOutput = false;
- $loaded = $document->load($file->getPathname());
+ $loaded = $document->load($file);
return $loaded ? $document : null;
}
@@ -156,7 +156,7 @@ private function validateDTD(DOMDocument $document): bool
return $document->validate();
}
- private function validateInternalSchemes(SplFileInfo $file, DOMDocument $document): bool
+ private function validateInternalSchemes(string $file, DOMDocument $document): bool
{
$schemas = [];
$attributes = $document->documentElement->attributes;
@@ -187,13 +187,13 @@ private function validateInternalSchemes(SplFileInfo $file, DOMDocument $documen
/**
* @return null|string
*/
- private function locateScheme(SplFileInfo $xmlFile, string $scheme)
+ private function locateScheme(string $xmlFile, string $scheme)
{
if (filter_var($scheme, FILTER_VALIDATE_URL)) {
return $this->loadFromNet ? $scheme : null;
}
- $xmlFilePath = $xmlFile->getPath();
+ $xmlFilePath = \dirname($xmlFile);
$schemePath = empty($xmlFilePath) ? $scheme : rtrim($xmlFilePath, '/').DIRECTORY_SEPARATOR.$scheme;
$schemeFile = new SplFileInfo($schemePath);
diff --git a/src/Linter/Yaml/YamlLinter.php b/src/Linter/Yaml/YamlLinter.php
index 22bde7087..8c89e2526 100644
--- a/src/Linter/Yaml/YamlLinter.php
+++ b/src/Linter/Yaml/YamlLinter.php
@@ -56,15 +56,15 @@ public function __construct(Filesystem $filesystem)
$this->filesystem = $filesystem;
}
- public function lint(SplFileInfo $file): LintErrorsCollection
+ public function lint(string $file): LintErrorsCollection
{
$errors = new LintErrorsCollection();
try {
- $content = $this->filesystem->readFromFileInfo($file);
+ $content = $this->filesystem->readPath($file);
$this->parseYaml($content);
} catch (ParseException $exception) {
- $exception->setParsedFile($file->getPathname());
+ $exception->setParsedFile($file);
$errors[] = YamlLintError::fromParseException($exception);
}
diff --git a/src/Locator/ChangedFiles.php b/src/Locator/ChangedFiles.php
index 6f4294078..e539d53fd 100644
--- a/src/Locator/ChangedFiles.php
+++ b/src/Locator/ChangedFiles.php
@@ -63,7 +63,7 @@ private function parseFilesFromDiff(Diff $diff): FilesCollection
continue;
}
- $files[] = $fileObject;
+ $files[] = $fileObject->getPathname();
}
return new FilesCollection($files);
diff --git a/src/Locator/ListedFiles.php b/src/Locator/ListedFiles.php
index 760d6e173..9e4a3e8c1 100644
--- a/src/Locator/ListedFiles.php
+++ b/src/Locator/ListedFiles.php
@@ -26,8 +26,7 @@ public function locate(string $fileList): FilesCollection
$files = [];
foreach (array_filter($filePaths) as $file) {
- $relativeFile = $this->paths->makePathRelativeToProjectDir($file);
- $files[] = new SplFileInfo($relativeFile, dirname($relativeFile), $relativeFile);
+ $files[] = $this->paths->makePathRelativeToProjectDir($file);
}
return new FilesCollection($files);
diff --git a/src/Parser/ParserInterface.php b/src/Parser/ParserInterface.php
index 9648f0d5c..5d52e1039 100644
--- a/src/Parser/ParserInterface.php
+++ b/src/Parser/ParserInterface.php
@@ -9,7 +9,7 @@
interface ParserInterface
{
- public function parse(SplFileInfo $file): ParseErrorsCollection;
+ public function parse(string $file): ParseErrorsCollection;
public function isInstalled(): bool;
}
diff --git a/src/Parser/Php/PhpParser.php b/src/Parser/Php/PhpParser.php
index edd299371..9a6dae03b 100644
--- a/src/Parser/Php/PhpParser.php
+++ b/src/Parser/Php/PhpParser.php
@@ -54,19 +54,20 @@ public function setParserOptions(array $options): void
$this->parserOptions = $options;
}
- public function parse(SplFileInfo $file): ParseErrorsCollection
+ public function parse(string $file): ParseErrorsCollection
{
+ $fileObject = new SplFileInfo($file);
$errors = new ParseErrorsCollection();
- $context = new ParserContext($file, $errors);
+ $context = new ParserContext($fileObject, $errors);
$parser = $this->parserFactory->createFromOptions($this->parserOptions);
$traverser = $this->traverserFactory->createForTaskContext($this->parserOptions, $context);
try {
- $code = $this->filesystem->readFromFileInfo($file);
+ $code = $this->filesystem->readFromFileInfo($fileObject);
$stmts = $parser->parse($code);
$traverser->traverse((array) $stmts);
} catch (Error $e) {
- $errors->add(PhpParserError::fromParseException($e, $file->getRealPath()));
+ $errors->add(PhpParserError::fromParseException($e, $fileObject->getRealPath()));
}
return $errors;
diff --git a/src/Task/Composer.php b/src/Task/Composer.php
index e812ee8a7..26669f41f 100644
--- a/src/Task/Composer.php
+++ b/src/Task/Composer.php
@@ -102,9 +102,9 @@ public function run(ContextInterface $context): TaskResultInterface
return TaskResult::createPassed($this, $context);
}
- private function hasLocalRepository(SplFileInfo $composerFile): bool
+ private function hasLocalRepository(string $composerFile): bool
{
- $json = $this->filesystem->readFromFileInfo($composerFile);
+ $json = $this->filesystem->readPath($composerFile);
$package = json_decode($json, true);
if (!array_key_exists('repositories', $package)) {
diff --git a/src/Task/FileSize.php b/src/Task/FileSize.php
index fd85a3135..799a461c9 100644
--- a/src/Task/FileSize.php
+++ b/src/Task/FileSize.php
@@ -78,7 +78,7 @@ public function run(ContextInterface $context): TaskResultInterface
foreach ($files as $file) {
$errorMessage .= sprintf(
'- %s exceeded the maximum size of %s.'.PHP_EOL,
- $file->getFilename(),
+ $file,
$maxSize
);
}
diff --git a/src/Test/Task/AbstractTaskTestCase.php b/src/Test/Task/AbstractTaskTestCase.php
index e616536c3..d79c0b991 100644
--- a/src/Test/Task/AbstractTaskTestCase.php
+++ b/src/Test/Task/AbstractTaskTestCase.php
@@ -168,14 +168,7 @@ protected static function mockContext(string $class = ContextInterface::class, a
/** @var ContextInterface|ObjectProphecy $context */
$context = (new Prophet())->prophesize($class);
$context->getFiles()->willReturn(
- new FilesCollection(
- array_map(
- static function ($file): SplFileInfo {
- return $file instanceof SplFileInfo ? $file : new SplFileInfo($file, $file, $file);
- },
- $files
- )
- )
+ new FilesCollection($files)
);
return $context->reveal();
diff --git a/test/Unit/Linter/Xml/XmlLinterTest.php b/test/Unit/Linter/Xml/XmlLinterTest.php
index 9310db2d9..f2a3fdfb6 100644
--- a/test/Unit/Linter/Xml/XmlLinterTest.php
+++ b/test/Unit/Linter/Xml/XmlLinterTest.php
@@ -26,7 +26,7 @@ protected function setUp(): void
/**
* @param string $fixture
*
- * @return SplFileInfo
+ * @return string
*/
private function getFixture($fixture)
{
@@ -35,7 +35,7 @@ private function getFixture($fixture)
throw new RuntimeException(sprintf('The fixture %s could not be loaded!', $fixture));
}
- return $file;
+ return $file->getPathname();
}
/**
diff --git a/test/Unit/Task/ComposerTest.php b/test/Unit/Task/ComposerTest.php
index 3984ecfd7..5766e59d2 100644
--- a/test/Unit/Task/ComposerTest.php
+++ b/test/Unit/Task/ComposerTest.php
@@ -10,7 +10,6 @@
use GrumPHP\Task\TaskInterface;
use GrumPHP\Test\Task\AbstractExternalTaskTestCase;
use GrumPHP\Util\Filesystem;
-use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
class ComposerTest extends AbstractExternalTaskTestCase
@@ -83,7 +82,7 @@ function () {
self::mockContext(RunContext::class, ['composer.json']),
function () {
$this->mockProcessBuilder('composer', self::mockProcess(0));
- $this->filesystem->readFromFileInfo(Argument::which('getBasename', 'composer.json'))->willReturn(
+ $this->filesystem->readPath('composer.json')->willReturn(
json_encode([
'repositories' => [
['type' => 'path'],
@@ -100,7 +99,7 @@ function () {
self::mockContext(RunContext::class, ['composer.json']),
function () {
$this->mockProcessBuilder('composer', self::mockProcess(0));
- $this->filesystem->readFromFileInfo(Argument::which('getBasename', 'composer.json'))->willReturn(
+ $this->filesystem->readPath('composer.json')->willReturn(
json_encode([
'repositories' => [
['type' => 'path'],
@@ -129,7 +128,7 @@ function () {
self::mockContext(RunContext::class, ['composer.json']),
function () {
$this->mockProcessBuilder('composer', self::mockProcess(0));
- $this->filesystem->readFromFileInfo(Argument::which('getBasename', 'composer.json'))->willReturn(
+ $this->filesystem->readPath('composer.json')->willReturn(
json_encode([
'name' => 'my/package',
])
@@ -143,7 +142,7 @@ function () {
self::mockContext(RunContext::class, ['composer.json']),
function () {
$this->mockProcessBuilder('composer', self::mockProcess(0));
- $this->filesystem->readFromFileInfo(Argument::which('getBasename', 'composer.json'))->willReturn(
+ $this->filesystem->readPath('composer.json')->willReturn(
json_encode([
'repositories' => [
['type' => 'git'],
@@ -159,7 +158,7 @@ function () {
self::mockContext(RunContext::class, ['composer.json']),
function () {
$this->mockProcessBuilder('composer', self::mockProcess(0));
- $this->filesystem->readFromFileInfo(Argument::which('getBasename', 'composer.json'))->willReturn(
+ $this->filesystem->readPath('composer.json')->willReturn(
json_encode([
'repositories' => [
['packagist.org' => false],
diff --git a/test/Unit/Task/FileSizeTest.php b/test/Unit/Task/FileSizeTest.php
index 034907583..78064ae71 100644
--- a/test/Unit/Task/FileSizeTest.php
+++ b/test/Unit/Task/FileSizeTest.php
@@ -10,11 +10,12 @@
use GrumPHP\Task\FileSize;
use GrumPHP\Task\TaskInterface;
use GrumPHP\Test\Task\AbstractTaskTestCase;
-use Prophecy\Prophet;
-use Symfony\Component\Finder\SplFileInfo;
+use Symfony\Component\Filesystem\Filesystem;
class FileSizeTest extends AbstractTaskTestCase
{
+ protected static ?Filesystem $filesystem;
+
protected function provideTask(): TaskInterface
{
return new FileSize();
@@ -58,42 +59,41 @@ public static function provideRunContexts(): iterable
public static function provideFailsOnStuff(): iterable
{
+ $singleFile1 = self::fixture('single-invalid/file1.php', 6);
+ $singleFile2 = self::fixture('single-invalid/file2.php', 12);
yield 'single-invalid-filesizes' => [
[],
- self::mockContext(RunContext::class, [
- self::mockFile('file1.php', 6),
- self::mockFile('file2.php', 12),
- ]),
+ self::mockContext(RunContext::class, [$singleFile1, $singleFile2]),
function (array $options, ContextInterface $context) {
},
'Large files detected:'.PHP_EOL.
- '- file2.php exceeded the maximum size of 10M.'.PHP_EOL,
+ '- '. $singleFile2 .' exceeded the maximum size of 10M.'.PHP_EOL,
];
+
+ $invalidFile1 = self::fixture('invalid/file1.php', 12);
+ $invalidFile2 = self::fixture('invalid/file2.php', 12);
yield 'invalid-filesizes' => [
[],
- self::mockContext(RunContext::class, [
- self::mockFile('file1.php', 12),
- self::mockFile('file2.php', 12),
- ]),
+ self::mockContext(RunContext::class, [$invalidFile1, $invalidFile2]),
function (array $options, ContextInterface $context) {
},
'Large files detected:'.PHP_EOL.
- '- file1.php exceeded the maximum size of 10M.'.PHP_EOL.
- '- file2.php exceeded the maximum size of 10M.'.PHP_EOL,
+ '- '.$invalidFile1.' exceeded the maximum size of 10M.'.PHP_EOL.
+ '- '.$invalidFile2.' exceeded the maximum size of 10M.'.PHP_EOL,
];
+
+ $customFile1 = self::fixture('invalid-custom/file1.php', 12);
+ $customFile2 = self::fixture('invalid-custom/file2.php', 12);
yield 'invalid-filesizes-custom-size' => [
[
'max_size' => '5M'
],
- self::mockContext(RunContext::class, [
- self::mockFile('file1.php', 12),
- self::mockFile('file2.php', 12),
- ]),
+ self::mockContext(RunContext::class, [$customFile1, $customFile2]),
function (array $options, ContextInterface $context) {
},
'Large files detected:'.PHP_EOL.
- '- file1.php exceeded the maximum size of 5M.'.PHP_EOL.
- '- file2.php exceeded the maximum size of 5M.'.PHP_EOL,
+ '- '.$customFile1.' exceeded the maximum size of 5M.'.PHP_EOL.
+ '- '.$customFile2.' exceeded the maximum size of 5M.'.PHP_EOL,
];
}
@@ -102,8 +102,8 @@ public static function providePassesOnStuff(): iterable
yield 'valid-filesizes' => [
[],
self::mockContext(RunContext::class, [
- self::mockFile('file1.php', 6),
- self::mockFile('file2.php', 6),
+ self::fixture('valid/file1.php', 6),
+ self::fixture('valid/file2.php', 6),
]),
function () {
}
@@ -113,14 +113,14 @@ function () {
'ignore_patterns' => ['test/'],
],
self::mockContext(RunContext::class, [
- self::mockFile('test/file.php', 2323, true),
+ self::fixture('ignored/test/file.php', 12),
]),
function () {}
];
yield 'dont-validate-symlinks' => [
[],
self::mockContext(RunContext::class, [
- self::mockFile('file.php', 2323, true),
+ self::fixtureSymlink('symlinks/file.php', 12),
]),
function () {}
];
@@ -136,16 +136,51 @@ function () {
];
}
- private static function mockFile(string $file, int $megaBytes, $isSymlink = false): SplFileInfo
+ public static function tearDownAfterClass(): void
+ {
+ self::filesystem()->remove(self::fixtureRoot());
+ }
+
+ private static function fixture(string $relative, int $sizeMB): string
+ {
+ $path = self::fixtureRoot() . '/' . $relative;
+
+ self::filesystem()->mkdir(\dirname($path));
+ self::createFileWithContent($path, $sizeMB);
+
+ return $path;
+ }
+
+ private static function fixtureSymlink(string $relative, int $sizeMB): string
+ {
+ $linkPath = self::fixtureRoot() . '/' . $relative;
+ self::filesystem()->mkdir(\dirname($linkPath));
+
+ $targetPath = \dirname($linkPath) . '/_target_' . \basename($linkPath);
+ self::createFileWithContent($targetPath, $sizeMB);
+
+ self::filesystem()->remove($linkPath);
+ self::filesystem()->symlink($targetPath, $linkPath);
+
+ return $linkPath;
+ }
+
+ private static function createFileWithContent(string $path, int $sizeMB): void
{
- /** @var SplFileInfo $mock */
- $mock = (new Prophet())->prophesize(SplFileInfo::class);
- $mock->getFilename()->willReturn($file);
- $mock->getRelativePathname()->willReturn($file);
- $mock->isLink()->willReturn($isSymlink);
- $mock->isFile()->willReturn(true);
- $mock->getSize()->willReturn($megaBytes * 1024 * 1024);
-
- return $mock->reveal();
+ $fh = \fopen($path, 'w');
+ \ftruncate($fh, $sizeMB * 1024 * 1024);
+ \fclose($fh);
+ }
+
+ private static function fixtureRoot(): string
+ {
+ return \sys_get_temp_dir() . '/grumphp-filesize-test';
+ }
+
+ private static function filesystem(): Filesystem
+ {
+ self::$filesystem ??= new Filesystem();
+
+ return self::$filesystem;
}
}
diff --git a/test/fixtures/e2e/tasks/ValidatePathsTask.php b/test/fixtures/e2e/tasks/ValidatePathsTask.php
index a995b150d..3f2e88282 100644
--- a/test/fixtures/e2e/tasks/ValidatePathsTask.php
+++ b/test/fixtures/e2e/tasks/ValidatePathsTask.php
@@ -55,9 +55,7 @@ public function canRunInContext(ContextInterface $context): bool
public function run(ContextInterface $context): TaskResultInterface
{
- $contextFiles = $context->getFiles()->map(function(\SplFileInfo $file) {
- return $file->getPathname();
- })->toArray();
+ $contextFiles = $context->getFiles()->toArray();
try {
Assert::assertEquals($this->availableFiles, $contextFiles);