updated core and modules

This commit is contained in:
Bachir Soussi Chiadmi
2017-09-09 16:27:51 +02:00
parent 027aa99b32
commit 41863f872c
7810 changed files with 318922 additions and 83631 deletions
@@ -58,6 +58,11 @@ class ExtraPackage
*/
protected $package;
/**
* @var VersionParser $versionParser
*/
protected $versionParser;
/**
* @param string $path Path to composer.json file
* @param Composer $composer
@@ -70,6 +75,7 @@ class ExtraPackage
$this->logger = $logger;
$this->json = $this->readPackageJson($path);
$this->package = $this->loadPackage($this->json);
$this->versionParser = new VersionParser();
}
/**
@@ -120,10 +126,10 @@ class ExtraPackage
}
/**
* @param string $json
* @param array $json
* @return CompletePackage
*/
protected function loadPackage($json)
protected function loadPackage(array $json)
{
$loader = new ArrayLoader();
$package = $loader->load($json);
@@ -146,12 +152,9 @@ class ExtraPackage
*/
public function mergeInto(RootPackageInterface $root, PluginState $state)
{
$this->addRepositories($root);
$this->prependRepositories($root);
$this->mergeRequires('require', $root, $state);
if ($state->isDevMode()) {
$this->mergeRequires('require-dev', $root, $state);
}
$this->mergePackageLinks('conflict', $root);
$this->mergePackageLinks('replace', $root);
@@ -160,11 +163,29 @@ class ExtraPackage
$this->mergeSuggests($root);
$this->mergeAutoload('autoload', $root);
if ($state->isDevMode()) {
$this->mergeAutoload('devAutoload', $root);
}
$this->mergeExtra($root, $state);
$this->mergeScripts($root, $state);
if ($state->isDevMode()) {
$this->mergeDevInto($root, $state);
} else {
$this->mergeReferences($root);
}
}
/**
* Merge just the dev portion into a RootPackageInterface
*
* @param RootPackageInterface $root
* @param PluginState $state
*/
public function mergeDevInto(RootPackageInterface $root, PluginState $state)
{
$this->mergeRequires('require-dev', $root, $state);
$this->mergeAutoload('devAutoload', $root);
$this->mergeReferences($root);
}
/**
@@ -173,7 +194,7 @@ class ExtraPackage
*
* @param RootPackageInterface $root
*/
protected function addRepositories(RootPackageInterface $root)
protected function prependRepositories(RootPackageInterface $root)
{
if (!isset($this->json['repositories'])) {
return;
@@ -185,12 +206,12 @@ class ExtraPackage
if (!isset($repoJson['type'])) {
continue;
}
$this->logger->info("Adding {$repoJson['type']} repository");
$this->logger->info("Prepending {$repoJson['type']} repository");
$repo = $repoManager->createRepository(
$repoJson['type'],
$repoJson
);
$repoManager->addRepository($repo);
$repoManager->prependRepository($repo);
$newRepos[] = $repo;
}
@@ -402,25 +423,70 @@ class ExtraPackage
if ($state->replaceDuplicateLinks()) {
$unwrapped->setExtra(
array_merge($rootExtra, $extra)
self::mergeExtraArray($state->shouldMergeExtraDeep(), $rootExtra, $extra)
);
} else {
foreach (array_intersect(
array_keys($extra),
array_keys($rootExtra)
) as $key) {
$this->logger->info(
"Ignoring duplicate <comment>{$key}</comment> in ".
"<comment>{$this->path}</comment> extra config."
);
if (!$state->shouldMergeExtraDeep()) {
foreach (array_intersect(
array_keys($extra),
array_keys($rootExtra)
) as $key) {
$this->logger->info(
"Ignoring duplicate <comment>{$key}</comment> in ".
"<comment>{$this->path}</comment> extra config."
);
}
}
$unwrapped->setExtra(
array_merge($extra, $rootExtra)
self::mergeExtraArray($state->shouldMergeExtraDeep(), $extra, $rootExtra)
);
}
}
/**
* Merge scripts config into a RootPackageInterface
*
* @param RootPackageInterface $root
* @param PluginState $state
*/
public function mergeScripts(RootPackageInterface $root, PluginState $state)
{
$scripts = $this->package->getScripts();
if (!$state->shouldMergeScripts() || empty($scripts)) {
return;
}
$rootScripts = $root->getScripts();
$unwrapped = self::unwrapIfNeeded($root, 'setScripts');
if ($state->replaceDuplicateLinks()) {
$unwrapped->setScripts(
array_merge($rootScripts, $scripts)
);
} else {
$unwrapped->setScripts(
array_merge($scripts, $rootScripts)
);
}
}
/**
* Merges two arrays either via arrayMergeDeep or via array_merge.
*
* @param bool $mergeDeep
* @param array $array1
* @param array $array2
* @return array
*/
public static function mergeExtraArray($mergeDeep, $array1, $array2)
{
if ($mergeDeep) {
return NestedArray::mergeDeep($array1, $array2);
}
return array_merge($array1, $array2);
}
/**
* Update Links with a 'self.version' constraint with the root package's
* version.
@@ -438,7 +504,7 @@ class ExtraPackage
$linkType = BasePackage::$supportedLinkTypes[$type];
$version = $root->getVersion();
$prettyVersion = $root->getPrettyVersion();
$vp = new VersionParser();
$vp = $this->versionParser;
$method = 'get' . ucfirst($linkType['method']);
$packages = $root->$method();
@@ -503,5 +569,53 @@ class ExtraPackage
// @codeCoverageIgnoreEnd
return $root;
}
/**
* Update the root packages reference information.
*
* @param RootPackageInterface $root
*/
protected function mergeReferences(RootPackageInterface $root)
{
// Merge source reference information for merged packages.
// @see RootPackageLoader::load
$references = array();
$unwrapped = $this->unwrapIfNeeded($root, 'setReferences');
foreach (array('require', 'require-dev') as $linkType) {
$linkInfo = BasePackage::$supportedLinkTypes[$linkType];
$method = 'get'.ucfirst($linkInfo['method']);
$links = array();
foreach ($unwrapped->$method() as $link) {
$links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
}
$references = $this->extractReferences($links, $references);
}
$unwrapped->setReferences($references);
}
/**
* Extract vcs revision from version constraint (dev-master#abc123.
*
* @param array $requires
* @param array $references
* @return array
* @see RootPackageLoader::extractReferences()
*/
protected function extractReferences(array $requires, array $references)
{
foreach ($requires as $reqName => $reqVersion) {
$reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
$stabilityName = VersionParser::parseStability($reqVersion);
if (
preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) &&
$stabilityName === 'dev'
) {
$name = strtolower($reqName);
$references[$name] = $match[1];
}
}
return $references;
}
}
// vim:sw=4:ts=4:sts=4:et:
@@ -0,0 +1,116 @@
<?php
/**
* This file is part of the Composer Merge plugin.
*
* Copyright (C) 2015 Bryan Davis, Wikimedia Foundation, and contributors
*
* This software may be modified and distributed under the terms of the MIT
* license. See the LICENSE file for details.
*/
namespace Wikimedia\Composer\Merge;
/**
* Adapted from
* http://cgit.drupalcode.org/drupal/tree/core/lib/Drupal/Component/Utility/NestedArray.php
* @ f86a4d650d5af0b82a3981e09977055fa63f6f2e
*/
class NestedArray
{
/**
* Merges multiple arrays, recursively, and returns the merged array.
*
* This function is similar to PHP's array_merge_recursive() function, but
* it handles non-array values differently. When merging values that are
* not both arrays, the latter value replaces the former rather than
* merging with it.
*
* Example:
*
* @code
* $link_options_1 = array('fragment' => 'x', 'attributes' => array('title' => t('X'), 'class' => array('a', 'b')));
* $link_options_2 = array('fragment' => 'y', 'attributes' => array('title' => t('Y'), 'class' => array('c', 'd')));
*
* // This results in array('fragment' => array('x', 'y'), 'attributes' =>
* // array('title' => array(t('X'), t('Y')), 'class' => array('a', 'b',
* // 'c', 'd'))).
* $incorrect = array_merge_recursive($link_options_1, $link_options_2);
*
* // This results in array('fragment' => 'y', 'attributes' =>
* // array('title' => t('Y'), 'class' => array('a', 'b', 'c', 'd'))).
* $correct = NestedArray::mergeDeep($link_options_1, $link_options_2);
* @endcode
*
* @param array ...
* Arrays to merge.
*
* @return array
* The merged array.
*
* @see NestedArray::mergeDeepArray()
*/
public static function mergeDeep()
{
return self::mergeDeepArray(func_get_args());
}
/**
* Merges multiple arrays, recursively, and returns the merged array.
*
* This function is equivalent to NestedArray::mergeDeep(), except the
* input arrays are passed as a single array parameter rather than
* a variable parameter list.
*
* The following are equivalent:
* - NestedArray::mergeDeep($a, $b);
* - NestedArray::mergeDeepArray(array($a, $b));
*
* The following are also equivalent:
* - call_user_func_array('NestedArray::mergeDeep', $arrays_to_merge);
* - NestedArray::mergeDeepArray($arrays_to_merge);
*
* @param array $arrays
* An arrays of arrays to merge.
* @param bool $preserveIntegerKeys
* (optional) If given, integer keys will be preserved and merged
* instead of appended. Defaults to false.
*
* @return array
* The merged array.
*
* @see NestedArray::mergeDeep()
*/
public static function mergeDeepArray(
array $arrays,
$preserveIntegerKeys = false
) {
$result = array();
foreach ($arrays as $array) {
foreach ($array as $key => $value) {
// Renumber integer keys as array_merge_recursive() does
// unless $preserveIntegerKeys is set to TRUE. Note that PHP
// automatically converts array keys that are integer strings
// (e.g., '1') to integers.
if (is_integer($key) && !$preserveIntegerKeys) {
$result[] = $value;
} elseif (isset($result[$key]) &&
is_array($result[$key]) &&
is_array($value)
) {
// Recurse when both values are arrays.
$result[$key] = self::mergeDeepArray(
array($result[$key], $value),
$preserveIntegerKeys
);
} else {
// Otherwise, use the latter value, overriding any
// previous value.
$result[$key] = $value;
}
}
}
return $result;
}
}
// vim:sw=4:ts=4:sts=4:et:
@@ -74,6 +74,31 @@ class PluginState
*/
protected $mergeExtra = false;
/**
* Whether to merge the extra section in a deep / recursive way.
*
* By default the extra section is merged with array_merge() and duplicate
* keys are ignored. When enabled this allows to merge the arrays recursively
* using the following rule: Integer keys are merged, while array values are
* replaced where the later values overwrite the former.
*
* This is useful especially for the extra section when plugins use larger
* structures like a 'patches' key with the packages as sub-keys and the
* patches as values.
*
* When 'replace' mode is activated the order of array merges is exchanged.
*
* @var bool $mergeExtraDeep
*/
protected $mergeExtraDeep = false;
/**
* Whether to merge the scripts section.
*
* @var bool $mergeScripts
*/
protected $mergeScripts = false;
/**
* @var bool $firstInstall
*/
@@ -116,6 +141,8 @@ class PluginState
'replace' => false,
'merge-dev' => true,
'merge-extra' => false,
'merge-extra-deep' => false,
'merge-scripts' => false,
),
isset($extra['merge-plugin']) ? $extra['merge-plugin'] : array()
);
@@ -128,6 +155,8 @@ class PluginState
$this->replace = (bool)$config['replace'];
$this->mergeDev = (bool)$config['merge-dev'];
$this->mergeExtra = (bool)$config['merge-extra'];
$this->mergeExtraDeep = (bool)$config['merge-extra-deep'];
$this->mergeScripts = (bool)$config['merge-scripts'];
}
/**
@@ -217,7 +246,17 @@ class PluginState
*/
public function isDevMode()
{
return $this->mergeDev && $this->devMode;
return $this->shouldMergeDev() && $this->devMode;
}
/**
* Should devMode settings be merged?
*
* @return bool
*/
public function shouldMergeDev()
{
return $this->mergeDev;
}
/**
@@ -323,5 +362,39 @@ class PluginState
{
return $this->mergeExtra;
}
/**
* Should the extra section be merged deep / recursively?
*
* By default the extra section is merged with array_merge() and duplicate
* keys are ignored. When enabled this allows to merge the arrays recursively
* using the following rule: Integer keys are merged, while array values are
* replaced where the later values overwrite the former.
*
* This is useful especially for the extra section when plugins use larger
* structures like a 'patches' key with the packages as sub-keys and the
* patches as values.
*
* When 'replace' mode is activated the order of array merges is exchanged.
*
* @return bool
*/
public function shouldMergeExtraDeep()
{
return $this->mergeExtraDeep;
}
/**
* Should the scripts section be merged?
*
* By default, the scripts section is not merged.
*
* @return bool
*/
public function shouldMergeScripts()
{
return $this->mergeScripts;
}
}
// vim:sw=4:ts=4:sts=4:et:
+89 -22
View File
@@ -16,6 +16,7 @@ use Wikimedia\Composer\Merge\PluginState;
use Composer\Composer;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\EventDispatcher\Event as BaseEvent;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Factory;
use Composer\Installer;
@@ -26,7 +27,7 @@ use Composer\Installer\PackageEvents;
use Composer\IO\IOInterface;
use Composer\Package\RootPackageInterface;
use Composer\Plugin\PluginInterface;
use Composer\Script\Event;
use Composer\Script\Event as ScriptEvent;
use Composer\Script\ScriptEvents;
/**
@@ -86,6 +87,16 @@ class MergePlugin implements PluginInterface, EventSubscriberInterface
*/
const PACKAGE_NAME = 'wikimedia/composer-merge-plugin';
/**
* Name of the composer 1.1 init event.
*/
const COMPAT_PLUGINEVENTS_INIT = 'init';
/**
* Priority that plugin uses to register callbacks.
*/
const CALLBACK_PRIORITY = 50000;
/**
* @var Composer $composer
*/
@@ -102,11 +113,18 @@ class MergePlugin implements PluginInterface, EventSubscriberInterface
protected $logger;
/**
* Files that have already been processed
* Files that have already been fully processed
*
* @var string[] $loadedFiles
* @var string[] $loaded
*/
protected $loadedFiles = array();
protected $loaded = array();
/**
* Files that have already been partially processed
*
* @var string[] $loadedNoDev
*/
protected $loadedNoDev = array();
/**
* {@inheritdoc}
@@ -124,24 +142,52 @@ class MergePlugin implements PluginInterface, EventSubscriberInterface
public static function getSubscribedEvents()
{
return array(
InstallerEvents::PRE_DEPENDENCIES_SOLVING => 'onDependencySolve',
PackageEvents::POST_PACKAGE_INSTALL => 'onPostPackageInstall',
ScriptEvents::POST_INSTALL_CMD => 'onPostInstallOrUpdate',
ScriptEvents::POST_UPDATE_CMD => 'onPostInstallOrUpdate',
ScriptEvents::PRE_AUTOLOAD_DUMP => 'onInstallUpdateOrDump',
ScriptEvents::PRE_INSTALL_CMD => 'onInstallUpdateOrDump',
ScriptEvents::PRE_UPDATE_CMD => 'onInstallUpdateOrDump',
// Use our own constant to make this event optional. Once
// composer-1.1 is required, this can use PluginEvents::INIT
// instead.
self::COMPAT_PLUGINEVENTS_INIT =>
array('onInit', self::CALLBACK_PRIORITY),
InstallerEvents::PRE_DEPENDENCIES_SOLVING =>
array('onDependencySolve', self::CALLBACK_PRIORITY),
PackageEvents::POST_PACKAGE_INSTALL =>
array('onPostPackageInstall', self::CALLBACK_PRIORITY),
ScriptEvents::POST_INSTALL_CMD =>
array('onPostInstallOrUpdate', self::CALLBACK_PRIORITY),
ScriptEvents::POST_UPDATE_CMD =>
array('onPostInstallOrUpdate', self::CALLBACK_PRIORITY),
ScriptEvents::PRE_AUTOLOAD_DUMP =>
array('onInstallUpdateOrDump', self::CALLBACK_PRIORITY),
ScriptEvents::PRE_INSTALL_CMD =>
array('onInstallUpdateOrDump', self::CALLBACK_PRIORITY),
ScriptEvents::PRE_UPDATE_CMD =>
array('onInstallUpdateOrDump', self::CALLBACK_PRIORITY),
);
}
/**
* Handle an event callback for initialization.
*
* @param \Composer\EventDispatcher\Event $event
*/
public function onInit(BaseEvent $event)
{
$this->state->loadSettings();
// It is not possible to know if the user specified --dev or --no-dev
// so assume it is false. The dev section will be merged later when
// the other events fire.
$this->state->setDevMode(false);
$this->mergeFiles($this->state->getIncludes(), false);
$this->mergeFiles($this->state->getRequires(), true);
}
/**
* Handle an event callback for an install, update or dump command by
* checking for "merge-plugin" in the "extra" data and merging package
* contents if found.
*
* @param Event $event
* @param ScriptEvent $event
*/
public function onInstallUpdateOrDump(Event $event)
public function onInstallUpdateOrDump(ScriptEvent $event)
{
$this->state->loadSettings();
$this->state->setDevMode($event->isDevMode());
@@ -196,16 +242,32 @@ class MergePlugin implements PluginInterface, EventSubscriberInterface
*/
protected function mergeFile(RootPackageInterface $root, $path)
{
if (isset($this->loadedFiles[$path])) {
$this->logger->debug("Already merged <comment>$path</comment>");
if (isset($this->loaded[$path]) ||
(isset($this->loadedNoDev[$path]) && !$this->state->isDevMode())
) {
$this->logger->debug(
"Already merged <comment>$path</comment> completely"
);
return;
} else {
$this->loadedFiles[$path] = true;
}
$this->logger->info("Loading <comment>{$path}</comment>...");
$package = new ExtraPackage($path, $this->composer, $this->logger);
$package->mergeInto($root, $this->state);
if (isset($this->loadedNoDev[$path])) {
$this->logger->info(
"Loading -dev sections of <comment>{$path}</comment>..."
);
$package->mergeDevInto($root, $this->state);
} else {
$this->logger->info("Loading <comment>{$path}</comment>...");
$package->mergeInto($root, $this->state);
}
if ($this->state->isDevMode()) {
$this->loaded[$path] = true;
} else {
$this->loadedNoDev[$path] = true;
}
if ($this->state->recurseIncludes()) {
$this->mergeFiles($package->getIncludes(), false);
@@ -230,7 +292,12 @@ class MergePlugin implements PluginInterface, EventSubscriberInterface
);
$request->install($link->getTarget(), $link->getConstraint());
}
if ($this->state->isDevMode()) {
// Issue #113: Check devMode of event rather than our global state.
// Composer fires the PRE_DEPENDENCIES_SOLVING event twice for
// `--no-dev` operations to decide which packages are dev only
// requirements.
if ($this->state->shouldMergeDev() && $event->isDevMode()) {
foreach ($this->state->getDuplicateLinks('require-dev') as $link) {
$this->logger->info(
"Adding dev dependency <comment>{$link}</comment>"
@@ -266,9 +333,9 @@ class MergePlugin implements PluginInterface, EventSubscriberInterface
* plugin was installed during the run then trigger an update command to
* process any merge-patterns in the current config.
*
* @param Event $event
* @param ScriptEvent $event
*/
public function onPostInstallOrUpdate(Event $event)
public function onPostInstallOrUpdate(ScriptEvent $event)
{
// @codeCoverageIgnoreStart
if ($this->state->isFirstInstall()) {