Browse Source

Merge branch '1.8'

Jordi Boggiano 6 years ago
parent
commit
81de5f82aa

+ 1 - 1
src/Composer/Console/Application.php

@@ -271,7 +271,7 @@ class Application extends BaseApplication
             }
 
             if (isset($startTime)) {
-                $io->writeError('<info>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('<info>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();

+ 1 - 1
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);
         }
 

+ 14 - 10
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) {
@@ -1324,11 +1319,16 @@ class Installer
             $packageQueue = new \SplQueue;
 
             $depPackages = $pool->whatProvides($packageName);
-
-            $nameMatchesRequiredPackage = in_array($packageName, $requiredPackageNames, true);
-
+            $matchesByPattern = array();
             // check if the name is a glob pattern that did not match directly
-            if (!$nameMatchesRequiredPackage) {
+            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)) {
@@ -1338,6 +1338,10 @@ class Installer
                 }
             }
 
+            if (!empty($matchesByPattern)) {
+                $depPackages = array_merge($depPackages, call_user_func_array('array_merge', $matchesByPattern));
+            }
+
             if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) {
                 $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
             }
@@ -1369,7 +1373,7 @@ class Installer
                             continue;
                         }
 
-                        if (isset($skipPackages[$requirePackage->getName()])) {
+                        if (isset($skipPackages[$requirePackage->getName()]) && !preg_match(BasePackage::packageNameToRegexp($packageName), $requirePackage->getName())) {
                             $this->io->writeError('<warning>Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.</warning>');
                             continue;
                         }

+ 3 - 2
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);
     }
 }

+ 33 - 0
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');

+ 46 - 0
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)

+ 49 - 0
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)

+ 55 - 0
tests/Composer/Test/Fixtures/installer/update-whitelist-patterns-with-root-dependencies.test

@@ -0,0 +1,55 @@
+--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", "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.*" }  },
+                { "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.*",
+        "whitelisted-component3": "1.0.0",
+        "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": "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" }
+]
+--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)

+ 44 - 0
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)