diff --git a/src/Console/Command/PurgeCommand.php b/src/Console/Command/PurgeCommand.php
index cdc3f02..bbef3d2 100644
--- a/src/Console/Command/PurgeCommand.php
+++ b/src/Console/Command/PurgeCommand.php
@@ -16,7 +16,6 @@ namespace Composer\Satis\Console\Command;
use Composer\Command\BaseCommand;
use Composer\Json\JsonFile;
use Composer\Satis\PackageSelection\PackageSelection;
-use Composer\Util\Filesystem;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -128,24 +127,9 @@ class PurgeCommand extends BaseCommand
return 0;
}
- $filesystem = new Filesystem();
foreach ($unreferenced as $currentFile) {
if (!$dryRun) {
- try {
- $filesystem->unlink($currentFile->getPathname());
- } catch (\RuntimeException $exception) {
- // Another process, e.g. a concurrent build or purge, may have removed the archive already.
- if (file_exists($currentFile->getPathname())) {
- throw $exception;
- }
-
- $output->writeln(sprintf(
- 'Skipped missing archive: %s',
- $currentFile->getRelativePathname()
- ));
-
- continue;
- }
+ unlink($currentFile->getPathname());
}
$output->writeln(sprintf(
@@ -182,7 +166,7 @@ class PurgeCommand extends BaseCommand
if (is_dir($path)
&& $depth > 0
&& $this->removeEmptyDirectories($output, $path, $depth - 1)
- && @rmdir($path)
+ && rmdir($path)
) {
$output->writeln(sprintf('Removed empty directory: %s', $path));
} else {
diff --git a/tests/Console/Command/PurgeCommandTest.php b/tests/Console/Command/PurgeCommandTest.php
index 2a57c22..7894b6f 100644
--- a/tests/Console/Command/PurgeCommandTest.php
+++ b/tests/Console/Command/PurgeCommandTest.php
@@ -19,7 +19,6 @@ use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\TestCase;
-use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Tester\CommandTester;
@@ -535,121 +534,6 @@ class PurgeCommandTest extends TestCase
self::assertStringContainsString('Removed empty directory', $tester->getDisplay());
}
- #[TestDox('execute() skips unreferenced archives that are already gone when they are about to be removed')]
- public function testExecuteSkipsArchivesThatDisappearDuringPurge(): void
- {
- $outputDir = vfsStream::url('satis/output-vanished');
- mkdir($outputDir);
- $archiveDir = $outputDir . '/dist';
- mkdir($archiveDir . '/vendor', 0755, true);
-
- $archives = [
- $archiveDir . '/vendor/first.tar.gz',
- $archiveDir . '/vendor/second.tar.gz',
- ];
- foreach ($archives as $archive) {
- file_put_contents($archive, 'x');
- }
-
- $this->writeOutputRepository($outputDir, $this->packageEntry(
- 'vendor/other',
- '1.0.0',
- 'https://example.com/dist/vendor/other.tar.gz'
- ));
-
- $this->writeSatisConfig([
- 'name' => 'test/satis-repo',
- 'homepage' => 'https://example.com',
- 'output-dir' => $outputDir,
- 'archive' => [
- 'directory' => 'dist',
- 'prefix-url' => 'https://example.com',
- ],
- ]);
-
- // Simulates a concurrent build or purge: once the first archive is removed, the others vanish too.
- $output = new class($archives) extends BufferedOutput {
- /**
- * @param list $archives
- */
- public function __construct(private readonly array $archives)
- {
- parent::__construct();
- }
-
- protected function doWrite(string $message, bool $newline): void
- {
- parent::doWrite($message, $newline);
-
- if (str_contains($message, 'Removed archive')) {
- foreach ($this->archives as $archive) {
- if (file_exists($archive)) {
- unlink($archive);
- }
- }
- }
- }
- };
-
- $input = new ArrayInput([
- 'file' => $this->configPath,
- 'output-dir' => $outputDir,
- ]);
- $input->setInteractive(false);
-
- $app = new Application();
- $app->addCommand(new PurgeCommand());
-
- $statusCode = $app->find('purge')->run($input, $output);
-
- $display = $output->fetch();
- self::assertSame(0, $statusCode);
- self::assertSame(1, substr_count($display, 'Removed archive'));
- self::assertStringContainsString('Skipped missing archive', $display);
- self::assertStringContainsString('Done.', $display);
- foreach ($archives as $archive) {
- self::assertFileDoesNotExist($archive);
- }
- }
-
- #[TestDox('execute() throws when an unreferenced archive exists but cannot be removed')]
- public function testExecuteThrowsWhenArchiveCannotBeRemoved(): void
- {
- $outputDir = vfsStream::url('satis/output-locked');
- mkdir($outputDir);
- $archiveDir = $outputDir . '/dist';
- mkdir($archiveDir . '/vendor', 0755, true);
-
- $unreferencedFile = $archiveDir . '/vendor/unreferenced.tar.gz';
- file_put_contents($unreferencedFile, 'x');
- chmod($archiveDir . '/vendor', 0555);
-
- $this->writeOutputRepository($outputDir, $this->packageEntry(
- 'vendor/other',
- '1.0.0',
- 'https://example.com/dist/vendor/other.tar.gz'
- ));
-
- $this->writeSatisConfig([
- 'name' => 'test/satis-repo',
- 'homepage' => 'https://example.com',
- 'output-dir' => $outputDir,
- 'archive' => [
- 'directory' => 'dist',
- 'prefix-url' => 'https://example.com',
- ],
- ]);
-
- $tester = $this->createTester();
-
- $this->expectException(\RuntimeException::class);
- $this->expectExceptionMessage('Could not delete ' . $unreferencedFile);
- $tester->execute([
- 'file' => $this->configPath,
- 'output-dir' => $outputDir,
- ]);
- }
-
// --- Dry-run ---
#[TestDox('execute() does not remove archives or empty dirs when dry-run is enabled')]