Upstream composer/satis state of the touched files before 85d7736744

This commit is contained in:
upstream committed 2026-10-14 19:40:29 +02:00
1 parent a0d660f831
commit a12177f2cb
2 files changed
+2 -134

No files matched your search

+2 -18
View File
@@ -16,7 +16,6 @@ namespace Composer\Satis\Console\Command;
use Composer\Command\BaseCommand; use Composer\Command\BaseCommand;
use Composer\Json\JsonFile; use Composer\Json\JsonFile;
use Composer\Satis\PackageSelection\PackageSelection; use Composer\Satis\PackageSelection\PackageSelection;
use Composer\Util\Filesystem;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@@ -128,24 +127,9 @@ class PurgeCommand extends BaseCommand
return 0; return 0;
} }
$filesystem = new Filesystem();
foreach ($unreferenced as $currentFile) { foreach ($unreferenced as $currentFile) {
if (!$dryRun) { if (!$dryRun) {
try { unlink($currentFile->getPathname());
$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(
'<warning>Skipped missing archive</warning>: <comment>%s</comment>',
$currentFile->getRelativePathname()
));
continue;
}
} }
$output->writeln(sprintf( $output->writeln(sprintf(
@@ -182,7 +166,7 @@ class PurgeCommand extends BaseCommand
if (is_dir($path) if (is_dir($path)
&& $depth > 0 && $depth > 0
&& $this->removeEmptyDirectories($output, $path, $depth - 1) && $this->removeEmptyDirectories($output, $path, $depth - 1)
&& @rmdir($path) && rmdir($path)
) { ) {
$output->writeln(sprintf('<info>Removed empty directory</info>: <comment>%s</comment>', $path)); $output->writeln(sprintf('<info>Removed empty directory</info>: <comment>%s</comment>', $path));
} else { } else {
-116
View File
@@ -19,7 +19,6 @@ use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\TestDox; use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Console\Tester\CommandTester;
@@ -535,121 +534,6 @@ class PurgeCommandTest extends TestCase
self::assertStringContainsString('Removed empty directory', $tester->getDisplay()); 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<string> $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 --- // --- Dry-run ---
#[TestDox('execute() does not remove archives or empty dirs when dry-run is enabled')] #[TestDox('execute() does not remove archives or empty dirs when dry-run is enabled')]