Skip to content

Commit e0500e1

Browse files
Deprecate not-unpacking, fix unpacking
1 parent 2a32137 commit e0500e1

File tree

3 files changed

+100
-108
lines changed

3 files changed

+100
-108
lines changed

src/Command/RequireCommand.php

+6-11
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,16 @@ public function __construct(PackageResolver $resolver)
3535
protected function configure()
3636
{
3737
parent::configure();
38-
$this->addOption('no-unpack', null, InputOption::VALUE_NONE, 'Disable unpacking Symfony packs in composer.json.');
38+
$this->addOption('no-unpack', null, InputOption::VALUE_NONE, '[DEPRECATED] Disable unpacking Symfony packs in composer.json.');
3939
$this->addOption('unpack', null, InputOption::VALUE_NONE, '[DEPRECATED] Unpacking is now enabled by default.');
4040
}
4141

4242
protected function execute(InputInterface $input, OutputInterface $output)
4343
{
44+
if ($input->getOption('no-unpack')) {
45+
$this->getIO()->writeError('<warning>The "--unpack" command line option is deprecated; unpacking is now enabled by default.</warning>');
46+
}
47+
4448
if ($input->getOption('unpack')) {
4549
$this->getIO()->writeError('<warning>The "--unpack" command line option is deprecated; unpacking is now enabled by default.</warning>');
4650
}
@@ -68,16 +72,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
6872
unset($contents, $json, $manipulator);
6973

7074
try {
71-
$ret = parent::execute($input, $output) ?? 0;
72-
73-
if (0 !== $ret || $input->getOption('no-unpack') || $input->getOption('no-update')) {
74-
return $ret;
75-
}
76-
77-
$unpackCommand = new UnpackCommand($this->resolver);
78-
$unpackCommand->setApplication($this->getApplication());
79-
80-
return $unpackCommand->execute($input, $output);
75+
return parent::execute($input, $output) ?? 0;
8176
} finally {
8277
if (null !== $file) {
8378
$manipulator = new JsonManipulator(file_get_contents($file));

src/Command/UnpackCommand.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
use Symfony\Flex\Unpack\Operation;
2424
use Symfony\Flex\Unpacker;
2525

26+
/**
27+
* @deprecated since Flex 1.4
28+
*/
2629
class UnpackCommand extends BaseCommand
2730
{
2831
private $resolver;
@@ -38,7 +41,7 @@ protected function configure()
3841
{
3942
$this->setName('symfony:unpack')
4043
->setAliases(['unpack'])
41-
->setDescription('Unpacks a Symfony pack.')
44+
->setDescription('[DEPRECATED] Unpacks a Symfony pack.')
4245
->setDefinition([
4346
new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Installed packages to unpack.'),
4447
new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages'),
@@ -56,6 +59,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
5659
$versionParser = new VersionParser();
5760
$dryRun = $input->hasOption('dry-run') && $input->getOption('dry-run');
5861

62+
$io->writeError('<warning>Command "symfony:unpack" is deprecated, Symfony packs are always unpacked now.</>');
63+
5964
$op = new Operation(true, $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages'));
6065
foreach ($versionParser->parseNameVersionPairs($packages) as $package) {
6166
if (null === $pkg = $installedRepo->findPackage($package['name'], '*')) {

src/Flex.php

+88-96
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
use Composer\Installer;
2525
use Composer\Installer\InstallerEvent;
2626
use Composer\Installer\InstallerEvents;
27-
use Composer\Installer\NoopInstaller;
2827
use Composer\Installer\PackageEvent;
2928
use Composer\Installer\PackageEvents;
3029
use Composer\Installer\SuggestedPackagesReporter;
@@ -71,6 +70,10 @@ class Flex implements PluginInterface, EventSubscriberInterface
7170
private $options;
7271
private $configurator;
7372
private $downloader;
73+
74+
/**
75+
* @var Installer
76+
*/
7477
private $installer;
7578
private $postInstallOutput = [''];
7679
private $operations = [];
@@ -293,8 +296,7 @@ public function configureInstaller()
293296
$backtrace = debug_backtrace();
294297
foreach ($backtrace as $trace) {
295298
if (isset($trace['object']) && $trace['object'] instanceof Installer) {
296-
$this->installer = \Closure::bind(function () { return $this->update ? $this : null; }, $trace['object'], $trace['object'])();
297-
$trace['object']->setSuggestedPackagesReporter(new SuggestedPackagesReporter(new NullIO()));
299+
$this->installer = $trace['object']->setSuggestedPackagesReporter(new SuggestedPackagesReporter(new NullIO()));
298300
}
299301

300302
if (isset($trace['object']) && $trace['object'] instanceof GlobalCommand) {
@@ -328,33 +330,21 @@ public function configureProject(Event $event)
328330
@unlink('LICENSE');
329331

330332
// Update composer.json (project is proprietary by default)
331-
$json = new JsonFile(Factory::getComposerFile());
332-
$contents = file_get_contents($json->getPath());
333+
$file = Factory::getComposerFile();
334+
$contents = file_get_contents($file);
333335
$manipulator = new JsonManipulator($contents);
336+
$json = JsonFile::parseJson($contents);
334337

335338
// new projects are most of the time proprietary
336339
$manipulator->addMainKey('license', 'proprietary');
337340

338341
// extra.branch-alias doesn't apply to the project
339342
$manipulator->removeSubNode('extra', 'branch-alias');
340343

341-
// replace unbounded constraints for symfony/* packages by extra.symfony.require
342-
$config = json_decode($contents, true);
343-
if ($symfonyVersion = $config['extra']['symfony']['require'] ?? null) {
344-
$versions = $this->downloader->getVersions();
345-
foreach (['require', 'require-dev'] as $type) {
346-
foreach ($config[$type] ?? [] as $package => $version) {
347-
if ('*' === $version && isset($versions['splits'][$package])) {
348-
$manipulator->addLink($type, $package, $symfonyVersion);
349-
}
350-
}
351-
}
352-
}
353-
354344
// 'name' and 'description' are only required for public packages
355345
// don't use $manipulator->removeProperty() for BC with Composer 1.0
356346
$contents = preg_replace(['{^\s*+"name":.*,$\n}m', '{^\s*+"description":.*,$\n}m'], '', $manipulator->getContents(), 1);
357-
file_put_contents($json->getPath(), $contents);
347+
file_put_contents($file, $contents);
358348

359349
$this->updateComposerLock();
360350
}
@@ -366,106 +356,49 @@ public function record(PackageEvent $event)
366356
}
367357
}
368358

369-
public function checkForUpdate(PackageEvent $event)
370-
{
371-
if (null === $this->installer || $this->cacheDirPopulated || 'symfony/flex' !== $event->getOperation()->getPackage()->getName()) {
372-
return;
373-
}
374-
375-
$this->update();
376-
$this->cacheDirPopulated = true;
377-
$this->composer->getInstallationManager()->addInstaller(new NoopInstaller());
378-
379-
\Closure::bind(function () {
380-
$this->io = new NullIO();
381-
$this->writeLock = false;
382-
$this->executeOperations = false;
383-
$this->dumpAutoloader = false;
384-
$this->runScripts = false;
385-
}, $this->installer, $this->installer)();
386-
}
387-
388-
public function update(Event $event = null, $operations = [])
359+
public function update(Event $event, $operations = [])
389360
{
390361
if ($operations) {
391362
$this->operations = $operations;
392363
}
393364

394365
$this->install($event);
395366

396-
$jsonPath = Factory::getComposerFile();
397-
$json = file_get_contents($jsonPath);
398-
$manipulator = new JsonManipulator($json);
399-
$json = json_decode($json, true);
367+
$file = Factory::getComposerFile();
368+
$contents = file_get_contents($file);
369+
$json = JsonFile::parseJson($contents);
370+
371+
if (!isset($json['flex-require']) && !isset($json['flex-require'])) {
372+
$this->unpack($event);
400373

401-
if (null === $event) {
402-
// called from checkForUpdate()
403-
} elseif (null === $this->installer || (!isset($json['flex-require']) && !isset($json['flex-require-dev']))) {
404374
return;
405-
} else {
406-
$event->stopPropagation();
407375
}
408376

377+
// merge "flex-require" with "require"
378+
$manipulator = new JsonManipulator($contents);
409379
$sortPackages = $this->composer->getConfig()->get('sort-packages');
410-
$unpackOp = new Operation(true, $sortPackages);
411-
380+
$symfonyVersion = $json['extra']['symfony']['require'] ?? null;
381+
$versions = $symfonyVersion ? $this->downloader->getVersions() : null;
412382
foreach (['require', 'require-dev'] as $type) {
413383
if (isset($json['flex-'.$type])) {
414384
foreach ($json['flex-'.$type] as $package => $constraint) {
415-
$unpackOp->addPackage($package, $constraint, 'require-dev' === $type);
385+
if ($symfonyVersion && '*' === $constraint && isset($versions['splits'][$package])) {
386+
// replace unbounded constraints for symfony/* packages by extra.symfony.require
387+
$constraint = $symfonyVersion;
388+
}
416389
$manipulator->addLink($type, $package, $constraint, $sortPackages);
417390
}
418391

419392
$manipulator->removeMainKey('flex-'.$type);
420393
}
421394
}
422395

423-
file_put_contents($jsonPath, $manipulator->getContents());
424-
425-
$this->cacheDirPopulated = false;
426-
$rm = $this->composer->getRepositoryManager();
427-
$package = Factory::create($this->io)->getPackage();
428-
$this->composer->setPackage($package);
429-
\Closure::bind(function () use ($package, $rm) {
430-
$this->package = $package;
431-
$this->repositoryManager = $rm;
432-
}, $this->installer, $this->installer)();
433-
$this->composer->getEventDispatcher()->__construct($this->composer, $this->io);
434-
435-
$status = $this->installer->run();
436-
if (0 !== $status) {
437-
exit($status);
438-
}
439-
440-
$unpacker = new Unpacker($this->composer, new PackageResolver($this->downloader), $this->dryRun);
441-
$result = $unpacker->unpack($unpackOp);
442-
$unpacker->updateLock($result, $this->io);
443-
444-
$io = new NullIO();
445-
$composer = Factory::create($io, null, true);
446-
$installer = Installer::create($io, $composer);
447-
$installer
448-
->setDevMode($this->dryRun)
449-
->setDumpAutoloader(false)
450-
->setIgnorePlatformRequirements(true)
451-
->setUpdate(true)
452-
->setUpdateAllowList(['php'])
453-
;
454-
455-
if (method_exists($composer->getEventDispatcher(), 'setRunScripts')) {
456-
$composer->getEventDispatcher()->setRunScripts(false);
457-
} else {
458-
$installer->setRunScripts(false);
459-
}
460-
461-
if (method_exists($installer, 'setSkipSuggest')) {
462-
$installer->setSkipSuggest(true);
463-
}
396+
file_put_contents($file, $manipulator->getContents());
464397

465-
$installer->run();
398+
$this->reinstall($event, true);
466399
}
467400

468-
public function install(Event $event = null)
401+
public function install(Event $event)
469402
{
470403
$rootDir = $this->options->get('root-dir');
471404

@@ -813,7 +746,7 @@ public function fetchRecipes(array $operations): array
813746
];
814747
$packRecipes = [];
815748

816-
foreach ($operations as $i => $operation) {
749+
foreach ($operations as $operation) {
817750
if ($operation instanceof UpdateOperation) {
818751
$package = $operation->getTargetPackage();
819752
} else {
@@ -992,14 +925,73 @@ private function updateComposerLock()
992925
$lockFile->write($lockData);
993926
}
994927

928+
private function unpack(Event $event)
929+
{
930+
$jsonPath = Factory::getComposerFile();
931+
$json = JsonFile::parseJson(file_get_contents($jsonPath));
932+
$sortPackages = $this->composer->getConfig()->get('sort-packages');
933+
$unpackOp = new Operation(true, $sortPackages);
934+
935+
foreach (['require', 'require-dev'] as $type) {
936+
foreach ($json[$type] ?? [] as $package => $constraint) {
937+
$unpackOp->addPackage($package, $constraint, 'require-dev' === $type);
938+
}
939+
}
940+
941+
$unpacker = new Unpacker($this->composer, new PackageResolver($this->downloader), $this->dryRun);
942+
$result = $unpacker->unpack($unpackOp);
943+
944+
if (!$result->getUnpacked()) {
945+
return;
946+
}
947+
948+
$this->io->writeError('<info>Unpacking Symfony packs</>');
949+
foreach ($result->getUnpacked() as $pkg) {
950+
$this->io->writeError(sprintf(' - Unpacked <info>%s</>', $pkg->getName()));
951+
}
952+
953+
$unpacker->updateLock($result, $this->io);
954+
955+
$this->reinstall($event, false);
956+
}
957+
958+
private function reinstall(Event $event, bool $update)
959+
{
960+
$event->stopPropagation();
961+
$composer = Factory::create($this->io);
962+
963+
$installer = clone $this->installer;
964+
$installer->__construct(
965+
$this->io,
966+
$composer->getConfig(),
967+
$composer->getPackage(),
968+
$composer->getDownloadManager(),
969+
$composer->getRepositoryManager(),
970+
$composer->getLocker(),
971+
$composer->getInstallationManager(),
972+
$composer->getEventDispatcher(),
973+
$composer->getAutoloadGenerator()
974+
);
975+
976+
if (!$update) {
977+
$installer->setUpdateAllowList(['php']);
978+
}
979+
980+
if (method_exists($installer, 'setSkipSuggest')) {
981+
$installer->setSkipSuggest(true);
982+
}
983+
984+
$installer->run();
985+
}
986+
995987
public static function getSubscribedEvents(): array
996988
{
997989
if (!self::$activated) {
998990
return [];
999991
}
1000992

1001993
$events = [
1002-
PackageEvents::POST_PACKAGE_INSTALL => __CLASS__ === self::class ? [['record'], ['checkForUpdate']] : 'record',
994+
PackageEvents::POST_PACKAGE_INSTALL => 'record',
1003995
PackageEvents::POST_PACKAGE_UPDATE => [['record'], ['enableThanksReminder']],
1004996
PackageEvents::POST_PACKAGE_UNINSTALL => 'record',
1005997
ScriptEvents::POST_CREATE_PROJECT_CMD => 'configureProject',

0 commit comments

Comments
 (0)