mirror of
https://github.com/php/pie.git
synced 2026-03-23 23:12:17 +01:00
Add a VendorCleanup process to remove all non-essential vendor-dir components
This commit is contained in:
89
src/ComposerIntegration/VendorCleanup.php
Normal file
89
src/ComposerIntegration/VendorCleanup.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Php\Pie\ComposerIntegration;
|
||||
|
||||
use Composer\Composer;
|
||||
use Composer\Util\Filesystem;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
use function array_filter;
|
||||
use function array_walk;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
use function scandir;
|
||||
use function sprintf;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
|
||||
/** @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks */
|
||||
class VendorCleanup
|
||||
{
|
||||
public function __construct(
|
||||
private readonly OutputInterface $output,
|
||||
private readonly Filesystem $filesystem,
|
||||
) {
|
||||
}
|
||||
|
||||
public function __invoke(Composer $composer): void
|
||||
{
|
||||
$vendorDir = (string) $composer->getConfig()->get('vendor-dir');
|
||||
$vendorContents = scandir($vendorDir);
|
||||
|
||||
if (! is_array($vendorContents)) {
|
||||
$this->output->writeln(
|
||||
sprintf(
|
||||
'<comment>Vendor directory (vendor-dir config) %s seemed invalid?/comment>',
|
||||
$vendorDir,
|
||||
),
|
||||
OutputInterface::VERBOSITY_VERY_VERBOSE,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$toRemove = array_filter(
|
||||
$vendorContents,
|
||||
static function (string $path): bool {
|
||||
return ! in_array(
|
||||
$path,
|
||||
[
|
||||
'.',
|
||||
'..',
|
||||
'autoload.php',
|
||||
'composer',
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
array_walk(
|
||||
$toRemove,
|
||||
function (string $pathToRemove) use ($vendorDir): void {
|
||||
$this->output->writeln(
|
||||
sprintf(
|
||||
'<comment>Removing: %s/%s</comment>',
|
||||
$vendorDir,
|
||||
$pathToRemove,
|
||||
),
|
||||
OutputInterface::VERBOSITY_VERY_VERBOSE,
|
||||
);
|
||||
|
||||
$fullPathToRemove = $vendorDir . DIRECTORY_SEPARATOR . $pathToRemove;
|
||||
|
||||
if ($this->filesystem->remove($fullPathToRemove)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->output->writeln(
|
||||
sprintf(
|
||||
'<comment>Warning: failed to remove %s</comment>',
|
||||
$fullPathToRemove,
|
||||
),
|
||||
OutputInterface::VERBOSITY_VERBOSE,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
0
test/assets/vendor-cleanup-dir/autoload.php
Normal file
0
test/assets/vendor-cleanup-dir/autoload.php
Normal file
0
test/assets/vendor-cleanup-dir/composer/dummy
Normal file
0
test/assets/vendor-cleanup-dir/composer/dummy
Normal file
0
test/assets/vendor-cleanup-dir/vendor1/dummy
Normal file
0
test/assets/vendor-cleanup-dir/vendor1/dummy
Normal file
0
test/assets/vendor-cleanup-dir/vendor2/dummy
Normal file
0
test/assets/vendor-cleanup-dir/vendor2/dummy
Normal file
82
test/unit/ComposerIntegration/VendorCleanupTest.php
Normal file
82
test/unit/ComposerIntegration/VendorCleanupTest.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Php\PieUnitTest\ComposerIntegration;
|
||||
|
||||
use Composer\Composer;
|
||||
use Composer\Config;
|
||||
use Composer\Util\Filesystem;
|
||||
use Php\Pie\ComposerIntegration\VendorCleanup;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
#[CoversClass(VendorCleanup::class)]
|
||||
final class VendorCleanupTest extends TestCase
|
||||
{
|
||||
private const VENDOR_DIR = __DIR__ . '/../../assets/vendor-cleanup-dir';
|
||||
|
||||
private OutputInterface&MockObject $output;
|
||||
private Filesystem&MockObject $filesystem;
|
||||
private VendorCleanup $vendorCleanup;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->output = $this->createMock(OutputInterface::class);
|
||||
$this->filesystem = $this->createMock(Filesystem::class);
|
||||
|
||||
$this->vendorCleanup = new VendorCleanup($this->output, $this->filesystem);
|
||||
}
|
||||
|
||||
private function composerWithVendorDirConfig(string $vendorDirConfig): Composer&MockObject
|
||||
{
|
||||
$config = $this->createMock(Config::class);
|
||||
$config->method('get')
|
||||
->with('vendor-dir')
|
||||
->willReturn($vendorDirConfig);
|
||||
|
||||
$composer = $this->createMock(Composer::class);
|
||||
$composer->method('getConfig')
|
||||
->willReturn($config);
|
||||
|
||||
return $composer;
|
||||
}
|
||||
|
||||
public function testInvalidVendorDirectory(): void
|
||||
{
|
||||
$this->output
|
||||
->expects(self::once())
|
||||
->method('writeln')
|
||||
->with(
|
||||
'<comment>Vendor directory (vendor-dir config) /path/that/does/not/exist seemed invalid?/comment>',
|
||||
OutputInterface::VERBOSITY_VERY_VERBOSE,
|
||||
);
|
||||
|
||||
($this->vendorCleanup)($this->composerWithVendorDirConfig('/path/that/does/not/exist'));
|
||||
}
|
||||
|
||||
public function testVendorDirIsCleaned(): void
|
||||
{
|
||||
$vendor1Removed = false;
|
||||
$vendor2Removed = false;
|
||||
|
||||
$this->filesystem
|
||||
->expects(self::exactly(2))
|
||||
->method('remove')
|
||||
->willReturnCallback(static function (string $path) use (&$vendor1Removed, &$vendor2Removed): bool {
|
||||
return match ($path) {
|
||||
self::VENDOR_DIR . '/vendor1' => $vendor1Removed = true,
|
||||
self::VENDOR_DIR . '/vendor2' => $vendor2Removed = true,
|
||||
};
|
||||
});
|
||||
|
||||
($this->vendorCleanup)($this->composerWithVendorDirConfig(self::VENDOR_DIR));
|
||||
|
||||
self::assertTrue($vendor1Removed);
|
||||
self::assertTrue($vendor2Removed);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user