Skip to content
This repository has been archived by the owner on Mar 7, 2023. It is now read-only.

Commit

Permalink
Refactor first install of merged requirements
Browse files Browse the repository at this point in the history
Adds tracking of merged requirements to `ExtraPackage` and `MergePlugin` to control if `MergePlugin::onPostInstallOrUpdate()` needs to trigger a `composer update` to install or update new requirements. The merged requirements are now assigned to `Installer::setUpdateAllowList()` to restrict the update operation to those new requirements. This prevents all other packages (such as root requirements) from being updated.

This solution provides consistent support of both the first-install feature and subsequent changes to merge-patterns between Composer 1 and 2.

Added:
- Property `ExtraPackage::$mergedRequirements` (and getter method) to track new requirements during merging process of `ExtraPackage::mergeOrDefer()`.
- Property `MergePlugin::$updateAllowList` (and getter method) to track all new requirements during merging process of `MergePlugin::mergeFile()`.
- Conditional statement in `MergePlugin::onPostInstallOrUpdate()` to skip first-install if there are no extra requirements.

Changed:
- Replaced `PluginState::forceUpdate()` conditional statement in `MergePlugin::onPostInstallOrUpdate()` with `Installer::setUpdateAllowList()`

FIxed:
- Property tags for `$loaded` and `$loadedNoDev` in `MergePlugin`
  • Loading branch information
mcaskill committed Feb 7, 2021
1 parent daa4e87 commit 4195d45
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 10 deletions.
18 changes: 18 additions & 0 deletions src/Merge/ExtraPackage.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ class ExtraPackage
*/
protected $package;

/**
* @var array<string, bool> $mergedRequirements
*/
protected $mergedRequirements = array();

/**
* @var VersionParser $versionParser
*/
Expand Down Expand Up @@ -103,6 +108,16 @@ public function getRequires()
$this->json['extra']['merge-plugin']['require'] : array();
}

/**
* Get list of merged requirements from this package.
*
* @return string[]
*/
public function getMergedRequirements()
{
return array_keys($this->mergedRequirements);
}

/**
* Read the contents of a composer.json style file into an array.
*
Expand Down Expand Up @@ -292,13 +307,16 @@ protected function mergeOrDefer(

if ($state->replaceDuplicateLinks()) {
$this->logger->info("Replacing <comment>{$name}</comment>");
$this->mergedRequirements[$name] = true;
$origin[$name] = $link;
} else {
$this->logger->info("Merging <comment>{$name}</comment>");
$this->mergedRequirements[$name] = true;
$origin[$name] = $this->mergeConstraints($origin[$name], $link, $state);
}
} else {
$this->logger->info("Adding <comment>{$name}</comment>");
$this->mergedRequirements[$name] = true;
$origin[$name] = $link;
}
}
Expand Down
46 changes: 36 additions & 10 deletions src/MergePlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,17 +109,24 @@ class MergePlugin implements PluginInterface, EventSubscriberInterface
/**
* Files that have already been fully processed
*
* @var string[] $loaded
* @var array<string, bool> $loaded
*/
protected $loaded = array();

/**
* Files that have already been partially processed
*
* @var string[] $loadedNoDev
* @var array<string, bool> $loadedNoDev
*/
protected $loadedNoDev = array();

/**
* Nested packages to restrict update operations.
*
* @var array<string, bool> $updateAllowList
*/
protected $updateAllowList = array();

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -167,6 +174,17 @@ public static function getSubscribedEvents()
);
}

/**
* Get list of packages to restrict update operations.
*
* @return string[]
* @see \Composer\Installer::setUpdateAllowList()
*/
public function getUpdateAllowList()
{
return array_keys($this->updateAllowList);
}

/**
* Handle an event callback for initialization.
*
Expand Down Expand Up @@ -266,6 +284,14 @@ protected function mergeFile(RootPackageInterface $root, $path)
$package->mergeInto($root, $this->state);
}

$requirements = $package->getMergedRequirements();
if (!empty($requirements)) {
$this->updateAllowList = array_replace(
$this->updateAllowList,
array_fill_keys($requirements, true)
);
}

if ($this->state->isDevMode()) {
$this->loaded[$path] = true;
} else {
Expand Down Expand Up @@ -311,6 +337,12 @@ public function onPostInstallOrUpdate(ScriptEvent $event)
// @codeCoverageIgnoreStart
if ($this->state->isFirstInstall()) {
$this->state->setFirstInstall(false);

$requirements = $this->getUpdateAllowList();
if (empty($requirements)) {
return;
}

$this->logger->log("\n".'<info>Running composer update to apply merge settings</info>');

if (!$this->state->isComposer1()) {
Expand Down Expand Up @@ -338,14 +370,8 @@ public function onPostInstallOrUpdate(ScriptEvent $event)
$this->state->shouldOptimizeAutoloader()
);

if ($this->state->forceUpdate()) {
// Force update mode so that new packages are processed rather
// than just telling the user that composer.json and
// composer.lock don't match.
$installer->setUpdate(true);
} else {
$this->logger->log('You may need to manually run composer update to apply merge settings');
}
$installer->setUpdate(true);
$installer->setUpdateAllowList($requirements);

$status = $installer->run();
if ($status !== 0) {
Expand Down

0 comments on commit 4195d45

Please sign in to comment.