Issue #3087626 by greg.1.anderson, Mixologic, jibran, Mile23, alexpott, xjm: Convert drupal/core-recommended & c. into a subtree split
parent
d5fc5da747
commit
55580b707d
|
@ -70,11 +70,15 @@
|
|||
}
|
||||
},
|
||||
"scripts": {
|
||||
"pre-install-cmd": "Drupal\\Core\\Composer\\Composer::ensureComposerVersion",
|
||||
"pre-update-cmd": "Drupal\\Core\\Composer\\Composer::ensureComposerVersion",
|
||||
"pre-install-cmd": "Drupal\\Composer\\Composer::ensureComposerVersion",
|
||||
"pre-update-cmd": "Drupal\\Composer\\Composer::ensureComposerVersion",
|
||||
"pre-autoload-dump": "Drupal\\Core\\Composer\\Composer::preAutoloadDump",
|
||||
"drupal-phpunit-upgrade-check": "Drupal\\Core\\Composer\\Composer::upgradePHPUnit",
|
||||
"drupal-phpunit-upgrade": "@composer update phpunit/phpunit symfony/phpunit-bridge phpspec/prophecy symfony/yaml --with-dependencies --no-progress",
|
||||
"post-update-cmd": [
|
||||
"Drupal\\Composer\\Composer::generateMetapackages",
|
||||
"Drupal\\Composer\\Composer::ensureBehatDriverVersions"
|
||||
],
|
||||
"phpcs": "phpcs --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --",
|
||||
"phpcbf": "phpcbf --standard=core/phpcs.xml.dist --runtime-set installed_paths $($COMPOSER_BINARY config vendor-dir)/drupal/coder/coder_sniffer --"
|
||||
},
|
||||
|
|
|
@ -947,14 +947,14 @@
|
|||
"authors": [
|
||||
{
|
||||
"name": "Nicholas Humfrey",
|
||||
"role": "Developer",
|
||||
"email": "njh@aelius.com",
|
||||
"homepage": "http://www.aelius.com/njh/"
|
||||
"homepage": "http://www.aelius.com/njh/",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Alexey Zakhlestin",
|
||||
"role": "Developer",
|
||||
"email": "indeyets@gmail.com"
|
||||
"email": "indeyets@gmail.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "EasyRdf is a PHP library designed to make it easy to consume and produce RDF.",
|
||||
|
@ -3563,16 +3563,16 @@
|
|||
},
|
||||
{
|
||||
"name": "behat/mink-selenium2-driver",
|
||||
"version": "dev-master",
|
||||
"version": "1.3.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/minkphp/MinkSelenium2Driver.git",
|
||||
"reference": "8684ee4e634db7abda9039ea53545f86fc1e105a"
|
||||
"reference": "0a09c4341621fca937a726827611b20ce3e2c259"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/8684ee4e634db7abda9039ea53545f86fc1e105a",
|
||||
"reference": "8684ee4e634db7abda9039ea53545f86fc1e105a",
|
||||
"url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/0a09c4341621fca937a726827611b20ce3e2c259",
|
||||
"reference": "0a09c4341621fca937a726827611b20ce3e2c259",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3599,15 +3599,15 @@
|
|||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Konstantin Kudryashov",
|
||||
"email": "ever.zet@gmail.com",
|
||||
"homepage": "http://everzet.com"
|
||||
},
|
||||
{
|
||||
"name": "Pete Otaqui",
|
||||
"email": "pete@otaqui.com",
|
||||
"homepage": "https://github.com/pete-otaqui"
|
||||
},
|
||||
{
|
||||
"name": "Konstantin Kudryashov",
|
||||
"email": "ever.zet@gmail.com",
|
||||
"homepage": "http://everzet.com"
|
||||
}
|
||||
],
|
||||
"description": "Selenium2 (WebDriver) driver for Mink framework",
|
||||
|
@ -3620,7 +3620,7 @@
|
|||
"testing",
|
||||
"webdriver"
|
||||
],
|
||||
"time": "2018-10-10T12:39:06+00:00"
|
||||
"time": "2019-09-02T09:46:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/ca-bundle",
|
||||
|
@ -4421,18 +4421,18 @@
|
|||
"authors": [
|
||||
{
|
||||
"name": "Arne Blankerts",
|
||||
"role": "Developer",
|
||||
"email": "arne@blankerts.de"
|
||||
"email": "arne@blankerts.de",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Sebastian Heuer",
|
||||
"role": "Developer",
|
||||
"email": "sebastian@phpeople.de"
|
||||
"email": "sebastian@phpeople.de",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"role": "Developer",
|
||||
"email": "sebastian@phpunit.de"
|
||||
"email": "sebastian@phpunit.de",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Library for handling version information and constraints",
|
||||
|
@ -4791,8 +4791,8 @@
|
|||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"role": "lead",
|
||||
"email": "sebastian@phpunit.de"
|
||||
"email": "sebastian@phpunit.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "Simple template engine.",
|
||||
|
@ -5595,8 +5595,8 @@
|
|||
"authors": [
|
||||
{
|
||||
"name": "Sebastian Bergmann",
|
||||
"role": "lead",
|
||||
"email": "sebastian@phpunit.de"
|
||||
"email": "sebastian@phpunit.de",
|
||||
"role": "lead"
|
||||
}
|
||||
],
|
||||
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Composer;
|
||||
|
||||
use Composer\Composer as ComposerApp;
|
||||
use Composer\Script\Event;
|
||||
use Composer\Semver\Comparator;
|
||||
use Drupal\Composer\Generator\PackageGenerator;
|
||||
use Drupal\Composer\Generator\Util\DrupalCoreComposer;
|
||||
|
||||
/**
|
||||
* Provides static functions for composer script events. See also
|
||||
* core/lib/Drupal/Composer/Composer.php, which contains similar
|
||||
* scripts needed by projects that include drupal/core. Scripts that
|
||||
* are only needed by drupal/drupal go here.
|
||||
*
|
||||
* @see https://getcomposer.org/doc/articles/scripts.md
|
||||
*/
|
||||
class Composer {
|
||||
|
||||
/**
|
||||
* Update metapackages whenever composer.lock is updated.
|
||||
*
|
||||
* @param \Composer\Script\Event $event
|
||||
*/
|
||||
public static function generateMetapackages(Event $event) {
|
||||
$generator = new PackageGenerator();
|
||||
$generator->generate($event->getIO(), getcwd());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the minimum required version of Composer is running.
|
||||
* Throw an exception if Composer is too old.
|
||||
*/
|
||||
public static function ensureComposerVersion() {
|
||||
$composerVersion = method_exists(ComposerApp::class, 'getVersion') ?
|
||||
ComposerApp::getVersion() : ComposerApp::VERSION;
|
||||
if (Comparator::lessThan($composerVersion, '1.9.0')) {
|
||||
throw new \RuntimeException("Drupal core development requires Composer 1.9.0, but Composer $composerVersion is installed. Please run 'composer self-update'.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the right version of behat/mink-selenium2-driver is locked.
|
||||
* Throw an exception if we do not have 1.3.x-dev.
|
||||
*
|
||||
* @todo: Remove this once https://www.drupal.org/node/3078671 is fixed.
|
||||
*/
|
||||
public static function ensureBehatDriverVersions() {
|
||||
$drupalCoreComposer = DrupalCoreComposer::createFromPath(getcwd());
|
||||
|
||||
$expectedVersion = '1.3.x-dev';
|
||||
$behatMinkSelenium2DriverInfo = $drupalCoreComposer->packageLockInfo('behat/mink-selenium2-driver', TRUE);
|
||||
if ($behatMinkSelenium2DriverInfo['version'] != $expectedVersion) {
|
||||
$drupalVersion = static::drupalVersionBranch();
|
||||
$message = <<< __EOT__
|
||||
Drupal requires behat/mink-selenium2-driver:$expectedVersion in its composer.json
|
||||
file, but it is pinned to {$behatMinkSelenium2DriverInfo['version']} in the composer.lock file.
|
||||
This sometimes happens when Composer becomes confused. To fix:
|
||||
|
||||
1. `git checkout -- composer.lock`, or otherwise reset to a known-good lock file.
|
||||
2. `rm -rf vendor`
|
||||
3. `composer install`
|
||||
4. `COMPOSER_ROOT_VERSION={$drupalVersion} composer update ...` (where ... is
|
||||
the update arguments you wish to run, e.g. --lock).
|
||||
__EOT__;
|
||||
throw new \RuntimeException($message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the branch name the current Drupal version is associated with.
|
||||
*
|
||||
* @return string
|
||||
* A branch name, e.g. 8.9.x or 9.0.x.
|
||||
*/
|
||||
public static function drupalVersionBranch() {
|
||||
return preg_replace('#\.[0-9]+-dev#', '.x-dev', \Drupal::VERSION);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Composer\Generator\Builder;
|
||||
|
||||
/**
|
||||
* Builder to produce metapackage for drupal/core-recommended.
|
||||
*/
|
||||
class DrupalCoreRecommendedBuilder extends DrupalPackageBuilder {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPath() {
|
||||
return 'CoreRecommended';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPackage() {
|
||||
|
||||
$composer = $this->initialPackageMetadata();
|
||||
|
||||
// Pull up the composer lock data.
|
||||
$composerLockData = $this->drupalCoreInfo->composerLock();
|
||||
if (!isset($composerLockData['packages'])) {
|
||||
return $composer;
|
||||
}
|
||||
|
||||
// Make a list of packages we do not want to put in the 'require' section.
|
||||
$remove_list = ['drupal/core', 'wikimedia/composer-merge-plugin'];
|
||||
|
||||
// Copy the 'packages' section from the Composer lock into our 'require'
|
||||
// section. There is also a 'packages-dev' section, but we do not need
|
||||
// to pin 'require-dev' versions, as 'require-dev' dependencies are never
|
||||
// included from subprojects. Use 'drupal/core-dev-dependencies' to get
|
||||
// Drupal's dev dependencies.
|
||||
foreach ($composerLockData['packages'] as $package) {
|
||||
// If there is no 'source' record, then this is a path repository
|
||||
// or something else that we do not want to include.
|
||||
if (isset($package['source']) && !in_array($package['name'], $remove_list)) {
|
||||
$composer['require'][$package['name']] = $package['version'];
|
||||
}
|
||||
}
|
||||
return $composer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initial package metadata that describes the metapackage.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function initialPackageMetadata() {
|
||||
return [
|
||||
"name" => "drupal/core-recommended",
|
||||
"type" => "metapackage",
|
||||
"description" => "Locked core dependencies; require this project INSTEAD OF drupal/core.",
|
||||
"license" => "GPL-2.0-or-later",
|
||||
"conflict" => [
|
||||
"webflo/drupal-core-strict" => "*",
|
||||
],
|
||||
"require" => [
|
||||
"drupal/core" => "self.version",
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Composer\Generator\Builder;
|
||||
|
||||
/**
|
||||
* Builder to produce metapackage for drupal/dev-dependencies.
|
||||
*/
|
||||
class DrupalDevDependenciesBuilder extends DrupalPackageBuilder {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPath() {
|
||||
return 'DevDependencies';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPackage() {
|
||||
|
||||
$composer = $this->initialPackageMetadata();
|
||||
|
||||
// Put everything from Drupal's "require-dev" into our "require" section.
|
||||
$composer['require'] = $this->drupalCoreInfo->getRequireDev();
|
||||
|
||||
// If the require-dev is bringing in a dev version of behat/mink, convert
|
||||
// the requirement to a more flexible set of versions.
|
||||
// @todo: remove when https://www.drupal.org/node/3078671 is fixed.
|
||||
if (isset($composer['require']['behat/mink']) && ($composer['require']['behat/mink'] == '1.7.x-dev')) {
|
||||
$composer['require']['behat/mink'] = '1.8.0 | 1.7.1.1 | 1.7.x-dev';
|
||||
}
|
||||
|
||||
// Do the same sort of conversion for behat/mink-selenium2-driver.
|
||||
if (isset($composer['require']['behat/mink-selenium2-driver']) && ($composer['require']['behat/mink-selenium2-driver'] == '1.3.x-dev')) {
|
||||
$composer['require']['behat/mink-selenium2-driver'] = '1.4.0 | 1.3.1.1 | 1.3.x-dev';
|
||||
}
|
||||
|
||||
// Sort our required packages by key.
|
||||
ksort($composer['require']);
|
||||
|
||||
return $composer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initial package metadata that describes the metapackage.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function initialPackageMetadata() {
|
||||
return [
|
||||
"name" => "drupal/dev-dependencies",
|
||||
"type" => "metapackage",
|
||||
"description" => "require-dev dependencies from drupal/drupal; use in addition to drupal/core-recommended to run tests from drupal/core.",
|
||||
"license" => "GPL-2.0-or-later",
|
||||
"conflict" => [
|
||||
"webflo/drupal-core-require-dev" => "*",
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Composer\Generator\Builder;
|
||||
|
||||
use Drupal\Composer\Generator\BuilderInterface;
|
||||
use Drupal\Composer\Generator\Util\DrupalCoreComposer;
|
||||
|
||||
/**
|
||||
* Base class that includes helpful utility routine for Drupal builder classes.
|
||||
*/
|
||||
abstract class DrupalPackageBuilder implements BuilderInterface {
|
||||
|
||||
/**
|
||||
* Information about composer.json, composer.lock etc. in current release.
|
||||
*
|
||||
* @var \Drupal\Composer\Generator\Util\DrupalCoreComposer
|
||||
*/
|
||||
protected $drupalCoreInfo;
|
||||
|
||||
/**
|
||||
* DrupalPackageBuilder constructor.
|
||||
*
|
||||
* @param \Drupal\Composer\Generator\Util\DrupalCoreComposer $drupalCoreInfo
|
||||
* Information about composer.json and composer.lock from current release.
|
||||
*/
|
||||
public function __construct(DrupalCoreComposer $drupalCoreInfo) {
|
||||
$this->drupalCoreInfo = $drupalCoreInfo;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Composer\Generator\Builder;
|
||||
|
||||
/**
|
||||
* Builder to produce metapackage for drupal/pinned-dev-dependencies.
|
||||
*/
|
||||
class DrupalPinnedDevDependenciesBuilder extends DrupalPackageBuilder {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPath() {
|
||||
return 'PinnedDevDependencies';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPackage() {
|
||||
|
||||
$composer = $this->initialPackageMetadata();
|
||||
|
||||
// Pull the exact versions of the dependencies from the composer.lock
|
||||
// file and use it to build our 'require' section.
|
||||
$composerLockData = $this->drupalCoreInfo->composerLock();
|
||||
|
||||
if (isset($composerLockData['packages-dev'])) {
|
||||
|
||||
foreach ($composerLockData['packages-dev'] as $package) {
|
||||
$composer['require'][$package['name']] = $package['version'];
|
||||
|
||||
// If the require-dev is bringing in a dev version of behat/mink,
|
||||
// convert the requirement to a more flexible set of versions.
|
||||
// @todo: remove when https://www.drupal.org/node/3078671 is fixed.
|
||||
if (($package['name'] == 'behat/mink') && (($package['version'] == 'dev-master') || ($package['version'] == '1.7.x-dev'))) {
|
||||
$composer['require']['behat/mink'] = '1.8.0 | 1.7.1.1 | 1.7.x-dev';
|
||||
}
|
||||
|
||||
// Do the same sort of conversion for behat/mink-selenium2-driver.
|
||||
if (($package['name'] == 'behat/mink-selenium2-driver') && (($package['version'] == 'dev-master') || ($package['version'] == '1.3.x-dev'))) {
|
||||
$composer['require']['behat/mink-selenium2-driver'] = '1.4.0 | 1.3.1.1 | 1.3.x-dev';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $composer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initial package metadata that describes the metapackage.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function initialPackageMetadata() {
|
||||
return [
|
||||
"name" => "drupal/pinned-dev-dependencies",
|
||||
"type" => "metapackage",
|
||||
"description" => "Pinned require-dev dependencies from drupal/drupal; use in addition to drupal/core-recommended to run tests from drupal/core.",
|
||||
"license" => "GPL-2.0-or-later",
|
||||
"conflict" => [
|
||||
"webflo/drupal-core-require-dev" => "*",
|
||||
],
|
||||
"require" => [
|
||||
"drupal/core" => "self.version",
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Composer\Generator;
|
||||
|
||||
use Drupal\Composer\Generator\Util\DrupalCoreComposer;
|
||||
|
||||
/**
|
||||
* Produce the output for a metapackage.
|
||||
*
|
||||
* BuilderInterface provides an interface for builder classes which are
|
||||
* called by the PackageGenerator in order to produce a derived metapackage from
|
||||
* the provided source package.
|
||||
*
|
||||
* See the README.txt file in composer/Metapackage for a description of what
|
||||
* a metapackage is, and an explanation of the metapackages produced by the
|
||||
* generator.
|
||||
*/
|
||||
interface BuilderInterface {
|
||||
|
||||
/**
|
||||
* BuilderInterface constructor.
|
||||
*
|
||||
* @param \Drupal\Composer\Generator\Util\DrupalCoreComposer $drupalCoreInfo
|
||||
* Information about the composer.json, composer.lock, and repository path.
|
||||
*/
|
||||
public function __construct(DrupalCoreComposer $drupalCoreInfo);
|
||||
|
||||
/**
|
||||
* Return the path to where the metapackage should be written.
|
||||
*
|
||||
* @return string
|
||||
* Path to the metapackage.
|
||||
*/
|
||||
public function getPath();
|
||||
|
||||
/**
|
||||
* Generate the Composer.json data for the current tag or branch.
|
||||
*
|
||||
* @return array
|
||||
* Composer json data.
|
||||
*/
|
||||
public function getPackage();
|
||||
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Composer\Generator;
|
||||
|
||||
use Drupal\Composer\Generator\Builder\DrupalCoreRecommendedBuilder;
|
||||
use Drupal\Composer\Generator\Builder\DrupalDevDependenciesBuilder;
|
||||
use Drupal\Composer\Generator\Builder\DrupalPinnedDevDependenciesBuilder;
|
||||
use Drupal\Composer\Generator\Util\DrupalCoreComposer;
|
||||
use Composer\Util\Filesystem;
|
||||
use Composer\IO\IOInterface;
|
||||
|
||||
/**
|
||||
* Generates metapackages.
|
||||
*/
|
||||
class PackageGenerator {
|
||||
|
||||
/**
|
||||
* Base directory where generated projects are written.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $generatedProjectBaseDir;
|
||||
|
||||
/**
|
||||
* PackageGenerator constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->generatedProjectBaseDir = dirname(__DIR__) . '/Metapackage';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Drupal's metapackages whenever composer.lock is updated
|
||||
*
|
||||
* @param \Composer\IO\IOInterface $io
|
||||
* Composer IO object for interacting with the user.
|
||||
* @param string $base_dir
|
||||
* Directory where drupal/drupal repository is located.
|
||||
*/
|
||||
public function generate(IOInterface $io, $base_dir) {
|
||||
// General information from drupal/drupal and drupal/core composer.json
|
||||
// and composer.lock files.
|
||||
$drupalCoreInfo = DrupalCoreComposer::createFromPath($base_dir);
|
||||
|
||||
// Exit early if there is no composer.lock file.
|
||||
if (empty($drupalCoreInfo->composerLock())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Run all of our available builders.
|
||||
$builders = $this->builders();
|
||||
$changed = FALSE;
|
||||
foreach ($builders as $builder_class) {
|
||||
$builder = new $builder_class($drupalCoreInfo);
|
||||
$changed |= $this->generateMetapackage($io, $builder);
|
||||
}
|
||||
|
||||
// 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.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of metapackage builders.
|
||||
*
|
||||
* @return BuilderInterface[]
|
||||
*/
|
||||
protected function builders() {
|
||||
return [
|
||||
DrupalCoreRecommendedBuilder::class,
|
||||
DrupalDevDependenciesBuilder::class,
|
||||
DrupalPinnedDevDependenciesBuilder::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate one metapackage.
|
||||
*
|
||||
* @param \Composer\IO\IOInterface $io
|
||||
* Composer IO object for interacting with the user.
|
||||
* @param BuilderInterface $builder
|
||||
* An object that can build a metapackage.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the generated metapackage is different than what is on disk.
|
||||
*/
|
||||
protected function generateMetapackage(IOInterface $io, BuilderInterface $builder) {
|
||||
|
||||
// Load the existing composer.json file for drupal/core-recommended
|
||||
$relative_path = $builder->getPath() . '/composer.json';
|
||||
$composer_json_path = $this->generatedProjectBaseDir . '/' . $relative_path;
|
||||
$original_composer_json = file_exists($composer_json_path) ? file_get_contents($composer_json_path) : '';
|
||||
|
||||
// Get the composer.json file from the builder.
|
||||
$composer_json_data = $builder->getPackage();
|
||||
$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 metapackage file has been updated..
|
||||
$io->write("Updated metapackage file <info>composer/Metapackage/$relative_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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to encode metapackage 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($composer_json_data) {
|
||||
return json_encode($composer_json_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
HOW-TO: Test this Drupal composer script
|
||||
|
||||
In order to test this script, you'll need to get the entire Drupal repo and
|
||||
run the tests there.
|
||||
|
||||
You'll find the tests under core/tests/Drupal/Tests/Composer/Generator.
|
||||
|
||||
You can get the full Drupal repo here:
|
||||
https://www.drupal.org/project/drupal/git-instructions
|
||||
|
||||
You can find more information about running PHPUnit tests with Drupal here:
|
||||
https://www.drupal.org/node/2116263
|
||||
|
||||
Each component in the Drupal\Composer\Plugin namespace has its own annotated test
|
||||
group. You can use this group to run only the tests for this component. Like
|
||||
this:
|
||||
|
||||
$ ./vendor/bin/phpunit -c core --group Metapackage
|
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Composer\Generator\Util;
|
||||
|
||||
/**
|
||||
* Utilities for accessing composer.json data from drupal/drupal and drupal/core.
|
||||
*
|
||||
* Some data is stored in the root composer.json file, while others is found
|
||||
* in the core/composer.json file.
|
||||
*/
|
||||
class DrupalCoreComposer {
|
||||
|
||||
/**
|
||||
* Cached composer.json data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $composerJson = [];
|
||||
|
||||
/**
|
||||
* Cached composer.lock data.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $composerLock = [];
|
||||
|
||||
/**
|
||||
* DrupalCoreComposer constructor.
|
||||
*
|
||||
* @param array $composerJson
|
||||
* The composer.json data.
|
||||
* @param array $composerLock
|
||||
* The composer.lock data.
|
||||
*/
|
||||
public function __construct(array $composerJson, array $composerLock) {
|
||||
$this->composerJson = $composerJson;
|
||||
$this->composerLock = $composerLock;
|
||||
}
|
||||
|
||||
/**
|
||||
* DrupalCoreComposer factory.
|
||||
*
|
||||
* @param string $repositoryPath
|
||||
* Path to a directory containing a composer.json and composer.lock files.
|
||||
*
|
||||
* @return static
|
||||
* New DrupalCoreComposer object containing composer.json and lock data.
|
||||
*/
|
||||
public static function createFromPath(string $repositoryPath) {
|
||||
$composerJson = static::loadJsonFromPath("$repositoryPath/composer.json");
|
||||
$composerLock = static::loadJsonFromPath("$repositoryPath/composer.lock");
|
||||
return new self($composerJson, $composerLock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the composer data from the root drupal/drupal project.
|
||||
*
|
||||
* @return array
|
||||
* Composer json data
|
||||
*/
|
||||
public function rootComposerJson() {
|
||||
return $this->composerJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the composer lock data.
|
||||
*
|
||||
* @return array
|
||||
* Composer lock data
|
||||
*/
|
||||
public function composerLock() {
|
||||
return $this->composerLock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the "require-dev" section from root or core composer.json file.
|
||||
*
|
||||
* The require-dev constraints moved from core/composer.json (8.7.x and
|
||||
* earlier) to the root composer.json file (8.8.x and later).
|
||||
*
|
||||
* @return array
|
||||
* The contents of the "require-dev" section.
|
||||
*/
|
||||
public function getRequireDev() {
|
||||
$composerJsonData = $this->rootComposerJson();
|
||||
return isset($composerJsonData['require-dev']) ? $composerJsonData['require-dev'] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the info for one package in the composer.lock file.
|
||||
*
|
||||
* @param string $packageName
|
||||
* Name of package to find, e.g. 'behat/mink-selenium2-driver'.
|
||||
* @param bool $dev
|
||||
* TRUE: consider only 'packages-dev'. Default: consider only 'packages'
|
||||
*
|
||||
* @return array
|
||||
* Package info from composer.lock.
|
||||
*/
|
||||
public function packageLockInfo($packageName, $dev = FALSE) {
|
||||
$packagesSection = $dev ? 'packages-dev' : 'packages';
|
||||
foreach ($this->composerLock[$packagesSection] as $info) {
|
||||
if ($info['name'] == $packageName) {
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Load json data from the specified path.
|
||||
*
|
||||
* @param string $path
|
||||
* Relative path to the json file to load.
|
||||
*
|
||||
* @return array
|
||||
* The contents of the json data for the specified file.
|
||||
*/
|
||||
protected static function loadJsonFromPath($path) {
|
||||
return file_exists($path) ? json_decode(file_get_contents($path), TRUE) : [];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"name": "drupal/core-recommended",
|
||||
"type": "metapackage",
|
||||
"description": "Locked core dependencies; require this project INSTEAD OF drupal/core.",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"conflict": {
|
||||
"webflo/drupal-core-strict": "*"
|
||||
},
|
||||
"require": {
|
||||
"drupal/core": "self.version",
|
||||
"asm89/stack-cors": "1.2.0",
|
||||
"composer/installers": "v1.7.0",
|
||||
"composer/semver": "1.5.0",
|
||||
"doctrine/annotations": "v1.4.0",
|
||||
"doctrine/cache": "v1.6.2",
|
||||
"doctrine/collections": "v1.4.0",
|
||||
"doctrine/common": "v2.7.3",
|
||||
"doctrine/inflector": "v1.2.0",
|
||||
"doctrine/lexer": "1.0.2",
|
||||
"easyrdf/easyrdf": "0.9.1",
|
||||
"egulias/email-validator": "2.1.11",
|
||||
"guzzlehttp/guzzle": "6.3.3",
|
||||
"guzzlehttp/promises": "v1.3.1",
|
||||
"guzzlehttp/psr7": "1.6.1",
|
||||
"masterminds/html5": "2.3.0",
|
||||
"paragonie/random_compat": "v9.99.99",
|
||||
"pear/archive_tar": "1.4.8",
|
||||
"pear/console_getopt": "v1.4.2",
|
||||
"pear/pear-core-minimal": "v1.10.9",
|
||||
"pear/pear_exception": "v1.0.0",
|
||||
"psr/container": "1.0.0",
|
||||
"psr/http-message": "1.0.1",
|
||||
"psr/log": "1.1.0",
|
||||
"ralouphie/getallheaders": "3.0.3",
|
||||
"stack/builder": "v1.0.5",
|
||||
"symfony-cmf/routing": "1.4.1",
|
||||
"symfony/class-loader": "v3.4.32",
|
||||
"symfony/console": "v3.4.32",
|
||||
"symfony/debug": "v3.4.32",
|
||||
"symfony/dependency-injection": "v3.4.32",
|
||||
"symfony/event-dispatcher": "v3.4.32",
|
||||
"symfony/http-foundation": "v3.4.32",
|
||||
"symfony/http-kernel": "v3.4.32",
|
||||
"symfony/polyfill-ctype": "v1.12.0",
|
||||
"symfony/polyfill-iconv": "v1.12.0",
|
||||
"symfony/polyfill-mbstring": "v1.12.0",
|
||||
"symfony/polyfill-php70": "v1.12.0",
|
||||
"symfony/process": "v3.4.32",
|
||||
"symfony/psr-http-message-bridge": "v1.1.2",
|
||||
"symfony/routing": "v3.4.32",
|
||||
"symfony/serializer": "v3.4.32",
|
||||
"symfony/translation": "v3.4.32",
|
||||
"symfony/validator": "v3.4.32",
|
||||
"symfony/yaml": "v3.4.32",
|
||||
"twig/twig": "v1.42.3",
|
||||
"typo3/phar-stream-wrapper": "v3.1.3",
|
||||
"zendframework/zend-diactoros": "1.8.7",
|
||||
"zendframework/zend-escaper": "2.6.1",
|
||||
"zendframework/zend-feed": "2.12.0",
|
||||
"zendframework/zend-stdlib": "3.2.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "drupal/dev-dependencies",
|
||||
"type": "metapackage",
|
||||
"description": "require-dev dependencies from drupal/drupal; use in addition to drupal/core-recommended to run tests from drupal/core.",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"conflict": {
|
||||
"webflo/drupal-core-require-dev": "*"
|
||||
},
|
||||
"require": {
|
||||
"behat/mink": "1.8.0 | 1.7.1.1 | 1.7.x-dev",
|
||||
"behat/mink-goutte-driver": "^1.2",
|
||||
"behat/mink-selenium2-driver": "1.4.0 | 1.3.1.1 | 1.3.x-dev",
|
||||
"composer/composer": "^1.8",
|
||||
"drupal/coder": "^8.3.2",
|
||||
"jcalderonzumba/gastonjs": "^1.0.2",
|
||||
"jcalderonzumba/mink-phantomjs-driver": "^0.3.1",
|
||||
"justinrainbow/json-schema": "^5.2",
|
||||
"mikey179/vfsstream": "^1.2",
|
||||
"phpspec/prophecy": "^1.7",
|
||||
"phpunit/phpunit": "^6.5 || ^7",
|
||||
"symfony/browser-kit": "^3.4.0",
|
||||
"symfony/css-selector": "^3.4.0",
|
||||
"symfony/debug": "^3.4.0",
|
||||
"symfony/filesystem": "~3.4.0",
|
||||
"symfony/finder": "~3.4.0",
|
||||
"symfony/lock": "~3.4.0",
|
||||
"symfony/phpunit-bridge": "^3.4.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"name": "drupal/pinned-dev-dependencies",
|
||||
"type": "metapackage",
|
||||
"description": "Pinned require-dev dependencies from drupal/drupal; use in addition to drupal/core-recommended to run tests from drupal/core.",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"conflict": {
|
||||
"webflo/drupal-core-require-dev": "*"
|
||||
},
|
||||
"require": {
|
||||
"drupal/core": "self.version",
|
||||
"behat/mink": "1.8.0 | 1.7.1.1 | 1.7.x-dev",
|
||||
"behat/mink-browserkit-driver": "1.3.3",
|
||||
"behat/mink-goutte-driver": "v1.2.1",
|
||||
"behat/mink-selenium2-driver": "1.4.0 | 1.3.1.1 | 1.3.x-dev",
|
||||
"composer/ca-bundle": "1.2.4",
|
||||
"composer/composer": "1.9.0",
|
||||
"composer/spdx-licenses": "1.5.2",
|
||||
"composer/xdebug-handler": "1.3.3",
|
||||
"doctrine/instantiator": "1.0.5",
|
||||
"drupal/coder": "8.3.6",
|
||||
"fabpot/goutte": "v3.2.3",
|
||||
"instaclick/php-webdriver": "1.4.6",
|
||||
"jcalderonzumba/gastonjs": "v1.0.2",
|
||||
"jcalderonzumba/mink-phantomjs-driver": "v0.3.2",
|
||||
"justinrainbow/json-schema": "5.2.8",
|
||||
"mikey179/vfsstream": "v1.6.7",
|
||||
"myclabs/deep-copy": "1.7.0",
|
||||
"phar-io/manifest": "1.0.1",
|
||||
"phar-io/version": "1.0.1",
|
||||
"phpdocumentor/reflection-common": "1.0.1",
|
||||
"phpdocumentor/reflection-docblock": "4.3.2",
|
||||
"phpdocumentor/type-resolver": "0.5.1",
|
||||
"phpspec/prophecy": "1.9.0",
|
||||
"phpunit/php-code-coverage": "5.3.2",
|
||||
"phpunit/php-file-iterator": "1.4.5",
|
||||
"phpunit/php-text-template": "1.2.1",
|
||||
"phpunit/php-timer": "1.0.9",
|
||||
"phpunit/php-token-stream": "2.0.2",
|
||||
"phpunit/phpunit": "6.5.14",
|
||||
"phpunit/phpunit-mock-objects": "5.0.10",
|
||||
"sebastian/code-unit-reverse-lookup": "1.0.1",
|
||||
"sebastian/comparator": "2.1.3",
|
||||
"sebastian/diff": "2.0.1",
|
||||
"sebastian/environment": "3.1.0",
|
||||
"sebastian/exporter": "3.1.2",
|
||||
"sebastian/global-state": "2.0.0",
|
||||
"sebastian/object-enumerator": "3.0.3",
|
||||
"sebastian/object-reflector": "1.1.1",
|
||||
"sebastian/recursion-context": "3.0.0",
|
||||
"sebastian/resource-operations": "1.0.0",
|
||||
"sebastian/version": "2.0.1",
|
||||
"seld/jsonlint": "1.7.1",
|
||||
"seld/phar-utils": "1.0.1",
|
||||
"squizlabs/php_codesniffer": "3.5.0",
|
||||
"symfony/browser-kit": "v3.4.32",
|
||||
"symfony/css-selector": "v3.4.32",
|
||||
"symfony/dom-crawler": "v3.4.32",
|
||||
"symfony/filesystem": "v3.4.32",
|
||||
"symfony/finder": "v3.4.32",
|
||||
"symfony/lock": "v3.4.32",
|
||||
"symfony/phpunit-bridge": "v3.4.32",
|
||||
"theseer/tokenizer": "1.1.3",
|
||||
"webmozart/assert": "1.5.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
# Drupal Metapackages
|
||||
|
||||
A metapackage is a Composer package that contains only a composer.json, and
|
||||
has no other content. In other words, the purpose of a metapackage is to
|
||||
provide dependencies, not to provide code or data.
|
||||
|
||||
|
||||
## Metapackages Provided by Drupal Core
|
||||
|
||||
Drupal Core provides three metapackages that serve different purposes.
|
||||
|
||||
- drupal/core-recommended: This project pins to the exact version of each
|
||||
dependency used in drupal/core. It also requires drupal/core, so
|
||||
drupal/core-recommended should be used INSTEAD OF drupal/core. See usage
|
||||
diagram below. This relationship makes it easier for Composer to update
|
||||
a Drupal project.
|
||||
|
||||
- drupal/dev-dependencies: This project provides the same version constraints
|
||||
as Drupal uses for testing. It is useful for projects that either wish to
|
||||
run some of the Drupal tests directly, or for projects that may wish to use
|
||||
the same components that Drupal does for testing.
|
||||
|
||||
- drupal/pinned-dev-dependencies: This project should be used INSTEAD OF
|
||||
drupal/dev-dependencies in instances where a project wishes to pin to the
|
||||
exact version of each testing dependency used in Drupal. This in general
|
||||
should not be necessary.
|
||||
|
||||
Note that a project that uses both drupal/core-recommended and
|
||||
drupal/pinned-dev-dependencies must update them both at the same time, e.g.:
|
||||
|
||||
composer update drupal/core-recommended drupal/pinned-dev-dependencies --with-updates
|
||||
|
||||
Composer may have trouble with the update if one of these projects is listed
|
||||
on the command line without the other. Running composer update without any
|
||||
parameters should also work, because in this instance every dependency is
|
||||
updated.
|
||||
|
||||
|
||||
## Metapackage Usage in Template Projects
|
||||
|
||||
The relationship between the metapackages drupal/core-recommended and
|
||||
drupal/dev-dependencies and the project (subtree split) drupal/core, as
|
||||
used in the drupal/recommended-project is shown below:
|
||||
|
||||
+----------------------------+
|
||||
| drupal/recommended-project |
|
||||
+----------------------------+
|
||||
|
|
||||
+--"require":
|
||||
| |
|
||||
| | +-------------------------+ +-------------+
|
||||
| +-->| drupal/core-recommended |-->| drupal/core |
|
||||
| +-------------------------+ +-------------+
|
||||
|
|
||||
+--"require-dev":
|
||||
|
|
||||
| +-------------------------+
|
||||
+-->| drupal/dev-dependencies |
|
||||
+-------------------------+
|
||||
|
||||
If a user does not wish to pin their Drupal project's dependencies to the same
|
||||
versions used in drupal/core, then they should replace drupal/core-recommended
|
||||
with drupal/core in their "require" section.
|
||||
|
||||
If a user does not need the testing dependencies in their Drupal project, then
|
||||
they may simply remove drupal/dev-dependencies from the "require-dev" section.
|
|
@ -2,10 +2,8 @@
|
|||
|
||||
namespace Drupal\Core\Composer;
|
||||
|
||||
use Composer\Composer as ComposerApp;
|
||||
use Composer\Installer\PackageEvent;
|
||||
use Composer\Script\Event;
|
||||
use Composer\Semver\Comparator;
|
||||
use Composer\Semver\Constraint\Constraint;
|
||||
use Composer\Util\ProcessExecutor;
|
||||
use Drupal\Component\FileSecurity\FileSecurity;
|
||||
|
@ -96,20 +94,10 @@ class Composer {
|
|||
'zendframework/zend-stdlib' => ['doc'],
|
||||
];
|
||||
|
||||
/**
|
||||
* Ensure that the minimum required version of Composer is running.
|
||||
* Throw an exception if Composer is too old.
|
||||
*/
|
||||
public static function ensureComposerVersion() {
|
||||
$composerVersion = method_exists(ComposerApp::class, 'getVersion') ?
|
||||
ComposerApp::getVersion() : ComposerApp::VERSION;
|
||||
if (Comparator::lessThan($composerVersion, '1.9.0')) {
|
||||
throw new \RuntimeException("Drupal core development requires Composer 1.9.0, but Composer $composerVersion is installed. Please run 'composer self-update'.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add vendor classes to Composer's static classmap.
|
||||
*
|
||||
* @param \Composer\Script\Event $event
|
||||
*/
|
||||
public static function preAutoloadDump(Event $event) {
|
||||
// Get the configured vendor directory.
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\Composer;
|
||||
|
||||
use Drupal\Composer\Composer;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Composer\Composer
|
||||
* @group Composer
|
||||
*/
|
||||
class ComposerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Verify that Composer::ensureComposerVersion() doesn't break.
|
||||
*
|
||||
* @covers::ensureComposerVersion
|
||||
*/
|
||||
public function testEnsureComposerVersion() {
|
||||
try {
|
||||
$this->assertNull(Composer::ensureComposerVersion());
|
||||
}
|
||||
catch (\RuntimeException $e) {
|
||||
$this->assertRegExp('/Drupal core development requires Composer 1.9.0, but Composer /', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that Composer::ensureBehatDriverVersions() detects a good version.
|
||||
*
|
||||
* @covers::ensureBehatDriverVersions
|
||||
*/
|
||||
public function testEnsureBehatDriverVersions() {
|
||||
// First call 'ensureBehatDriverVersions' test directly using Drupal's
|
||||
// composer.lock. It should not fail.
|
||||
chdir($this->root);
|
||||
$this->assertNull(Composer::ensureBehatDriverVersions());
|
||||
|
||||
// Next, call 'ensureBehatDriverVersions' again, this time using a fixture
|
||||
// with a known-bad version number.
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessageRegExp('#^Drupal requires behat/mink-selenium2-driver:1.3.x-dev#');
|
||||
chdir(__DIR__ . '/fixtures/ensureBehatDriverVersionsFixture');
|
||||
$this->assertNull(Composer::ensureBehatDriverVersions());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\Composer\Generator;
|
||||
|
||||
use Drupal\Composer\Generator\Builder\DrupalCoreRecommendedBuilder;
|
||||
use Drupal\Composer\Generator\Builder\DrupalDevDependenciesBuilder;
|
||||
use Drupal\Composer\Generator\Builder\DrupalPinnedDevDependenciesBuilder;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Test DrupalCoreRecommendedBuilder
|
||||
*
|
||||
* @group Metapackage
|
||||
*/
|
||||
class BuilderTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Test data for testBuilder
|
||||
*/
|
||||
public function builderTestData() {
|
||||
return [
|
||||
[
|
||||
DrupalCoreRecommendedBuilder::class,
|
||||
[
|
||||
'name' => 'drupal/core-recommended',
|
||||
'type' => 'metapackage',
|
||||
'description' => 'Locked core dependencies; require this project INSTEAD OF drupal/core.',
|
||||
'license' => 'GPL-2.0-or-later',
|
||||
'require' =>
|
||||
[
|
||||
'drupal/core' => 'self.version',
|
||||
'symfony/polyfill-ctype' => 'v1.12.0',
|
||||
'symfony/yaml' => 'v3.4.32',
|
||||
],
|
||||
'conflict' =>
|
||||
[
|
||||
'webflo/drupal-core-strict' => '*',
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
[
|
||||
DrupalDevDependenciesBuilder::class,
|
||||
[
|
||||
'name' => 'drupal/dev-dependencies',
|
||||
'type' => 'metapackage',
|
||||
'description' => 'require-dev dependencies from drupal/drupal; use in addition to drupal/core-recommended to run tests from drupal/core.',
|
||||
'license' => 'GPL-2.0-or-later',
|
||||
'require' =>
|
||||
[
|
||||
'behat/mink' => '1.8.0 | 1.7.1.1 | 1.7.x-dev',
|
||||
],
|
||||
'conflict' =>
|
||||
[
|
||||
'webflo/drupal-core-require-dev' => '*',
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
[
|
||||
DrupalPinnedDevDependenciesBuilder::class,
|
||||
[
|
||||
'name' => 'drupal/pinned-dev-dependencies',
|
||||
'type' => 'metapackage',
|
||||
'description' => 'Pinned require-dev dependencies from drupal/drupal; use in addition to drupal/core-recommended to run tests from drupal/core.',
|
||||
'license' => 'GPL-2.0-or-later',
|
||||
'require' =>
|
||||
[
|
||||
'drupal/core' => 'self.version',
|
||||
'behat/mink' => '1.8.0 | 1.7.1.1 | 1.7.x-dev',
|
||||
'symfony/css-selector' => 'v4.3.5',
|
||||
],
|
||||
'conflict' =>
|
||||
[
|
||||
'webflo/drupal-core-require-dev' => '*',
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all of the various kinds of builders.
|
||||
*
|
||||
* @dataProvider builderTestData
|
||||
*/
|
||||
public function testBuilder($builderClass, $expected) {
|
||||
$fixtures = new Fixtures();
|
||||
$drupalCoreInfo = $fixtures->drupalCoreComposerFixture();
|
||||
|
||||
$builder = new $builderClass($drupalCoreInfo);
|
||||
$generatedJson = $builder->getPackage();
|
||||
|
||||
$this->assertEquals($expected, $generatedJson);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\Composer\Generator;
|
||||
|
||||
use Drupal\Composer\Generator\Util\DrupalCoreComposer;
|
||||
|
||||
/**
|
||||
* Convenience class for creating fixtures.
|
||||
*/
|
||||
class Fixtures {
|
||||
|
||||
/**
|
||||
* Generate a suitable DrupalCoreComposer fixture for testing.
|
||||
*
|
||||
* @return \Drupal\Composer\Generator\Util\DrupalCoreComposer
|
||||
* DrupalCoreComposer fixture.
|
||||
*/
|
||||
public function drupalCoreComposerFixture() {
|
||||
return new DrupalCoreComposer($this->composerJson(), $this->composerLock());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for a composer.json fixture.
|
||||
*
|
||||
* @return array
|
||||
* composer.json fixture data.
|
||||
*/
|
||||
protected function composerJson() {
|
||||
return [
|
||||
'name' => 'drupal/project-fixture',
|
||||
'description' => 'A fixture for testing the metapackage generator.',
|
||||
'type' => 'project',
|
||||
'license' => 'GPL-2.0-or-later',
|
||||
'require' =>
|
||||
[
|
||||
'php' => '>=7.0.8',
|
||||
'symfony/yaml' => '~3.4.5',
|
||||
],
|
||||
'require-dev' =>
|
||||
[
|
||||
'behat/mink' => '1.7.x-dev',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for a composer.lock fixture.
|
||||
*
|
||||
* @return array
|
||||
* composer.lock fixture data.
|
||||
*/
|
||||
protected function composerLock() {
|
||||
return [
|
||||
'_readme' =>
|
||||
[
|
||||
'This is a composer.lock fixture. It contains only a subset of a',
|
||||
'typical composer.lock file (just what is needed for testing).',
|
||||
],
|
||||
'content-hash' => 'da9910627bab73a256b39ceda83d7167',
|
||||
'packages' =>
|
||||
[
|
||||
[
|
||||
'name' => 'symfony/polyfill-ctype',
|
||||
'version' => 'v1.12.0',
|
||||
'source' =>
|
||||
[
|
||||
'type' => 'git',
|
||||
'url' => 'https://github.com/symfony/polyfill-ctype.git',
|
||||
'reference' => '550ebaac289296ce228a706d0867afc34687e3f4',
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'symfony/yaml',
|
||||
'version' => 'v3.4.32',
|
||||
'source' =>
|
||||
[
|
||||
'type' => 'git',
|
||||
'url' => 'https://github.com/symfony/yaml.git',
|
||||
'reference' => '768f817446da74a776a31eea335540f9dcb53942',
|
||||
],
|
||||
],
|
||||
],
|
||||
'packages-dev' =>
|
||||
[
|
||||
[
|
||||
'name' => 'behat/mink',
|
||||
'version' => 'dev-master',
|
||||
'source' =>
|
||||
[
|
||||
'type' => 'git',
|
||||
'url' => 'https://github.com/minkphp/Mink.git',
|
||||
'reference' => 'a534fe7dac9525e8e10ca68e737c3d7e5058ec83',
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'symfony/css-selector',
|
||||
'version' => 'v4.3.5',
|
||||
'source' =>
|
||||
[
|
||||
'type' => 'git',
|
||||
'url' => 'https://github.com/symfony/css-selector.git',
|
||||
'reference' => 'f4b3ff6a549d9ed28b2b0ecd1781bf67cf220ee9',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\Composer\Generator;
|
||||
|
||||
use Drupal\Composer\Generator\Builder\DrupalCoreRecommendedBuilder;
|
||||
use Drupal\Composer\Generator\Builder\DrupalDevDependenciesBuilder;
|
||||
use Drupal\Composer\Generator\Builder\DrupalPinnedDevDependenciesBuilder;
|
||||
use Drupal\Composer\Generator\PackageGenerator;
|
||||
use Drupal\Composer\Generator\Util\DrupalCoreComposer;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Test to see if the metapackages are up-to-date with the root composer.lock.
|
||||
*
|
||||
* @group Metapackage
|
||||
*/
|
||||
class MetapackageUpdateTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Test data for testUpdated
|
||||
*/
|
||||
public function updatedTestData() {
|
||||
return [
|
||||
[
|
||||
DrupalCoreRecommendedBuilder::class,
|
||||
'composer/Metapackage/CoreRecommended',
|
||||
],
|
||||
[
|
||||
DrupalDevDependenciesBuilder::class,
|
||||
'composer/Metapackage/DevDependencies',
|
||||
],
|
||||
[
|
||||
DrupalPinnedDevDependenciesBuilder::class,
|
||||
'composer/Metapackage/PinnedDevDependencies',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the generated metapackages are in sync with composer.lock.
|
||||
*
|
||||
* Note that this is not a test of code correctness, but rather it merely
|
||||
* confirms if the package builder was used on the most recent set of
|
||||
* metapackages.
|
||||
*
|
||||
* See BuilderTest.php for a test that checks for code correctness.
|
||||
*
|
||||
* @param string $builderClass
|
||||
* The metapackage builder to test.
|
||||
* @param string $path
|
||||
* The relative path to the metapackage
|
||||
*
|
||||
* @dataProvider updatedTestData
|
||||
*/
|
||||
public function testUpdated($builderClass, $path) {
|
||||
// Create a DrupalCoreComposer for the System Under Test (current repo)
|
||||
$repositoryRoot = dirname(dirname(dirname(dirname(dirname(dirname(__DIR__))))));
|
||||
$drupalCoreInfo = DrupalCoreComposer::createFromPath($repositoryRoot);
|
||||
|
||||
// Rebuild the metapackage for the composer.json / composer.lock of
|
||||
// the current repo.
|
||||
$builder = new $builderClass($drupalCoreInfo);
|
||||
$generatedJson = $builder->getPackage();
|
||||
$generatedJson = PackageGenerator::encode($generatedJson);
|
||||
|
||||
// Also load the most-recently-generated version of the metapackage.
|
||||
$loadedJson = file_get_contents("$repositoryRoot/$path/composer.json");
|
||||
|
||||
// The generated json is the "expected", what we think the loaded
|
||||
// json would contain, if the current patch is generated correctly
|
||||
// (metapackages updated when composer.lock is updated).
|
||||
$version = str_replace('.0-dev', '.x-dev', \Drupal::VERSION);
|
||||
$message = <<< __EOT__
|
||||
The rebuilt version of $path does not match what is in the source tree.
|
||||
|
||||
To fix, run:
|
||||
|
||||
COMPOSER_ROOT_VERSION=$version composer update --lock
|
||||
|
||||
__EOT__;
|
||||
$this->assertEquals($generatedJson, $loadedJson, $message);
|
||||
}
|
||||
|
||||
}
|
17
core/tests/Drupal/Tests/Composer/fixtures/ensureBehatDriverVersionsFixture/composer.lock
generated
Normal file
17
core/tests/Drupal/Tests/Composer/fixtures/ensureBehatDriverVersionsFixture/composer.lock
generated
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file is a fixture used to test Drupal."
|
||||
],
|
||||
"content-hash": "da9910627bab73a256b39ceda83d7167",
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "behat/mink-selenium2-driver",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/minkphp/MinkSelenium2Driver.git",
|
||||
"reference": "0a09c4341621fca937a726827611b20ce3e2c259"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\Core\Composer;
|
||||
|
||||
use Drupal\Core\Composer\Composer;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Composer\Composer
|
||||
* @group Composer
|
||||
*/
|
||||
class ComposerTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Verify that Composer::ensureComposerVersion() doesn't break.
|
||||
*
|
||||
* @covers::ensureComposerVersion
|
||||
*/
|
||||
public function testEnsureComposerVersion() {
|
||||
try {
|
||||
$this->assertNull(Composer::ensureComposerVersion());
|
||||
}
|
||||
catch (\RuntimeException $e) {
|
||||
$this->assertRegExp('/Drupal core development requires Composer 1.9.0, but Composer /', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue