Skip to content
Snippets Groups Projects
Commit 73730fb9 authored by Adam G-H's avatar Adam G-H
Browse files

Issue #3258045 by phenaproxima: Ensure update command in Stage::require() only...

Issue #3258045 by phenaproxima: Ensure update command in Stage::require() only updates specified packages
parent 560d2f9a
No related branches found
No related tags found
No related merge requests found
...@@ -128,23 +128,6 @@ class ComposerUtility { ...@@ -128,23 +128,6 @@ class ComposerUtility {
return array_values($core_packages); return array_values($core_packages);
} }
/**
* Returns the names of the core packages in the dev dependencies.
*
* All packages listed in ../core_packages.json are considered core packages.
*
* @return string[]
* The names of the core packages in the dev requirements.
*
* @todo Make this return a keyed array of packages, not just names in
* https://www.drupal.org/i/3258059.
*/
public function getCoreDevPackageNames(): array {
$dev_packages = $this->composer->getPackage()->getDevRequires();
$dev_packages = array_keys($dev_packages);
return array_intersect(static::getCorePackageList(), $dev_packages);
}
/** /**
* Returns all Drupal extension packages in the lock file. * Returns all Drupal extension packages in the lock file.
* *
...@@ -174,7 +157,7 @@ class ComposerUtility { ...@@ -174,7 +157,7 @@ class ComposerUtility {
* All packages in the lock file, keyed by name. * All packages in the lock file, keyed by name.
*/ */
protected function getLockedPackages(): array { protected function getLockedPackages(): array {
$locked_packages = $this->composer->getLocker() $locked_packages = $this->getComposer()->getLocker()
->getLockedRepository(TRUE) ->getLockedRepository(TRUE)
->getPackages(); ->getPackages();
......
...@@ -231,28 +231,38 @@ class Stage { ...@@ -231,28 +231,38 @@ class Stage {
} }
/** /**
* Requires packages in the staging area. * Adds or updates packages in the staging area.
* *
* @param string[] $constraints * @param string[] $runtime
* The packages to require, in the form 'vendor/name:version'. * The packages to add as regular top-level dependencies, in the form
* @param bool $dev * 'vendor/name:version'.
* (optional) Whether the packages should be required as dev dependencies. * @param string[] $dev
* Defaults to FALSE. * (optional) The packages to add as dev dependencies, in the form
* 'vendor/name:version'. Defaults to an empty array.
*/ */
public function require(array $constraints, bool $dev = FALSE): void { public function require(array $runtime, array $dev = []): void {
$this->checkOwnership(); $this->checkOwnership();
$command = array_merge(['require', '--no-update'], $constraints); $this->dispatch(new PreRequireEvent($this));
$dir = $this->getStageDirectory();
// Change the runtime and dev requirements as needed, but don't update
// the installed packages yet.
if ($runtime) {
$command = array_merge(['require', '--no-update'], $runtime);
$this->stager->stage($command, $dir);
}
if ($dev) { if ($dev) {
$command[] = '--dev'; $command = array_merge(['require', '--dev', '--no-update'], $dev);
$this->stager->stage($command, $dir);
}
// If constraints were changed, update those packages.
if ($runtime || $dev) {
$command = array_merge(['update', '--with-all-dependencies'], $runtime, $dev);
$this->stager->stage($command, $dir);
} }
$this->dispatch(new PreRequireEvent($this));
$dir = $this->getStageDirectory();
$this->stager->stage($command, $dir);
// @todo Limit the update command to only packages in $constraints in
// https://www.drupal.org/i/3257849.
$this->stager->stage(['update', '--with-all-dependencies'], $dir);
$this->dispatch(new PostRequireEvent($this)); $this->dispatch(new PostRequireEvent($this));
} }
......
...@@ -35,11 +35,12 @@ class Updater extends Stage { ...@@ -35,11 +35,12 @@ class Updater extends Stage {
'dev' => [], 'dev' => [],
]; ];
$require_dev = $composer->getComposer()
->getPackage()
->getDevRequires();
foreach ($composer->getCorePackageNames() as $package) { foreach ($composer->getCorePackageNames() as $package) {
$package_versions['production'][$package] = $project_versions['drupal']; $group = array_key_exists($package, $require_dev) ? 'dev' : 'production';
} $package_versions[$group][$package] = $project_versions['drupal'];
foreach ($composer->getCoreDevPackageNames() as $package) {
$package_versions['dev'][$package] = $project_versions['drupal'];
} }
// Ensure that package versions are available to pre-create event // Ensure that package versions are available to pre-create event
...@@ -79,12 +80,7 @@ class Updater extends Stage { ...@@ -79,12 +80,7 @@ class Updater extends Stage {
return $requirements; return $requirements;
}; };
$versions = array_map($map, $this->getPackageVersions()); $versions = array_map($map, $this->getPackageVersions());
$this->require($versions['production'], $versions['dev']);
$this->require($versions['production']);
if ($versions['dev']) {
$this->require($versions['dev'], TRUE);
}
} }
/** /**
......
...@@ -19,5 +19,10 @@ ...@@ -19,5 +19,10 @@
"version": "9.8.0" "version": "9.8.0"
} }
], ],
"packages-dev": [] "packages-dev": [
{
"name": "drupal/core-dev",
"version": "9.8.0"
}
]
} }
...@@ -57,7 +57,7 @@ class UpdaterTest extends AutomaticUpdatesKernelTestBase { ...@@ -57,7 +57,7 @@ class UpdaterTest extends AutomaticUpdatesKernelTestBase {
$id = $this->container->get('automatic_updates.updater')->begin([ $id = $this->container->get('automatic_updates.updater')->begin([
'drupal' => '9.8.1', 'drupal' => '9.8.1',
]); ]);
// Rebuild the container to ensure the project versions are kept in state. // Rebuild the container to ensure the package versions are persisted.
/** @var \Drupal\Core\DrupalKernel $kernel */ /** @var \Drupal\Core\DrupalKernel $kernel */
$kernel = $this->container->get('kernel'); $kernel = $this->container->get('kernel');
$kernel->rebuildContainer(); $kernel->rebuildContainer();
...@@ -66,37 +66,55 @@ class UpdaterTest extends AutomaticUpdatesKernelTestBase { ...@@ -66,37 +66,55 @@ class UpdaterTest extends AutomaticUpdatesKernelTestBase {
$this->container->set('package_manager.path_locator', $locator->reveal()); $this->container->set('package_manager.path_locator', $locator->reveal());
$this->setCurrentUser($user); $this->setCurrentUser($user);
/** @var \Drupal\automatic_updates\Updater $updater */
$updater = $this->container->get('automatic_updates.updater');
// Ensure that the target package versions are what we expect.
$expected_versions = [
'production' => [
'drupal/core-recommended' => '9.8.1',
],
'dev' => [
'drupal/core-dev' => '9.8.1',
],
];
$this->assertSame($expected_versions, $updater->claim($id)->getPackageVersions());
// When we call Updater::stage(), the stored project versions should be // When we call Updater::stage(), the stored project versions should be
// read from state and passed to Composer Stager's Stager service, in the // read from state and passed to Composer Stager's Stager service, in the
// form of a Composer command. This is done using package_manager_bypass's // form of a Composer command. This is done using package_manager_bypass's
// invocation recorder, rather than a regular mock, in order to test that // invocation recorder, rather than a regular mock, in order to test that
// the invocation recorder itself works. // the invocation recorder itself works.
// The production dependencies should be updated first... // The production requirements are changed first, followed by the dev
$expected_require_arguments = [ // requirements. Then the installed packages are updated.
'require', $expected_arguments = [
'--no-update', [
'drupal/core-recommended:9.8.1', 'require',
]; '--no-update',
// ...followed by the dev dependencies. 'drupal/core-recommended:9.8.1',
$expected_require_dev_arguments = [ ],
'require', [
'--no-update', 'require',
'drupal/core-dev:9.8.1', '--dev',
'--dev', '--no-update',
'drupal/core-dev:9.8.1',
],
[
'update',
'--with-all-dependencies',
'drupal/core-recommended:9.8.1',
'drupal/core-dev:9.8.1',
],
]; ];
// In both cases, `composer update` will be called separately. $updater->stage();
$expected_update_arguments = ['update', '--with-all-dependencies'];
$actual_arguments = $this->container->get('package_manager.stager')
$this->container->get('automatic_updates.updater')->claim($id)->stage(); ->getInvocationArguments();
/** @var \Drupal\package_manager_bypass\InvocationRecorderBase $stager */ $this->assertSame(count($expected_arguments), count($actual_arguments));
$stager = $this->container->get('package_manager.stager'); foreach ($actual_arguments as $i => [$arguments]) {
$invocation_arguments = $stager->getInvocationArguments(); $this->assertSame($expected_arguments[$i], $arguments);
$this->assertCount(4, $invocation_arguments); }
$this->assertSame($expected_require_arguments, $invocation_arguments[0][0]);
$this->assertSame($expected_update_arguments, $invocation_arguments[1][0]);
$this->assertSame($expected_require_dev_arguments, $invocation_arguments[2][0]);
$this->assertSame($expected_update_arguments, $invocation_arguments[3][0]);
} }
/** /**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment