From 3b6b63784fe5e11e5eaf469aebd6fa40e723403a Mon Sep 17 00:00:00 2001 From: Den Girnyk Date: Thu, 17 Jan 2019 18:11:32 +0200 Subject: [PATCH 1/9] Fix: Keep replaced packages for autoload dumping with --no-dev --- src/Composer/Autoload/AutoloadGenerator.php | 8 +++-- .../Test/Autoload/AutoloadGeneratorTest.php | 34 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 0db4015c3..7ea1a3444 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -940,9 +940,13 @@ INITIALIZER; $packageMap, function ($item) use ($include) { $package = $item[0]; - $name = $package->getName(); + foreach ($package->getNames() as $name) { + if (isset($include[$name])) { + return true; + } + } - return isset($include[$name]); + return false; } ); } diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index 4d672084e..615a613f9 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -14,6 +14,7 @@ namespace Composer\Test\Autoload; use Composer\Autoload\AutoloadGenerator; use Composer\Package\Link; +use Composer\Semver\Constraint\Constraint; use Composer\Util\Filesystem; use Composer\Package\AliasPackage; use Composer\Package\Package; @@ -419,6 +420,39 @@ class AutoloadGeneratorTest extends TestCase $this->assertFileExists($this->vendorDir.'/composer/autoload_classmap.php', "ClassMap file needs to be generated, even if empty."); } + public function testNonDevAutoloadShouldIncludeReplacedPackages() + { + $package = new Package('a', '1.0', '1.0'); + $package->setRequires(array(new Link('a', 'a/a'))); + + $packages = array(); + $packages[] = $a = new Package('a/a', '1.0', '1.0'); + $packages[] = $b = new Package('b/b', '1.0', '1.0'); + + $a->setRequires(array(new Link('a/a', 'b/c'))); + + $b->setAutoload(array('psr-4' => array('B\\' => 'src/'))); + $b->setReplaces( + array(new Link('b/b', 'b/c', new Constraint('==', '1.0'), 'replaces')) + ); + + $this->repository->expects($this->once()) + ->method('getCanonicalPackages') + ->will($this->returnValue($packages)); + + $this->fs->ensureDirectoryExists($this->vendorDir.'/b/b/src/C'); + file_put_contents($this->vendorDir.'/b/b/src/C/C.php', 'generator->dump($this->config, $this->repository, $package, $this->im, 'composer', true, '_5'); + + $this->assertEquals( + array( + 'B\\C\\C' => $this->vendorDir.'/b/b/src/C/C.php', + ), + include $this->vendorDir.'/composer/autoload_classmap.php' + ); + } + public function testPSRToClassMapIgnoresNonExistingDir() { $package = new Package('a', '1.0', '1.0'); From 386382503dfb009f378f8318c2b9b973c3e6aee7 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 20 Aug 2018 22:06:46 +0200 Subject: [PATCH 2/9] Add a test for autoloading if a package is only required via replacing name --- .../Test/Autoload/AutoloadGeneratorTest.php | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php index 615a613f9..c1605bf97 100644 --- a/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php +++ b/tests/Composer/Test/Autoload/AutoloadGeneratorTest.php @@ -453,6 +453,39 @@ class AutoloadGeneratorTest extends TestCase ); } + public function testNonDevAutoloadExclusionWithRecursionReplace() + { + $package = new Package('a', '1.0', '1.0'); + $package->setRequires(array( + new Link('a', 'a/a'), + )); + + $packages = array(); + $packages[] = $a = new Package('a/a', '1.0', '1.0'); + $packages[] = $b = new Package('b/b', '1.0', '1.0'); + $a->setAutoload(array('psr-0' => array('A' => 'src/', 'A\\B' => 'lib/'))); + $a->setRequires(array( + new Link('a/a', 'c/c'), + )); + $b->setAutoload(array('psr-0' => array('B\\Sub\\Name' => 'src/'))); + $b->setReplaces(array( + new Link('b/b', 'c/c'), + )); + + $this->repository->expects($this->once()) + ->method('getCanonicalPackages') + ->will($this->returnValue($packages)); + + $this->fs->ensureDirectoryExists($this->vendorDir.'/composer'); + $this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/src'); + $this->fs->ensureDirectoryExists($this->vendorDir.'/a/a/lib'); + $this->fs->ensureDirectoryExists($this->vendorDir.'/b/b/src'); + + $this->generator->dump($this->config, $this->repository, $package, $this->im, 'composer', false, '_5'); + $this->assertAutoloadFiles('vendors', $this->vendorDir.'/composer'); + $this->assertFileExists($this->vendorDir.'/composer/autoload_classmap.php', "ClassMap file needs to be generated, even if empty."); + } + public function testPSRToClassMapIgnoresNonExistingDir() { $package = new Package('a', '1.0', '1.0'); From 50cb5fe3daa8e29b1de19cc24dddd278422b8ddd Mon Sep 17 00:00:00 2001 From: Sascha Egerer Date: Wed, 12 Dec 2018 16:21:15 +0100 Subject: [PATCH 3/9] Update all whitelist matching root dependencies The update command can receive a pattern like `vendor/prefix-*` to update all matching packages. This has not worked if multiple packages, depending on each other, where matched to the given pattern. No package has been updated in this case as only the first package matching the pattern was added to the whitelist. --- src/Composer/Installer.php | 2 +- ...elist-patterns-with-root-dependencies.test | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index bd0d22e3c..12f071c51 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -1332,8 +1332,8 @@ class Installer $whitelistPatternRegexp = BasePackage::packageNameToRegexp($packageName); foreach ($rootRequiredPackageNames as $rootRequiredPackageName) { if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) { + $depPackages = array_merge($pool->whatProvides($rootRequiredPackageName)); $nameMatchesRequiredPackage = true; - break; } } } diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test new file mode 100644 index 000000000..360ef49f5 --- /dev/null +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test @@ -0,0 +1,45 @@ +--TEST-- +Update with a package whitelist only updates those packages and their dependencies matching the pattern +--COMPOSER-- +{ + "repositories": [ + { + "type": "package", + "package": [ + { "name": "fixed", "version": "1.1.0" }, + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted-component1", "version": "1.1.0", "require": { "whitelisted-component2": "1.1.0" } }, + { "name": "whitelisted-component1", "version": "1.0.0", "require": { "whitelisted-component2": "1.0.0" } }, + { "name": "whitelisted-component2", "version": "1.1.0", "require": { "dependency": "1.1.0" } }, + { "name": "whitelisted-component2", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "dependency", "version": "1.1.0" }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.1.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.1.0" }, + { "name": "unrelated-dependency", "version": "1.0.0" } + ] + } + ], + "require": { + "fixed": "1.*", + "whitelisted-component1": "1.*", + "whitelisted-component2": "1.*", + "unrelated": "1.*" + } +} +--INSTALLED-- +[ + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted-component1", "version": "1.0.0", "require": { "whitelisted-component2": "1.0.0" } }, + { "name": "whitelisted-component2", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.0.0" } +] +--RUN-- +update whitelisted-* --with-dependencies +--EXPECT-- +Updating dependency (1.0.0) to dependency (1.1.0) +Updating whitelisted-component2 (1.0.0) to whitelisted-component2 (1.1.0) +Updating whitelisted-component1 (1.0.0) to whitelisted-component1 (1.1.0) From dc59af555aadcf52ff74735de571f5f5e3318560 Mon Sep 17 00:00:00 2001 From: Sascha Egerer Date: Wed, 12 Dec 2018 17:27:26 +0100 Subject: [PATCH 4/9] Fix invalid call to array_merge --- src/Composer/Installer.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 12f071c51..2046dd1da 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -1323,7 +1323,7 @@ class Installer foreach ($this->updateWhitelist as $packageName => $void) { $packageQueue = new \SplQueue; - $depPackages = $pool->whatProvides($packageName); + $depPackages = [$pool->whatProvides($packageName)]; $nameMatchesRequiredPackage = in_array($packageName, $requiredPackageNames, true); @@ -1332,12 +1332,14 @@ class Installer $whitelistPatternRegexp = BasePackage::packageNameToRegexp($packageName); foreach ($rootRequiredPackageNames as $rootRequiredPackageName) { if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) { - $depPackages = array_merge($pool->whatProvides($rootRequiredPackageName)); + $depPackages[] = $pool->whatProvides($rootRequiredPackageName); $nameMatchesRequiredPackage = true; } } } + $depPackages = array_merge(...$depPackages); + if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) { $this->io->writeError('Package "' . $packageName . '" listed for update is not installed. Ignoring.'); } From 1845adcfbdeeff9884ff4561287a32ffaab25749 Mon Sep 17 00:00:00 2001 From: Sascha Egerer Date: Thu, 13 Dec 2018 13:54:22 +0100 Subject: [PATCH 5/9] Fix update whitelist pattern resolving and add more tests --- src/Composer/Installer.php | 25 +++++----- src/Composer/Package/BasePackage.php | 5 +- ...telist-patterns-with-all-dependencies.test | 46 +++++++++++++++++ ...-whitelist-patterns-with-dependencies.test | 49 +++++++++++++++++++ ...elist-patterns-with-root-dependencies.test | 12 ++++- ...itelist-patterns-without-dependencies.test | 44 +++++++++++++++++ 6 files changed, 165 insertions(+), 16 deletions(-) create mode 100644 tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-all-dependencies.test create mode 100644 tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-dependencies.test create mode 100644 tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-without-dependencies.test diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 2046dd1da..88b4ea1d5 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -1301,11 +1301,6 @@ class Installer $rootRequires = array_merge($rootRequires, $rootDevRequires); - $requiredPackageNames = array(); - foreach ($rootRequires as $require) { - $requiredPackageNames[] = $require->getTarget(); - } - $skipPackages = array(); if (!$this->whitelistAllDependencies) { foreach ($rootRequires as $require) { @@ -1323,22 +1318,26 @@ class Installer foreach ($this->updateWhitelist as $packageName => $void) { $packageQueue = new \SplQueue; - $depPackages = [$pool->whatProvides($packageName)]; - - $nameMatchesRequiredPackage = in_array($packageName, $requiredPackageNames, true); - + $depPackages = $pool->whatProvides($packageName); + $matchesByPattern = []; // check if the name is a glob pattern that did not match directly - if (!$nameMatchesRequiredPackage) { + if (empty($depPackages)) { + $whitelistPatternSearchRegexp = BasePackage::packageNameToRegexp($packageName, '^%s$'); + foreach ($localOrLockRepo->search($whitelistPatternSearchRegexp) as $installedPackage) { + $matchesByPattern[] = $pool->whatProvides($installedPackage['name']); + } $whitelistPatternRegexp = BasePackage::packageNameToRegexp($packageName); foreach ($rootRequiredPackageNames as $rootRequiredPackageName) { if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) { - $depPackages[] = $pool->whatProvides($rootRequiredPackageName); $nameMatchesRequiredPackage = true; + break; } } } - $depPackages = array_merge(...$depPackages); + if (!empty($matchesByPattern)) { + $depPackages = array_merge($depPackages, array_merge(...$matchesByPattern)); + } if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) { $this->io->writeError('Package "' . $packageName . '" listed for update is not installed. Ignoring.'); @@ -1371,7 +1370,7 @@ class Installer continue; } - if (isset($skipPackages[$requirePackage->getName()])) { + if (isset($skipPackages[$requirePackage->getName()]) && !preg_match(BasePackage::packageNameToRegexp($packageName), $requirePackage->getName())) { $this->io->writeError('Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.'); continue; } diff --git a/src/Composer/Package/BasePackage.php b/src/Composer/Package/BasePackage.php index 65ea6860f..f2f5be707 100644 --- a/src/Composer/Package/BasePackage.php +++ b/src/Composer/Package/BasePackage.php @@ -239,12 +239,13 @@ abstract class BasePackage implements PackageInterface * Build a regexp from a package name, expanding * globs as required * * @param string $whiteListedPattern + * @param bool $wrap Wrap the cleaned string by the given string * @return string */ - public static function packageNameToRegexp($whiteListedPattern) + public static function packageNameToRegexp($whiteListedPattern, $wrap = '{^%s$}i') { $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern)); - return "{^" . $cleanedWhiteListedPattern . "$}i"; + return sprintf($wrap, $cleanedWhiteListedPattern); } } diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-all-dependencies.test b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-all-dependencies.test new file mode 100644 index 000000000..8ea177cad --- /dev/null +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-all-dependencies.test @@ -0,0 +1,46 @@ +--TEST-- +Update with a package whitelist pattern and all-dependencies flag updates packages and their dependencies, even if defined as root dependency, matching the pattern +--COMPOSER-- +{ + "repositories": [ + { + "type": "package", + "package": [ + { "name": "fixed", "version": "1.1.0" }, + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted-component1", "version": "1.1.0" }, + { "name": "whitelisted-component1", "version": "1.0.0" }, + { "name": "whitelisted-component2", "version": "1.1.0", "require": { "dependency": "1.*" } }, + { "name": "whitelisted-component2", "version": "1.0.0", "require": { "dependency": "1.*" } }, + { "name": "dependency", "version": "1.1.0" }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.1.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.1.0" }, + { "name": "unrelated-dependency", "version": "1.0.0" } + ] + } + ], + "require": { + "fixed": "1.*", + "whitelisted-component1": "1.*", + "whitelisted-component2": "1.*", + "dependency": "1.*", + "unrelated": "1.*" + } +} +--INSTALLED-- +[ + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted-component1", "version": "1.0.0" }, + { "name": "whitelisted-component2", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.0.0" } +] +--RUN-- +update whitelisted-* --with-all-dependencies +--EXPECT-- +Updating whitelisted-component1 (1.0.0) to whitelisted-component1 (1.1.0) +Updating dependency (1.0.0) to dependency (1.1.0) +Updating whitelisted-component2 (1.0.0) to whitelisted-component2 (1.1.0) diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-dependencies.test b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-dependencies.test new file mode 100644 index 000000000..c685f14ce --- /dev/null +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-dependencies.test @@ -0,0 +1,49 @@ +--TEST-- +Update with a package whitelist only updates those packages and their dependencies matching the pattern but no dependencies defined as roo package +--COMPOSER-- +{ + "repositories": [ + { + "type": "package", + "package": [ + { "name": "fixed", "version": "1.1.0" }, + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted-component1", "version": "1.1.0" }, + { "name": "whitelisted-component1", "version": "1.0.0" }, + { "name": "whitelisted-component2", "version": "1.1.0", "require": { "dependency": "1.*", "root-dependency": "1.*" } }, + { "name": "whitelisted-component2", "version": "1.0.0", "require": { "dependency": "1.*", "root-dependency": "1.*" } }, + { "name": "dependency", "version": "1.1.0" }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "root-dependency", "version": "1.1.0" }, + { "name": "root-dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.1.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.1.0" }, + { "name": "unrelated-dependency", "version": "1.0.0" } + ] + } + ], + "require": { + "fixed": "1.*", + "whitelisted-component1": "1.*", + "whitelisted-component2": "1.*", + "root-dependency": "1.*", + "unrelated": "1.*" + } +} +--INSTALLED-- +[ + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted-component1", "version": "1.0.0" }, + { "name": "whitelisted-component2", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "root-dependency", "version": "1.0.0" }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.0.0" } +] +--RUN-- +update whitelisted-* --with-dependencies +--EXPECT-- +Updating whitelisted-component1 (1.0.0) to whitelisted-component1 (1.1.0) +Updating dependency (1.0.0) to dependency (1.1.0) +Updating whitelisted-component2 (1.0.0) to whitelisted-component2 (1.1.0) diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test index 360ef49f5..a24bafb91 100644 --- a/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test @@ -10,8 +10,14 @@ Update with a package whitelist only updates those packages and their dependenci { "name": "fixed", "version": "1.0.0" }, { "name": "whitelisted-component1", "version": "1.1.0", "require": { "whitelisted-component2": "1.1.0" } }, { "name": "whitelisted-component1", "version": "1.0.0", "require": { "whitelisted-component2": "1.0.0" } }, - { "name": "whitelisted-component2", "version": "1.1.0", "require": { "dependency": "1.1.0" } }, + { "name": "whitelisted-component2", "version": "1.1.0", "require": { "dependency": "1.1.0", "whitelisted-component5": "1.0.0" } }, { "name": "whitelisted-component2", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "whitelisted-component3", "version": "1.1.0", "require": { "whitelisted-component4": "1.1.0" } }, + { "name": "whitelisted-component3", "version": "1.0.0", "require": { "whitelisted-component4": "1.0.0" } }, + { "name": "whitelisted-component4", "version": "1.1.0" }, + { "name": "whitelisted-component4", "version": "1.0.0" }, + { "name": "whitelisted-component5", "version": "1.1.0" }, + { "name": "whitelisted-component5", "version": "1.0.0" }, { "name": "dependency", "version": "1.1.0" }, { "name": "dependency", "version": "1.0.0" }, { "name": "unrelated", "version": "1.1.0", "require": { "unrelated-dependency": "1.*" } }, @@ -25,6 +31,7 @@ Update with a package whitelist only updates those packages and their dependenci "fixed": "1.*", "whitelisted-component1": "1.*", "whitelisted-component2": "1.*", + "whitelisted-component3": "1.0.0", "unrelated": "1.*" } } @@ -33,6 +40,9 @@ Update with a package whitelist only updates those packages and their dependenci { "name": "fixed", "version": "1.0.0" }, { "name": "whitelisted-component1", "version": "1.0.0", "require": { "whitelisted-component2": "1.0.0" } }, { "name": "whitelisted-component2", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "whitelisted-component3", "version": "1.0.0", "require": { "whitelisted-component4": "1.0.0" } }, + { "name": "whitelisted-component4", "version": "1.0.0" }, + { "name": "whitelisted-component5", "version": "1.0.0" }, { "name": "dependency", "version": "1.0.0" }, { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, { "name": "unrelated-dependency", "version": "1.0.0" } diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-without-dependencies.test b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-without-dependencies.test new file mode 100644 index 000000000..e5551b43f --- /dev/null +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-without-dependencies.test @@ -0,0 +1,44 @@ +--TEST-- +Update with a package whitelist only updates those packages matching the pattern +--COMPOSER-- +{ + "repositories": [ + { + "type": "package", + "package": [ + { "name": "fixed", "version": "1.1.0" }, + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted-component1", "version": "1.1.0" }, + { "name": "whitelisted-component1", "version": "1.0.0" }, + { "name": "whitelisted-component2", "version": "1.1.0", "require": { "dependency": "1.*" } }, + { "name": "whitelisted-component2", "version": "1.0.0", "require": { "dependency": "1.*" } }, + { "name": "dependency", "version": "1.1.0" }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.1.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.1.0" }, + { "name": "unrelated-dependency", "version": "1.0.0" } + ] + } + ], + "require": { + "fixed": "1.*", + "whitelisted-component1": "1.*", + "whitelisted-component2": "1.*", + "unrelated": "1.*" + } +} +--INSTALLED-- +[ + { "name": "fixed", "version": "1.0.0" }, + { "name": "whitelisted-component1", "version": "1.0.0" }, + { "name": "whitelisted-component2", "version": "1.0.0", "require": { "dependency": "1.0.0" } }, + { "name": "dependency", "version": "1.0.0" }, + { "name": "unrelated", "version": "1.0.0", "require": { "unrelated-dependency": "1.*" } }, + { "name": "unrelated-dependency", "version": "1.0.0" } +] +--RUN-- +update whitelisted-* +--EXPECT-- +Updating whitelisted-component1 (1.0.0) to whitelisted-component1 (1.1.0) +Updating whitelisted-component2 (1.0.0) to whitelisted-component2 (1.1.0) From 82ecf95a3cf6e020a97cbbf1206771925c2cde35 Mon Sep 17 00:00:00 2001 From: Sascha Egerer Date: Mon, 17 Dec 2018 15:21:03 +0100 Subject: [PATCH 6/9] Add PHP 5.3 compatibility --- src/Composer/Installer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 88b4ea1d5..b4885e76c 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -1319,7 +1319,7 @@ class Installer $packageQueue = new \SplQueue; $depPackages = $pool->whatProvides($packageName); - $matchesByPattern = []; + $matchesByPattern = array(); // check if the name is a glob pattern that did not match directly if (empty($depPackages)) { $whitelistPatternSearchRegexp = BasePackage::packageNameToRegexp($packageName, '^%s$'); @@ -1336,7 +1336,7 @@ class Installer } if (!empty($matchesByPattern)) { - $depPackages = array_merge($depPackages, array_merge(...$matchesByPattern)); + $depPackages = array_merge($depPackages, call_user_func_array('array_merge', $matchesByPattern)); } if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) { From 1f97ffdcd700df530376f7a5e013c9a78ee0d93b Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Mon, 28 Jan 2019 17:54:32 +0100 Subject: [PATCH 7/9] Add some docs --- src/Composer/Installer.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index b4885e76c..f38086611 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -1322,10 +1322,13 @@ class Installer $matchesByPattern = array(); // check if the name is a glob pattern that did not match directly if (empty($depPackages)) { + // add any installed package matching the whitelisted name/pattern $whitelistPatternSearchRegexp = BasePackage::packageNameToRegexp($packageName, '^%s$'); foreach ($localOrLockRepo->search($whitelistPatternSearchRegexp) as $installedPackage) { $matchesByPattern[] = $pool->whatProvides($installedPackage['name']); } + + // add root requirements which match the whitelisted name/pattern $whitelistPatternRegexp = BasePackage::packageNameToRegexp($packageName); foreach ($rootRequiredPackageNames as $rootRequiredPackageName) { if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) { From 4765a8f21b38b7ee65968569a00fa96d00f9d2f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20K=C3=A4fer?= Date: Fri, 21 Dec 2018 21:57:19 +0100 Subject: [PATCH 8/9] MB to MiB I did not study computer science, so correct me if I'm wrong. But I think you are calculating mebibyte (MiB) not megabyte (MB). Megabyte would be: ... round($valueInByte / 1000 / 1000, 2).'MB ... Or is there some specific standard you follow? According to https://en.wikipedia.org/wiki/Binary_prefix both calculations (yours and mine) are correct in a way but I find yours to be not completely clear. --- src/Composer/Console/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index e6ff7da9d..ccf83c943 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -262,7 +262,7 @@ class Application extends BaseApplication } if (isset($startTime)) { - $io->writeError('Memory usage: '.round(memory_get_usage() / 1024 / 1024, 2).'MB (peak: '.round(memory_get_peak_usage() / 1024 / 1024, 2).'MB), time: '.round(microtime(true) - $startTime, 2).'s'); + $io->writeError('Memory usage: '.round(memory_get_usage() / 1024 / 1024, 2).'MiB (peak: '.round(memory_get_peak_usage() / 1024 / 1024, 2).'MiB), time: '.round(microtime(true) - $startTime, 2).'s'); } restore_error_handler(); From e0c44f2a25dfca01394dd497ee302ce7fbe1d595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20K=C3=A4fer?= Date: Fri, 28 Dec 2018 15:07:21 +0100 Subject: [PATCH 9/9] Another MB to MiB --- src/Composer/IO/ConsoleIO.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/IO/ConsoleIO.php b/src/Composer/IO/ConsoleIO.php index c0f235659..8b29177d5 100644 --- a/src/Composer/IO/ConsoleIO.php +++ b/src/Composer/IO/ConsoleIO.php @@ -153,7 +153,7 @@ class ConsoleIO extends BaseIO $memoryUsage = memory_get_usage() / 1024 / 1024; $timeSpent = microtime(true) - $this->startTime; $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) { - return sprintf('[%.1fMB/%.2fs] %s', $memoryUsage, $timeSpent, $message); + return sprintf('[%.1fMiB/%.2fs] %s', $memoryUsage, $timeSpent, $message); }, (array) $messages); }