1
0
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:
James Titcumb
2025-01-07 10:19:36 +00:00
parent dab2173868
commit 66f8d9e2c0
6 changed files with 171 additions and 0 deletions

View 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,
);
},
);
}
}

View 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);
}
}