Issue #3272110 by Mile23, ravi.shankar, Spokje, xjm, andypost, joachim: Drupal 9 and 10's Drupal\Component composer.json files are totally out of date
parent
e91369d0b8
commit
bbdf337d77
|
@ -108,7 +108,9 @@
|
|||
"@composer update phpunit/phpunit --with-dependencies --no-progress"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"Drupal\\Composer\\Composer::generateMetapackages"
|
||||
"Drupal\\Composer\\Composer::generateMetapackages",
|
||||
"Drupal\\Composer\\Composer::generateComponentPackages"
|
||||
|
||||
],
|
||||
"phpcs": "phpcs --standard=core/phpcs.xml.dist --",
|
||||
"phpcbf": "phpcbf --standard=core/phpcs.xml.dist --"
|
||||
|
|
|
@ -6,6 +6,7 @@ use Composer\Composer as ComposerApp;
|
|||
use Composer\Script\Event;
|
||||
use Composer\Semver\Comparator;
|
||||
use Composer\Semver\VersionParser;
|
||||
use Drupal\Composer\Generator\ComponentGenerator;
|
||||
use Drupal\Composer\Generator\PackageGenerator;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
|
@ -30,6 +31,17 @@ class Composer {
|
|||
$generator->generate($event->getIO(), getcwd());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update component packages whenever composer.lock is updated.
|
||||
*
|
||||
* @param \Composer\Script\Event $event
|
||||
* The Composer event.
|
||||
*/
|
||||
public static function generateComponentPackages(Event $event): void {
|
||||
$generator = new ComponentGenerator();
|
||||
$generator->generate($event, getcwd());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the version of Drupal; used in release process and by the test suite.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Composer\Generator;
|
||||
|
||||
use Composer\IO\IOInterface;
|
||||
use Composer\Semver\VersionParser;
|
||||
use Composer\Script\Event;
|
||||
use Composer\Util\Filesystem;
|
||||
use Drupal\Composer\Composer;
|
||||
use Drupal\Composer\Generator\Util\DrupalCoreComposer;
|
||||
use Drupal\Composer\Util\SemanticVersion;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
/**
|
||||
* Reconciles Drupal component dependencies with core.
|
||||
*/
|
||||
class ComponentGenerator {
|
||||
|
||||
/**
|
||||
* Relative path from Drupal root to the component directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $relativeComponentPath = 'core/lib/Drupal/Component';
|
||||
|
||||
/**
|
||||
* Full path to the component directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $componentBaseDir;
|
||||
|
||||
/**
|
||||
* Data from drupal/drupal's composer.json file.
|
||||
*
|
||||
* @var \Drupal\Composer\Generator\Util\DrupalCoreComposer
|
||||
*/
|
||||
protected $drupalProjectInfo;
|
||||
|
||||
/**
|
||||
* Data from drupal/core's composer.json file.
|
||||
*
|
||||
* @var \Drupal\Composer\Generator\Util\DrupalCoreComposer
|
||||
*/
|
||||
protected $drupalCoreInfo;
|
||||
|
||||
/**
|
||||
* ComponentGenerator constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->componentBaseDir = dirname(__DIR__, 2) . '/' . static::$relativeComponentPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the composer.json files for components.
|
||||
*
|
||||
* @return \Symfony\Component\Finder\Finder
|
||||
* A Finder object with all the composer.json files for components.
|
||||
*/
|
||||
public function getComponentPathsFinder(): Finder {
|
||||
$composer_json_finder = new Finder();
|
||||
$composer_json_finder->name('composer.json')
|
||||
->in($this->componentBaseDir)
|
||||
->ignoreUnreadableDirs()
|
||||
->depth(1);
|
||||
return $composer_json_finder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconcile Drupal's components whenever composer.lock is updated.
|
||||
*
|
||||
* @param \Composer\Script\Event $event
|
||||
* The Composer event.
|
||||
* @param string $base_dir
|
||||
* Directory where drupal/drupal repository is located.
|
||||
*/
|
||||
public function generate(Event $event, string $base_dir): void {
|
||||
$io = $event->getIO();
|
||||
// General information from drupal/drupal and drupal/core composer.json
|
||||
// and composer.lock files.
|
||||
$this->drupalProjectInfo = DrupalCoreComposer::createFromPath($base_dir);
|
||||
$this->drupalCoreInfo = DrupalCoreComposer::createFromPath($base_dir . '/core');
|
||||
|
||||
$changed = FALSE;
|
||||
/** @var \Symfony\Component\Finder\SplFileInfo $component_composer_json */
|
||||
foreach ($this->getComponentPathsFinder()->getIterator() as $component_composer_json) {
|
||||
$changed |= $this->generateComponentPackage($event, $component_composer_json->getRelativePathname());
|
||||
}
|
||||
|
||||
// Remind the user not to miss files in a patch.
|
||||
if ($changed) {
|
||||
$io->write("If you make a patch, ensure that the files above are included.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the component JSON files.
|
||||
*
|
||||
* @param \Composer\Script\Event $event
|
||||
* The Composer event.
|
||||
* @param string $component_pathname
|
||||
* Relative path to the composer.json file for a component.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the generated component package is different from what is on
|
||||
* disk.
|
||||
*/
|
||||
protected function generateComponentPackage(Event $event, string $component_pathname): bool {
|
||||
$io = $event->getIO();
|
||||
$composer_json_path = $this->componentBaseDir . '/' . $component_pathname;
|
||||
$original_composer_json = file_exists($composer_json_path) ? file_get_contents($composer_json_path) : '';
|
||||
|
||||
// Modify the original data.
|
||||
$composer_json_data = $this->getPackage($io, $original_composer_json);
|
||||
$updated_composer_json = static::encode($composer_json_data);
|
||||
|
||||
// Exit early if nothing changed.
|
||||
if (trim($original_composer_json, " \t\r\0\x0B") === trim($updated_composer_json, " \t\r\0\x0B")) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Warn the user that a component file has been updated.
|
||||
$display_path = static::$relativeComponentPath . '/' . $component_pathname;
|
||||
$io->write("Updated component file <info>$display_path</info>.");
|
||||
|
||||
// Write the composer.json file back to disk.
|
||||
$fs = new Filesystem();
|
||||
$fs->ensureDirectoryExists(dirname($composer_json_path));
|
||||
file_put_contents($composer_json_path, $updated_composer_json);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconcile component dependencies with core.
|
||||
*
|
||||
* @param \Composer\IO\IOInterface $io
|
||||
* IO object for messages to the user.
|
||||
* @param string $original_json
|
||||
* Contents of the component's composer.json file.
|
||||
*
|
||||
* @return array
|
||||
* Structured data to be turned back into JSON.
|
||||
*/
|
||||
protected function getPackage(IOInterface $io, string $original_json): array {
|
||||
$original_data = json_decode($original_json, TRUE);
|
||||
$package_data = array_merge($original_data, $this->initialPackageMetadata());
|
||||
|
||||
$core_info = $this->drupalCoreInfo->rootComposerJson();
|
||||
|
||||
$stability = VersionParser::parseStability(\Drupal::VERSION);
|
||||
|
||||
// List of packages which we didn't find in either core requirement.
|
||||
$not_in_core = [];
|
||||
|
||||
// Traverse required packages.
|
||||
foreach (array_keys($original_data['require'] ?? []) as $package_name) {
|
||||
// Reconcile locked constraints from drupal/drupal. We might have a locked
|
||||
// version of a dependency that's not present in drupal/core.
|
||||
if ($info = $this->drupalProjectInfo->packageLockInfo($package_name)) {
|
||||
$package_data['require'][$package_name] = $info['version'];
|
||||
}
|
||||
// The package wasn't in the lock file, which means we need to tell the
|
||||
// user. But there are some packages we want to exclude from this list.
|
||||
elseif ($package_name !== 'php' && (strpos($package_name, 'drupal/core-') === FALSE)) {
|
||||
$not_in_core[$package_name] = $package_name;
|
||||
}
|
||||
|
||||
// Reconcile looser constraints from drupal/core, and we're totally OK
|
||||
// with over-writing the locked ones from above.
|
||||
if ($constraint = $core_info['require'][$package_name] ?? FALSE) {
|
||||
$package_data['require'][$package_name] = $constraint;
|
||||
}
|
||||
|
||||
// Reconcile dependencies on other Drupal components, so we can set the
|
||||
// constraint to our current version.
|
||||
if (strpos($package_name, 'drupal/core-') !== FALSE) {
|
||||
if ($stability === 'stable') {
|
||||
// Set the constraint to ^maj.min.
|
||||
$package_data['require'][$package_name] = SemanticVersion::majorMinorConstraint(\Drupal::VERSION);
|
||||
}
|
||||
else {
|
||||
// For non-stable releases, set the constraint to the branch version.
|
||||
$package_data['require'][$package_name] = Composer::drupalVersionBranch();
|
||||
// Also for non-stable releases which depend on another component,
|
||||
// set the minimum stability. We do this so we can test build the
|
||||
// components. Minimum-stability is otherwise ignored for packages
|
||||
// which aren't the root package, so for any other purpose, this is
|
||||
// unneeded.
|
||||
$package_data['minimum-stability'] = $stability;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($not_in_core) {
|
||||
$io->error($package_data['name'] . ' requires packages not present in drupal/drupal: ' . implode(', ', $not_in_core));
|
||||
}
|
||||
|
||||
return $package_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to encode package json in a consistent way.
|
||||
*
|
||||
* @param array $composer_json_data
|
||||
* Data to encode into a json string.
|
||||
*
|
||||
* @return string
|
||||
* Encoded version of provided json data.
|
||||
*/
|
||||
public static function encode(array $composer_json_data): string {
|
||||
return json_encode($composer_json_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Common default metadata for all components.
|
||||
*
|
||||
* @return array
|
||||
* An array containing the common default metadata for all components.
|
||||
*/
|
||||
protected function initialPackageMetadata(): array {
|
||||
return [
|
||||
'extra' => [
|
||||
'_readme' => [
|
||||
'This file was partially generated automatically. See: https://www.drupal.org/node/3293830',
|
||||
],
|
||||
],
|
||||
// Always reconcile PHP version.
|
||||
'require' => [
|
||||
'php' => '>=7.3.0',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Composer\Util;
|
||||
|
||||
/**
|
||||
* Utility methods for manipulating semantic versions.
|
||||
*/
|
||||
class SemanticVersion {
|
||||
|
||||
/**
|
||||
* Given a version, generate a loose ^major.minor constraint.
|
||||
*
|
||||
* @param string $version
|
||||
* Semantic version string. Example: 9.5.0-beta23.
|
||||
*
|
||||
* @return string
|
||||
* Constraint string for major and minor. Example: ^9.5
|
||||
*/
|
||||
public static function majorMinorConstraint(string $version): string {
|
||||
preg_match('/^(\d+)\.(\d+)\.\d+/', $version, $matches);
|
||||
return '^' . $matches[1] . '.' . $matches[2];
|
||||
}
|
||||
|
||||
}
|
|
@ -1,19 +1,27 @@
|
|||
{
|
||||
"name": "drupal/core-annotation",
|
||||
"description": "Annotation discovery and implementation of plugins.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"doctrine/annotations": "^1.4",
|
||||
"drupal/core-file-cache": "^8.8",
|
||||
"drupal/core-plugin": "^8.8",
|
||||
"drupal/core-utility": "^8.8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Annotation\\": ""
|
||||
}
|
||||
}
|
||||
"name": "drupal/core-annotation",
|
||||
"description": "Annotation discovery and implementation of plugins.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"doctrine/annotations": "^1.13",
|
||||
"drupal/core-file-cache": "10.0.x-dev",
|
||||
"drupal/core-plugin": "10.0.x-dev",
|
||||
"drupal/core-utility": "10.0.x-dev"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Annotation\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
{
|
||||
"name": "drupal/core-assertion",
|
||||
"description": "Provides helper functionality for runtime assertions.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Assertion\\": ""
|
||||
"name": "drupal/core-assertion",
|
||||
"description": "Provides helper functionality for runtime assertions.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Assertion\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
{
|
||||
"name": "drupal/core-class-finder",
|
||||
"description": "This class provides a class finding utility.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\ClassFinder\\": ""
|
||||
"name": "drupal/core-class-finder",
|
||||
"description": "This class provides a class finding utility.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\ClassFinder\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
{
|
||||
"name": "drupal/core-datetime",
|
||||
"description": "This class wraps the PHP DateTime class with more flexible initialization parameters, allowing a date to be created from an existing date object, a timestamp, a string with an unknown format, a string with a known format, or an array of date parts. It also adds an errors array and a __toString() method to the date object.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"drupal/core-utility": "^8.8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Datetime\\": ""
|
||||
}
|
||||
}
|
||||
"name": "drupal/core-datetime",
|
||||
"description": "This class wraps the PHP DateTime class with more flexible initialization parameters, allowing a date to be created from an existing date object, a timestamp, a string with an unknown format, a string with a known format, or an array of date parts. It also adds an errors array and a __toString() method to the date object.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"drupal/core-utility": "10.0.x-dev"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Datetime\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
|
|
|
@ -1,26 +1,33 @@
|
|||
{
|
||||
"name": "drupal/core-dependency-injection",
|
||||
"description": "Dependency Injection container optimized for Drupal's needs.",
|
||||
"keywords": ["drupal", "dependency injection"],
|
||||
"type": "library",
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"support": {
|
||||
"issues": "https://www.drupal.org/project/issues/drupal",
|
||||
"irc": "irc://irc.freenode.net/drupal-contribute",
|
||||
"source": "https://www.drupal.org/project/drupal/git-instructions"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"symfony/dependency-injection": "^4.4",
|
||||
"symfony/service-contracts": "^1.1|^2"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/expression-language": "For using expressions in service container configuration"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\DependencyInjection\\": ""
|
||||
"name": "drupal/core-dependency-injection",
|
||||
"description": "Dependency Injection container optimized for Drupal's needs.",
|
||||
"keywords": [
|
||||
"drupal",
|
||||
"dependency injection"
|
||||
],
|
||||
"type": "library",
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"support": {
|
||||
"issues": "https://www.drupal.org/project/issues/drupal",
|
||||
"source": "https://www.drupal.org/project/drupal/git-instructions"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"symfony/dependency-injection": "^6.1",
|
||||
"symfony/service-contracts": "v3.1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/expression-language": "For using expressions in service container configuration"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\DependencyInjection\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
{
|
||||
"name": "drupal/core-diff",
|
||||
"description": "Diff.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Diff\\": ""
|
||||
"name": "drupal/core-diff",
|
||||
"description": "Diff.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Diff\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
{
|
||||
"name": "drupal/core-discovery",
|
||||
"description": "Discovery.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"drupal/core-file-cache": "^8.8",
|
||||
"drupal/core-serialization": "^8.8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Discovery\\": ""
|
||||
}
|
||||
}
|
||||
"name": "drupal/core-discovery",
|
||||
"description": "Discovery.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"drupal/core-file-cache": "10.0.x-dev",
|
||||
"drupal/core-serialization": "10.0.x-dev"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Discovery\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
{
|
||||
"name": "drupal/core-event-dispatcher",
|
||||
"description": "EventDispatcher.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"symfony/dependency-injection": "^4.4",
|
||||
"symfony/event-dispatcher": "^4.4",
|
||||
"symfony/event-dispatcher-contracts": "^1.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\EventDispatcher\\": ""
|
||||
"name": "drupal/core-event-dispatcher",
|
||||
"description": "EventDispatcher.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"symfony/dependency-injection": "^6.1",
|
||||
"symfony/event-dispatcher": "^6.1",
|
||||
"symfony/event-dispatcher-contracts": "v3.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\EventDispatcher\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
{
|
||||
"name": "drupal/core-file-cache",
|
||||
"description": "FileCache.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\FileCache\\": ""
|
||||
"name": "drupal/core-file-cache",
|
||||
"description": "FileCache.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\FileCache\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
{
|
||||
"name": "drupal/core-file-security",
|
||||
"description": "FileSecurity.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\FileSecurity\\": ""
|
||||
"name": "drupal/core-file-security",
|
||||
"description": "FileSecurity.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\FileSecurity\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
{
|
||||
"name": "drupal/core-filesystem",
|
||||
"description": "FileSystem.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\FileSystem\\": ""
|
||||
"name": "drupal/core-filesystem",
|
||||
"description": "FileSystem.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\FileSystem\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
{
|
||||
"name": "drupal/core-front-matter",
|
||||
"description": "Component for parsing front matter from a source.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"drupal/core-serialization": "^8.8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\FrontMatter\\": ""
|
||||
}
|
||||
}
|
||||
"name": "drupal/core-front-matter",
|
||||
"description": "Component for parsing front matter from a source.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"drupal/core-serialization": "10.0.x-dev"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\FrontMatter\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
{
|
||||
"name": "drupal/core-gettext",
|
||||
"description": "PHP library for reading PO files.",
|
||||
"type": "library",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"support": {
|
||||
"issues": "https://www.drupal.org/project/issues/drupal",
|
||||
"irc": "irc://irc.freenode.net/drupal-contribute",
|
||||
"source": "https://www.drupal.org/project/drupal/git-instructions"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"drupal/core-render": "^9.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Gettext\\": ""
|
||||
}
|
||||
}
|
||||
"name": "drupal/core-gettext",
|
||||
"description": "PHP library for reading PO files.",
|
||||
"type": "library",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"support": {
|
||||
"issues": "https://www.drupal.org/project/issues/drupal",
|
||||
"source": "https://www.drupal.org/project/drupal/git-instructions"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"drupal/core-render": "10.0.x-dev"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Gettext\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
{
|
||||
"name": "drupal/core-graph",
|
||||
"description": "Graph.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Graph\\": ""
|
||||
"name": "drupal/core-graph",
|
||||
"description": "Graph.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Graph\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
{
|
||||
"name": "drupal/core-http-foundation",
|
||||
"description": "HttpFoundation.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"symfony/http-foundation": "^4.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\HttpFoundation\\": ""
|
||||
"name": "drupal/core-http-foundation",
|
||||
"description": "HttpFoundation.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"symfony/http-foundation": "^6.1.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\HttpFoundation\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
{
|
||||
"name": "drupal/core-php-storage",
|
||||
"description": "PhpStorage.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"drupal/core-file-security": "^8.8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\PhpStorage\\": ""
|
||||
}
|
||||
}
|
||||
"name": "drupal/core-php-storage",
|
||||
"description": "PhpStorage.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"drupal/core-file-security": "10.0.x-dev"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\PhpStorage\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
{
|
||||
"name": "drupal/core-plugin",
|
||||
"description": "Base building block for a scalable and extensible plug-in system for PHP components and application framework extensions.",
|
||||
"keywords": ["drupal", "plugin", "plugins"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"symfony/validator": "^4.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Plugin\\": ""
|
||||
"name": "drupal/core-plugin",
|
||||
"description": "Base building block for a scalable and extensible plug-in system for PHP components and application framework extensions.",
|
||||
"keywords": [
|
||||
"drupal",
|
||||
"plugin",
|
||||
"plugins"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"symfony/validator": "^6.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Plugin\\": ""
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/validator": "Leveraged in the use of context aware plugins."
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/validator": "Leveraged in the use of context aware plugins."
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
{
|
||||
"name": "drupal/core-proxy-builder",
|
||||
"description": "Provides a lightweight mechanism to provide lazy loaded proxies.",
|
||||
"keywords": ["drupal", "proxy"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\ProxyBuilder\\": ""
|
||||
"name": "drupal/core-proxy-builder",
|
||||
"description": "Provides a lightweight mechanism to provide lazy loaded proxies.",
|
||||
"keywords": [
|
||||
"drupal",
|
||||
"proxy"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\ProxyBuilder\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
{
|
||||
"name": "drupal/core-render",
|
||||
"description": "Renders placeholder variables for HTML and plain-text display.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"drupal/core-utility": "^8.8"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Render\\": ""
|
||||
}
|
||||
}
|
||||
"name": "drupal/core-render",
|
||||
"description": "Renders placeholder variables for HTML and plain-text display.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"drupal/core-utility": "10.0.x-dev"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Render\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
{
|
||||
"name": "drupal/core-serialization",
|
||||
"description": "Serialization.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0",
|
||||
"symfony/yaml": "^4.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Serialization\\": ""
|
||||
"name": "drupal/core-serialization",
|
||||
"description": "Serialization.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0",
|
||||
"symfony/yaml": "^6.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Serialization\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,23 @@
|
|||
{
|
||||
"name": "drupal/core-transliteration",
|
||||
"description": "Transliteration.",
|
||||
"type": "library",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"support": {
|
||||
"issues": "https://www.drupal.org/project/issues/drupal",
|
||||
"irc": "irc://irc.freenode.net/drupal-contribute",
|
||||
"source": "https://www.drupal.org/project/drupal/git-instructions"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Transliteration\\": ""
|
||||
"name": "drupal/core-transliteration",
|
||||
"description": "Transliteration.",
|
||||
"type": "library",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"support": {
|
||||
"issues": "https://www.drupal.org/project/issues/drupal",
|
||||
"source": "https://www.drupal.org/project/drupal/git-instructions"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Transliteration\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
{
|
||||
"name": "drupal/core-utility",
|
||||
"description": "Mostly static utility classes for string, xss, array, image, and other commonly needed manipulations.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Utility\\": ""
|
||||
"name": "drupal/core-utility",
|
||||
"description": "Mostly static utility classes for string, xss, array, image, and other commonly needed manipulations.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Utility\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
{
|
||||
"name": "drupal/core-uuid",
|
||||
"description": "UUID generation and validation.",
|
||||
"type": "library",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"support": {
|
||||
"issues": "https://www.drupal.org/project/issues/drupal",
|
||||
"irc": "irc://irc.freenode.net/drupal-contribute",
|
||||
"source": "https://www.drupal.org/project/drupal/git-instructions"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Uuid\\": ""
|
||||
"name": "drupal/core-uuid",
|
||||
"description": "UUID generation and validation.",
|
||||
"type": "library",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"support": {
|
||||
"issues": "https://www.drupal.org/project/issues/drupal",
|
||||
"source": "https://www.drupal.org/project/drupal/git-instructions"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Uuid\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
{
|
||||
"name": "drupal/core-version",
|
||||
"description": "Utility classes for process Drupal specific version information.",
|
||||
"keywords": ["drupal"],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=7.3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Version\\": ""
|
||||
"name": "drupal/core-version",
|
||||
"description": "Utility classes for process Drupal specific version information.",
|
||||
"keywords": [
|
||||
"drupal"
|
||||
],
|
||||
"homepage": "https://www.drupal.org/project/drupal",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"require": {
|
||||
"php": ">=8.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Drupal\\Component\\Version\\": ""
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"_readme": [
|
||||
"This file was partially generated automatically. See: https://www.drupal.org/node/3293830"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\BuildTests\Composer\Component;
|
||||
|
||||
use Drupal\BuildTests\Composer\ComposerBuildTestBase;
|
||||
use Drupal\Composer\Composer;
|
||||
|
||||
/**
|
||||
* Try to install dependencies per component, using Composer.
|
||||
*
|
||||
* @group #slow
|
||||
* @group Composer
|
||||
* @group Component
|
||||
*
|
||||
* @coversNothing
|
||||
*
|
||||
* @requires externalCommand composer
|
||||
*/
|
||||
class ComponentsIsolatedBuildTest extends ComposerBuildTestBase {
|
||||
|
||||
/**
|
||||
* Provides an array with relative paths to the component paths.
|
||||
*
|
||||
* @return array
|
||||
* An array with relative paths to the component paths.
|
||||
*/
|
||||
public function provideComponentPaths(): array {
|
||||
$data = [];
|
||||
// During the dataProvider phase, there is not a workspace directory yet.
|
||||
// So we will find relative paths and assemble them with the workspace
|
||||
// path later.
|
||||
$drupal_root = $this->getDrupalRoot();
|
||||
$composer_json_finder = $this->getComponentPathsFinder($drupal_root);
|
||||
|
||||
/** @var \Symfony\Component\Finder\SplFileInfo $path */
|
||||
foreach ($composer_json_finder->getIterator() as $path) {
|
||||
$data[] = ['/' . $path->getRelativePath()];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether components' composer.json can be installed in isolation.
|
||||
*
|
||||
* @dataProvider provideComponentPaths
|
||||
*/
|
||||
public function testComponentComposerJson(string $component_path): void {
|
||||
// Only copy the components. Copy all of them because some of them depend on
|
||||
// each other.
|
||||
$finder = $this->getCodebaseFinder();
|
||||
$finder->in($this->getDrupalRoot() . static::$componentsPath);
|
||||
$this->copyCodebase($finder->getIterator());
|
||||
|
||||
$working_dir = $this->getWorkingPath() . static::$componentsPath . $component_path;
|
||||
|
||||
// We add path repositories so we can wire internal dependencies together.
|
||||
$this->addExpectedRepositories($working_dir);
|
||||
|
||||
// Perform the installation.
|
||||
$this->executeCommand("composer install --working-dir=$working_dir --no-interaction --no-progress");
|
||||
$this->assertCommandSuccessful();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds expected repositories as path repositories to package under test.
|
||||
*
|
||||
* @param string $working_dir
|
||||
* The working directory.
|
||||
*/
|
||||
protected function addExpectedRepositories(string $working_dir): void {
|
||||
$repo_paths = [
|
||||
'Render' => 'drupal/core-render',
|
||||
'Utility' => 'drupal/core-utility',
|
||||
];
|
||||
foreach ($repo_paths as $path => $package_name) {
|
||||
$path_repo = $this->getWorkingPath() . static::$componentsPath . '/' . $path;
|
||||
$repo_name = strtolower($path);
|
||||
// Add path repositories with the current version number to the current
|
||||
// package under test.
|
||||
$drupal_version = Composer::drupalVersionBranch();
|
||||
$this->executeCommand("composer config repositories.$repo_name " .
|
||||
"'{\"type\": \"path\",\"url\": \"$path_repo\",\"options\": {\"versions\": {\"$package_name\": \"$drupal_version\"}}}' --working-dir=$working_dir");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\BuildTests\Composer\Component;
|
||||
|
||||
use Drupal\BuildTests\Composer\ComposerBuildTestBase;
|
||||
use Drupal\Composer\Composer;
|
||||
|
||||
/**
|
||||
* Demonstrate that the Component generator responds to release tagging.
|
||||
*
|
||||
* @group #slow
|
||||
* @group Composer
|
||||
* @group Component
|
||||
*
|
||||
* @coversNothing
|
||||
*
|
||||
* @requires externalCommand composer
|
||||
*/
|
||||
class ComponentsTaggedReleaseTest extends ComposerBuildTestBase {
|
||||
|
||||
/**
|
||||
* Highly arbitrary version and constraint expectations.
|
||||
*
|
||||
* @return array
|
||||
* - First element is the tag that should be applied to \Drupal::version.
|
||||
* - Second element is the resulting constraint which should be present in
|
||||
* the component core dependencies.
|
||||
*/
|
||||
public function providerVersionConstraint(): array {
|
||||
return [
|
||||
// [Tag, constraint]
|
||||
'1.0.x-dev' => ['1.0.x-dev', '1.0.x-dev'],
|
||||
'1.0.0-beta1' => ['1.0.0-beta1', '1.0.0-beta1'],
|
||||
'1.0.0-rc1' => ['1.0.0-rc1', '1.0.0-rc1'],
|
||||
'1.0.0' => ['1.0.0', '^1.0'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate release tagging and regeneration of dependencies.
|
||||
*
|
||||
* @dataProvider providerVersionConstraint
|
||||
*/
|
||||
public function testReleaseTagging(string $tag, string $constraint): void {
|
||||
$this->copyCodebase();
|
||||
$drupal_root = $this->getWorkspaceDirectory();
|
||||
|
||||
// Set the core version.
|
||||
Composer::setDrupalVersion($drupal_root, $tag);
|
||||
$this->assertDrupalVersion($tag, $drupal_root);
|
||||
|
||||
// Emulate the release script.
|
||||
// @see https://github.com/xjm/drupal_core_release/blob/main/tag.sh
|
||||
$this->executeCommand("COMPOSER_ROOT_VERSION=\"$tag\" composer update drupal/core*");
|
||||
$this->assertCommandSuccessful();
|
||||
$this->assertErrorOutputContains('generateComponentPackages');
|
||||
|
||||
// Find all the components.
|
||||
$component_finder = $this->getComponentPathsFinder($drupal_root);
|
||||
|
||||
// Loop through all the component packages.
|
||||
/** @var \Symfony\Component\Finder\SplFileInfo $composer_json */
|
||||
foreach ($component_finder->getIterator() as $composer_json) {
|
||||
$composer_json_data = json_decode(file_get_contents($composer_json->getPathname()), TRUE);
|
||||
$requires = array_merge(
|
||||
$composer_json_data['require'] ?? [],
|
||||
$composer_json_data['require-dev'] ?? []
|
||||
);
|
||||
// Required packages from drupal/core-* should have our constraint.
|
||||
foreach ($requires as $package => $req_constraint) {
|
||||
if (strpos($package, 'drupal/core-') !== FALSE) {
|
||||
$this->assertEquals($constraint, $req_constraint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\BuildTests\Composer;
|
||||
|
||||
use Drupal\BuildTests\Framework\BuildTestBase;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
/**
|
||||
* Base class for Composer build tests.
|
||||
*
|
||||
* @coversNothing
|
||||
*/
|
||||
abstract class ComposerBuildTestBase extends BuildTestBase {
|
||||
|
||||
/**
|
||||
* Relative path from Drupal root to the Components directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $componentsPath = '/core/lib/Drupal/Component';
|
||||
|
||||
/**
|
||||
* Assert that the VERSION constant in Drupal.php is the expected value.
|
||||
*
|
||||
* @param string $expectedVersion
|
||||
* The expected version.
|
||||
* @param string $dir
|
||||
* The path to the site root.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function assertDrupalVersion(string $expectedVersion, string $dir): void {
|
||||
$drupal_php_path = $dir . '/core/lib/Drupal.php';
|
||||
$this->assertFileExists($drupal_php_path);
|
||||
|
||||
// Read back the Drupal version that was set and assert it matches
|
||||
// expectations
|
||||
$this->executeCommand("php -r 'include \"$drupal_php_path\"; print \Drupal::VERSION;'");
|
||||
$this->assertCommandSuccessful();
|
||||
$this->assertCommandOutputContains($expectedVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the composer.json files for components.
|
||||
*
|
||||
* @param string $drupal_root
|
||||
* The Drupal root directory.
|
||||
*
|
||||
* @return \Symfony\Component\Finder\Finder
|
||||
* A Finder object with all the composer.json files for components.
|
||||
*/
|
||||
protected function getComponentPathsFinder(string $drupal_root): Finder {
|
||||
$finder = new Finder();
|
||||
$finder->name('composer.json')
|
||||
->in($drupal_root . static::$componentsPath)
|
||||
->ignoreUnreadableDirs()
|
||||
->depth(1);
|
||||
|
||||
return $finder;
|
||||
}
|
||||
|
||||
}
|
|
@ -4,7 +4,7 @@ namespace Drupal\BuildTests\Composer\Template;
|
|||
|
||||
use Composer\Json\JsonFile;
|
||||
use Composer\Semver\VersionParser;
|
||||
use Drupal\BuildTests\Framework\BuildTestBase;
|
||||
use Drupal\BuildTests\Composer\ComposerBuildTestBase;
|
||||
use Drupal\Composer\Composer;
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,7 @@ use Drupal\Composer\Composer;
|
|||
*
|
||||
* @requires externalCommand composer
|
||||
*/
|
||||
class ComposerProjectTemplatesTest extends BuildTestBase {
|
||||
class ComposerProjectTemplatesTest extends ComposerBuildTestBase {
|
||||
|
||||
/**
|
||||
* The minimum stability requirement for dependencies.
|
||||
|
@ -297,26 +297,6 @@ class ComposerProjectTemplatesTest extends BuildTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the VERSION constant in Drupal.php is the expected value.
|
||||
*
|
||||
* @param string $expectedVersion
|
||||
* The expected version.
|
||||
* @param string $dir
|
||||
* The path to the site root.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function assertDrupalVersion(string $expectedVersion, string $dir): void {
|
||||
$drupal_php_path = $dir . '/core/lib/Drupal.php';
|
||||
$this->assertFileExists($drupal_php_path);
|
||||
|
||||
// Read back the Drupal version that was set and assert it matches expectations.
|
||||
$this->executeCommand("php -r 'include \"$drupal_php_path\"; print \Drupal::VERSION;'");
|
||||
$this->assertCommandSuccessful();
|
||||
$this->assertCommandOutputContains($expectedVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a test package that points to the templates.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue