diff --git a/src/Composer/Artifact/ComposerFile.php b/src/Composer/Artifact/ComposerFile.php index f02ff555e..6a4346eb8 100644 --- a/src/Composer/Artifact/ComposerFile.php +++ b/src/Composer/Artifact/ComposerFile.php @@ -21,4 +21,20 @@ public function __construct( public array $decodedContents, ) { } + + public function toComposerJson(): DecodedComposerJson + { + return new DecodedComposerJson( + $this->path, + $this->decodedContents, + ); + } + + public function toComposerLock(): DecodedComposerLock + { + return new DecodedComposerLock( + $this->path, + $this->decodedContents, + ); + } } diff --git a/src/Composer/Artifact/ComposerFiles.php b/src/Composer/Artifact/ComposerFiles.php index 9234f0f65..aa65eb285 100644 --- a/src/Composer/Artifact/ComposerFiles.php +++ b/src/Composer/Artifact/ComposerFiles.php @@ -21,18 +21,18 @@ final readonly class ComposerFiles { public function __construct( - private ?ComposerFile $composerJson = null, - private ?ComposerFile $composerLock = null, + private ?DecodedComposerJson $composerJson = null, + private ?DecodedComposerLock $composerLock = null, private ?ComposerFile $installedJson = null, ) { } - public function getComposerJson(): ?ComposerFile + public function getComposerJson(): ?DecodedComposerJson { return $this->composerJson; } - public function getComposerLock(): ?ComposerFile + public function getComposerLock(): ?DecodedComposerLock { return $this->composerLock; } @@ -50,7 +50,7 @@ public function getPaths(): array return array_values( array_filter( array_map( - static fn (?ComposerFile $file): ?string => $file?->path, + static fn (null|ComposerFile|DecodedComposerJson|DecodedComposerLock $file): ?string => $file?->path, [$this->composerJson, $this->composerLock, $this->installedJson], ), ), diff --git a/src/Composer/Artifact/DecodedComposerJson.php b/src/Composer/Artifact/DecodedComposerJson.php index 47d084a36..5de137422 100644 --- a/src/Composer/Artifact/DecodedComposerJson.php +++ b/src/Composer/Artifact/DecodedComposerJson.php @@ -27,8 +27,10 @@ /** * @param array $decodedContents Decoded JSON contents of the `composer.json` file */ - public function __construct(private array $decodedContents) - { + public function __construct( + public string $path, + public array $decodedContents, + ) { } public function getRequiredPhpVersion(): ?string diff --git a/src/Composer/Artifact/DecodedComposerLock.php b/src/Composer/Artifact/DecodedComposerLock.php index fe1eef0c8..c93dac583 100644 --- a/src/Composer/Artifact/DecodedComposerLock.php +++ b/src/Composer/Artifact/DecodedComposerLock.php @@ -27,8 +27,10 @@ /** * @param array $decodedContents Decoded JSON contents of the `composer.lock` file */ - public function __construct(private array $decodedContents) - { + public function __construct( + public string $path, + public array $decodedContents, + ) { } public function isEmpty(): bool diff --git a/src/Configuration/Configuration.php b/src/Configuration/Configuration.php index 9fbccd78a..1a56c3843 100644 --- a/src/Configuration/Configuration.php +++ b/src/Configuration/Configuration.php @@ -265,8 +265,8 @@ public static function create(?string $file, stdClass $raw): self $devPackages = ComposerConfiguration::retrieveDevPackages( $basePath, - new DecodedComposerJson($composerFiles->getComposerJson()?->decodedContents ?? []), - new DecodedComposerLock($composerFiles->getComposerLock()?->decodedContents ?? []), + $composerFiles->getComposerJson(), + $composerFiles->getComposerLock(), $excludeDevPackages, ); @@ -422,8 +422,8 @@ private function __construct( private readonly ?string $file, private readonly string $alias, private readonly string $basePath, - private readonly ?ComposerFile $composerJson, - private readonly ?ComposerFile $composerLock, + private readonly ?DecodedComposerJson $composerJson, + private readonly ?DecodedComposerLock $composerLock, private readonly array $files, private readonly array $binaryFiles, private readonly bool $autodiscoveredFiles, @@ -495,12 +495,12 @@ public function getBasePath(): string return $this->basePath; } - public function getComposerJson(): ?ComposerFile + public function getComposerJson(): ?DecodedComposerJson { return $this->composerJson; } - public function getComposerLock(): ?ComposerFile + public function getComposerLock(): ?DecodedComposerLock { return $this->composerLock; } @@ -1808,9 +1808,12 @@ private static function retrieveMainScriptContents(?string $mainScriptPath): ?st private static function retrieveComposerFiles(string $basePath): ComposerFiles { + $composerJson = self::retrieveComposerFile(Path::canonicalize($basePath.'/composer.json')); + $composerLock = self::retrieveComposerFile(Path::canonicalize($basePath.'/composer.lock')); + return new ComposerFiles( - self::retrieveComposerFile(Path::canonicalize($basePath.'/composer.json')), - self::retrieveComposerFile(Path::canonicalize($basePath.'/composer.lock')), + $composerJson?->toComposerJson(), + $composerLock?->toComposerLock(), self::retrieveComposerFile(Path::canonicalize($basePath.'/vendor/composer/installed.json')), ); } diff --git a/src/Console/Command/Compile.php b/src/Console/Command/Compile.php index 53b936d66..631efe526 100644 --- a/src/Console/Command/Compile.php +++ b/src/Console/Command/Compile.php @@ -28,8 +28,6 @@ use Humbug\PhpScoper\Symbol\SymbolsRegistry; use KevinGH\Box\Box; use KevinGH\Box\Compactor\Compactor; -use KevinGH\Box\Composer\Artifact\DecodedComposerJson; -use KevinGH\Box\Composer\Artifact\DecodedComposerLock; use KevinGH\Box\Composer\ComposerConfiguration; use KevinGH\Box\Composer\ComposerOrchestrator; use KevinGH\Box\Composer\ComposerProcessFactory; @@ -567,8 +565,8 @@ private static function registerRequirementsChecker(Configuration $config, Box $ ); $checkFiles = RequirementsDumper::dump( - new DecodedComposerJson($config->getComposerJson()?->decodedContents ?? []), - new DecodedComposerLock($config->getComposerLock()?->decodedContents ?? []), + $config->getComposerJson(), + $config->getComposerLock(), $config->getCompressionAlgorithm(), ); @@ -682,7 +680,7 @@ private static function checkComposerFiles(Box $box, Configuration $config, Comp if ($config->excludeComposerFiles()) { $box->removeComposerArtefacts( ComposerConfiguration::retrieveVendorDir( - new DecodedComposerJson($config->getComposerJson()?->decodedContents ?? []), + $config->getComposerJson(), ), ); } diff --git a/src/RequirementChecker/RequirementsDumper.php b/src/RequirementChecker/RequirementsDumper.php index f8b1700b3..3c57e22c3 100644 --- a/src/RequirementChecker/RequirementsDumper.php +++ b/src/RequirementChecker/RequirementsDumper.php @@ -41,16 +41,16 @@ final class RequirementsDumper * @return list */ public static function dump( - DecodedComposerJson $composerJson, - DecodedComposerLock $composerLock, + ?DecodedComposerJson $composerJson, + ?DecodedComposerLock $composerLock, CompressionAlgorithm $compressionAlgorithm, ): array { Assert::directory(self::REQUIREMENT_CHECKER_PATH, 'Expected the requirement checker to have been dumped'); $filesWithContents = [ self::dumpRequirementsConfig( - $composerJson, - $composerLock, + $composerJson ?? new DecodedComposerJson('', []), + $composerLock ?? new DecodedComposerLock('', []), $compressionAlgorithm, ), ]; diff --git a/tests/Benchmark/AppRequirementFactoryBench.php b/tests/Benchmark/AppRequirementFactoryBench.php index c5750cf97..d1a162317 100644 --- a/tests/Benchmark/AppRequirementFactoryBench.php +++ b/tests/Benchmark/AppRequirementFactoryBench.php @@ -39,12 +39,14 @@ public function bench(): void { AppRequirementsFactory::create( new DecodedComposerJson( + '', json_decode( file_get_contents(self::FIXTURES.'/composer.json'), true, ), ), new DecodedComposerLock( + '', json_decode( file_get_contents(self::FIXTURES.'/composer.lock'), true, diff --git a/tests/Composer/Artifact/ComposerFilesTest.php b/tests/Composer/Artifact/ComposerFilesTest.php index 682688752..b3434df5d 100644 --- a/tests/Composer/Artifact/ComposerFilesTest.php +++ b/tests/Composer/Artifact/ComposerFilesTest.php @@ -28,8 +28,8 @@ class ComposerFilesTest extends TestCase #[DataProvider('validInstantiatorsProvider')] public function test_it_can_be_created( Closure $create, - ?ComposerFile $expectedComposerJson, - ?ComposerFile $expectedComposerLock, + ?DecodedComposerJson $expectedComposerJson, + ?DecodedComposerLock $expectedComposerLock, ?ComposerFile $expectedInstalledJson, array $expectedPaths, ): void { @@ -48,8 +48,8 @@ public function test_it_can_be_created( public static function validInstantiatorsProvider(): iterable { yield (static function (): array { - $json = new ComposerFile('path/to/composer.json', ['name' => 'composer.json']); - $lock = new ComposerFile('path/to/composer.lock', ['name' => 'composer.lock']); + $json = new DecodedComposerJson('path/to/composer.json', ['name' => 'composer.json']); + $lock = new DecodedComposerLock('path/to/composer.lock', ['name' => 'composer.lock']); $installed = new ComposerFile('path/to/installed.json', ['name' => 'installed.json']); return [ @@ -66,7 +66,7 @@ public static function validInstantiatorsProvider(): iterable })(); yield (static function (): array { - $json = new ComposerFile('path/to/composer.json', ['name' => 'composer.json']); + $json = new DecodedComposerJson('path/to/composer.json', ['name' => 'composer.json']); $lock = null; $installed = new ComposerFile('path/to/installed.json', ['name' => 'installed.json']); diff --git a/tests/Composer/Artifact/DecodedComposerJsonTest.php b/tests/Composer/Artifact/DecodedComposerJsonTest.php index 3261380d8..37839f6f3 100644 --- a/tests/Composer/Artifact/DecodedComposerJsonTest.php +++ b/tests/Composer/Artifact/DecodedComposerJsonTest.php @@ -35,7 +35,10 @@ public function test_it_can_interpret_a_decoded_composer_json_file( array $expectedRequiredItems, array $expectedConflictingExtensions, ): void { - $actual = new DecodedComposerJson(json_decode($composerJsonContents, true)); + $actual = new DecodedComposerJson( + '', + json_decode($composerJsonContents, true), + ); self::assertStateIs( $actual, diff --git a/tests/Composer/Artifact/DecodedComposerLockTest.php b/tests/Composer/Artifact/DecodedComposerLockTest.php index fa3dad2b4..afab9a3c0 100644 --- a/tests/Composer/Artifact/DecodedComposerLockTest.php +++ b/tests/Composer/Artifact/DecodedComposerLockTest.php @@ -36,7 +36,10 @@ public function test_it_can_interpret_a_decoded_composer_json_file( array $expectedPlatformExtensions, array $expectedPackages, ): void { - $actual = new DecodedComposerLock(json_decode($composerJsonContents, true)); + $actual = new DecodedComposerLock( + '', + json_decode($composerJsonContents, true), + ); self::assertStateIs( $actual, diff --git a/tests/Composer/ComposerConfigurationTest.php b/tests/Composer/ComposerConfigurationTest.php index b550e4d85..27eca2e49 100644 --- a/tests/Composer/ComposerConfigurationTest.php +++ b/tests/Composer/ComposerConfigurationTest.php @@ -241,7 +241,7 @@ public function test_it_returns_an_empty_list_when_trying_to_retrieve_the_list_o [], ComposerConfiguration::retrieveDevPackages( $this->tmp, - new DecodedComposerJson([]), + new DecodedComposerJson('', []), null, $excludeDevPackages, ), @@ -251,8 +251,8 @@ public function test_it_returns_an_empty_list_when_trying_to_retrieve_the_list_o #[DataProvider('excludeDevFilesSettingProvider')] public function test_it_can_retrieve_the_dev_packages_found_in_the_lock_file(): void { - $composerJson = new DecodedComposerJson([]); - $composerLock = new DecodedComposerLock(json_decode(self::COMPOSER_LOCK_SAMPLE, true)); + $composerJson = new DecodedComposerJson('', []); + $composerLock = self::createComposerLockSample(); FS::mkdir('vendor/bamarni/composer-bin-plugin'); FS::mkdir('vendor/doctrine/instantiator'); @@ -279,8 +279,8 @@ public function test_it_can_retrieve_the_dev_packages_found_in_the_lock_file(): public function test_it_can_retrieve_the_dev_packages_found_in_the_lock_file_2(): void { - $composerJson = new DecodedComposerJson(['config' => []]); - $composerLock = new DecodedComposerLock(json_decode(self::COMPOSER_LOCK_SAMPLE, true)); + $composerJson = new DecodedComposerJson('', ['config' => []]); + $composerLock = self::createComposerLockSample(); FS::mkdir('vendor/bamarni/composer-bin-plugin'); FS::mkdir('vendor/doctrine/instantiator'); @@ -307,8 +307,8 @@ public function test_it_can_retrieve_the_dev_packages_found_in_the_lock_file_2() public function test_it_ignores_non_existent_dev_packages_found_in_the_lock_file(): void { - $composerJson = new DecodedComposerJson([]); - $composerLock = new DecodedComposerLock(json_decode(self::COMPOSER_LOCK_SAMPLE, true)); + $composerJson = new DecodedComposerJson('', []); + $composerLock = self::createComposerLockSample(); FS::mkdir('vendor/bamarni/composer-bin-plugin'); // Doctrine Instantiator vendor does not exists @@ -334,12 +334,15 @@ public function test_it_ignores_non_existent_dev_packages_found_in_the_lock_file public function test_it_can_retrieve_the_dev_packages_found_in_the_lock_file_in_a_custom_vendor_directory(): void { - $composerJson = new DecodedComposerJson([ - 'config' => [ - 'vendor-dir' => 'custom-vendor', + $composerJson = new DecodedComposerJson( + '', + [ + 'config' => [ + 'vendor-dir' => 'custom-vendor', + ], ], - ]); - $composerLock = new DecodedComposerLock(json_decode(self::COMPOSER_LOCK_SAMPLE, true)); + ); + $composerLock = self::createComposerLockSample(); FS::mkdir('custom-vendor/bamarni/composer-bin-plugin'); FS::mkdir('vendor/doctrine/instantiator'); // Wrong directory @@ -370,109 +373,112 @@ public function test_it_can_retrieve_the_dev_packages_found_in_the_lock_file_in_ public function test_it_can_retrieve_the_dev_packages_found_in_the_lock_file_even_if_no_dev_package_is_registered(): void { - $composerJson = new DecodedComposerJson([]); - - $composerLock = new DecodedComposerLock(json_decode( - <<<'JSON' - { - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "content-hash": "c9ae998336c74a11e44be3255b6abceb", - "packages": [ - { - "name": "amphp/amp", - "version": "v2.0.6", - "source": { - "type": "git", - "url": "https://github.com/amphp/amp.git", - "reference": "4a742beb59615f36ed998e2dc210e36576e44c44" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/4a742beb59615f36ed998e2dc210e36576e44c44", - "reference": "4a742beb59615f36ed998e2dc210e36576e44c44", - "shasum": "" - }, - "require": { - "php": ">=7" - }, - "require-dev": { - "amphp/phpunit-util": "^1", - "friendsofphp/php-cs-fixer": "^2.3", - "phpstan/phpstan": "^0.8.5", - "phpunit/phpunit": "^6.0.9", - "react/promise": "^2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Amp\\": "lib" + $composerJson = new DecodedComposerJson('', []); + + $composerLock = new DecodedComposerLock( + '', + json_decode( + <<<'JSON' + { + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "content-hash": "c9ae998336c74a11e44be3255b6abceb", + "packages": [ + { + "name": "amphp/amp", + "version": "v2.0.6", + "source": { + "type": "git", + "url": "https://github.com/amphp/amp.git", + "reference": "4a742beb59615f36ed998e2dc210e36576e44c44" }, - "files": [ - "lib/functions.php", - "lib/Internal/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bob Weinand", - "email": "bobwei9@hotmail.com" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/amp/zipball/4a742beb59615f36ed998e2dc210e36576e44c44", + "reference": "4a742beb59615f36ed998e2dc210e36576e44c44", + "shasum": "" }, - { - "name": "Niklas Keller", - "email": "me@kelunik.com" + "require": { + "php": ">=7" }, - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" + "require-dev": { + "amphp/phpunit-util": "^1", + "friendsofphp/php-cs-fixer": "^2.3", + "phpstan/phpstan": "^0.8.5", + "phpunit/phpunit": "^6.0.9", + "react/promise": "^2" }, - { - "name": "Aaron Piotrowski", - "email": "aaron@trowski.com" - } - ], - "description": "A non-blocking concurrency framework for PHP applications.", - "homepage": "http://amphp.org/amp", - "keywords": [ - "async", - "asynchronous", - "awaitable", - "concurrency", - "event", - "event-loop", - "future", - "non-blocking", - "promise" - ], - "time": "2018-01-27T19:18:05+00:00" - } - ], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": "^7.1", - "ext-phar": "*" - }, - "platform-dev": [] - } - JSON, - true, - )); + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Amp\\": "lib" + }, + "files": [ + "lib/functions.php", + "lib/Internal/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + } + ], + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "http://amphp.org/amp", + "keywords": [ + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "time": "2018-01-27T19:18:05+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.1", + "ext-phar": "*" + }, + "platform-dev": [] + } + JSON, + true, + ), + ); FS::mkdir('custom-vendor/bamarni/composer-bin-plugin'); FS::mkdir('vendor/doctrine/instantiator'); // Wrong directory @@ -518,22 +524,33 @@ public static function vendorDirProvider(): iterable ]; yield 'no custom vendor-dir' => [ - new DecodedComposerJson([]), + new DecodedComposerJson('', []), 'vendor', ]; yield 'no custom vendor-dir in config' => [ - new DecodedComposerJson(['config' => ['platform' => ['php' => '7.2']]]), + new DecodedComposerJson('', ['config' => ['platform' => ['php' => '7.2']]]), 'vendor', ]; yield 'custom vendor-dir' => [ - new DecodedComposerJson([ - 'config' => [ - 'vendor-dir' => 'custom-vendor', + new DecodedComposerJson( + '', + [ + 'config' => [ + 'vendor-dir' => 'custom-vendor', + ], ], - ]), + ), 'custom-vendor', ]; } + + private static function createComposerLockSample(): DecodedComposerLock + { + return new DecodedComposerLock( + '', + json_decode(self::COMPOSER_LOCK_SAMPLE, true), + ); + } } diff --git a/tests/Configuration/ConfigurationTest.php b/tests/Configuration/ConfigurationTest.php index b2de07d04..809a312ab 100644 --- a/tests/Configuration/ConfigurationTest.php +++ b/tests/Configuration/ConfigurationTest.php @@ -22,7 +22,8 @@ use KevinGH\Box\Compactor\NullCompactor; use KevinGH\Box\Compactor\Php; use KevinGH\Box\Compactor\PhpScoper; -use KevinGH\Box\Composer\Artifact\ComposerFile; +use KevinGH\Box\Composer\Artifact\DecodedComposerJson; +use KevinGH\Box\Composer\Artifact\DecodedComposerLock; use KevinGH\Box\Json\JsonValidationException; use KevinGH\Box\MapFile; use KevinGH\Box\Phar\CompressionAlgorithm; @@ -325,14 +326,14 @@ public function test_it_attempts_to_get_and_decode_the_json_and_lock_files( $expectedJson = null === $expectedJsonPath ? null - : new ComposerFile( + : new DecodedComposerJson( $this->tmp.DIRECTORY_SEPARATOR.$expectedJsonPath, $expectedJsonContents ?? [], ); $expectedLock = null === $expectedLockPath ? null - : new ComposerFile( + : new DecodedComposerLock( $this->tmp.DIRECTORY_SEPARATOR.$expectedLockPath, $expectedLockContents ?? [], ); diff --git a/tests/RequirementChecker/AppRequirementsFactoryTest.php b/tests/RequirementChecker/AppRequirementsFactoryTest.php index 56457c921..072c92cc7 100644 --- a/tests/RequirementChecker/AppRequirementsFactoryTest.php +++ b/tests/RequirementChecker/AppRequirementsFactoryTest.php @@ -36,9 +36,22 @@ public function test_it_can_generate_and_serialized_requirements_from_a_composer CompressionAlgorithm $compressionAlgorithm, array $expected, ): void { + $composerJson = new DecodedComposerJson( + '', + null === $composerJsonContents + ? [] + : json_decode($composerJsonContents, true, flags: JSON_THROW_ON_ERROR), + ); + $composerLock = new DecodedComposerLock( + '', + null === $composerLockContents + ? [] + : json_decode($composerLockContents, true, flags: JSON_THROW_ON_ERROR), + ); + $actual = AppRequirementsFactory::create( - new DecodedComposerJson(null === $composerJsonContents ? [] : json_decode($composerJsonContents, true, flags: JSON_THROW_ON_ERROR)), - new DecodedComposerLock(null === $composerLockContents ? [] : json_decode($composerLockContents, true, flags: JSON_THROW_ON_ERROR)), + $composerJson, + $composerLock, $compressionAlgorithm, ); diff --git a/tests/RequirementChecker/RequirementsDumperTest.php b/tests/RequirementChecker/RequirementsDumperTest.php index 402953d8b..41fe92288 100644 --- a/tests/RequirementChecker/RequirementsDumperTest.php +++ b/tests/RequirementChecker/RequirementsDumperTest.php @@ -102,8 +102,8 @@ public function test_it_dumps_the_requirement_checker_files( public static function jsonAndLockContentsProvider(): iterable { yield [ - new DecodedComposerJson([]), - new DecodedComposerLock([]), + new DecodedComposerJson('', []), + new DecodedComposerLock('', []), CompressionAlgorithm::NONE, <<<'PHP' [ - [ - 'name' => 'acme/foo', - 'require' => [ - 'php' => '^7.4', - 'ext-json' => '*', + new DecodedComposerJson('', []), + new DecodedComposerLock( + '', + [ + 'packages' => [ + [ + 'name' => 'acme/foo', + 'require' => [ + 'php' => '^7.4', + 'ext-json' => '*', + ], ], ], ], - ]), + ), CompressionAlgorithm::GZ, <<<'PHP'