Browse Source

Merge remote-tracking branch 'grasmash/issue-6661-whitelist-all-deps'

Jordi Boggiano 7 years ago
parent
commit
9df22654c3

+ 4 - 3
doc/03-cli.md

@@ -155,7 +155,8 @@ php composer.phar update vendor/*
 * **--no-progress:** Removes the progress display that can mess with some
   terminals or scripts which don't handle backspace characters.
 * **--no-suggest:** Skips suggested packages in the output.
-* **--with-dependencies:** Add also all dependencies of whitelisted packages to the whitelist.
+* **--with-dependencies:** Add also dependencies of whitelisted packages to the whitelist, except those that are root requirements.
+* **--with-all-dependencies:** Add also all dependencies of whitelisted packages to the whitelist, including those that are root requirements.
 * **--optimize-autoloader (-o):** Convert PSR-0/4 autoloading to classmap to get a faster
   autoloader. This is recommended especially for production, but can take
   a bit of time to run so it is currently not done by default.
@@ -201,8 +202,8 @@ php composer.phar require vendor/package:2.* vendor/package2:dev-master
 * **--no-update:** Disables the automatic update of the dependencies.
 * **--no-scripts:** Skips execution of scripts defined in `composer.json`.
 * **--update-no-dev:** Run the dependency update with the `--no-dev` option.
-* **--update-with-dependencies:** Also update dependencies of the newly
-  required packages.
+* **--update-with-dependencies:** Also update dependencies of the newly required packages, except those that are root requirements.
+* **--update-with-all-dependencies:** Also update dependencies of the newly required packages, including those that are root requirements.
 * **--ignore-platform-reqs:** ignore `php`, `hhvm`, `lib-*` and `ext-*`
   requirements and force the installation even if the local machine does not
   fulfill these. See also the [`platform`](06-config.md#platform) config option.

+ 1 - 1
src/Composer/Command/RemoveCommand.php

@@ -131,7 +131,7 @@ EOT
             ->setApcuAutoloader($apcu)
             ->setUpdate(true)
             ->setUpdateWhitelist($packages)
-            ->setWhitelistDependencies(!$input->getOption('no-update-with-dependencies'))
+            ->setWhitelistNonRootDependencies(!$input->getOption('no-update-with-dependencies'))
             ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
             ->setRunScripts(!$input->getOption('no-scripts'))
         ;

+ 4 - 2
src/Composer/Command/RequireCommand.php

@@ -47,7 +47,8 @@ class RequireCommand extends InitCommand
                 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
                 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
                 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
-                new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies.'),
+                new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated, except those that are root requirements.'),
+                new InputOption('update-with-all-dependencies', null, InputOption::VALUE_NONE, 'Allows all inherited dependencies to be updated, including those that are root requirements.'),
                 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
                 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
                 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
@@ -169,7 +170,8 @@ EOT
             ->setApcuAutoloader($apcu)
             ->setUpdate(true)
             ->setUpdateWhitelist(array_keys($requirements))
-            ->setWhitelistDependencies($input->getOption('update-with-dependencies'))
+            ->setWhitelistNonRootDependencies($input->getOption('update-with-dependencies'))
+            ->setWhitelistAllDependencies($input->getOption('update-with-all-dependencies'))
             ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
             ->setPreferStable($input->getOption('prefer-stable'))
             ->setPreferLowest($input->getOption('prefer-lowest'))

+ 4 - 2
src/Composer/Command/UpdateCommand.php

@@ -49,7 +49,8 @@ class UpdateCommand extends BaseCommand
                 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
                 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
                 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
-                new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'),
+                new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also dependencies of whitelisted packages to the whitelist, except those defined in root package.'),
+                new InputOption('with-all-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist, including those defined in root package.'),
                 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
                 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
                 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
@@ -146,7 +147,8 @@ EOT
             ->setApcuAutoloader($apcu)
             ->setUpdate(true)
             ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages)
-            ->setWhitelistDependencies($input->getOption('with-dependencies'))
+            ->setWhitelistNonRootDependencies($input->getOption('with-dependencies'))
+            ->setWhitelistAllDependencies($input->getOption('with-all-dependencies'))
             ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
             ->setPreferStable($input->getOption('prefer-stable'))
             ->setPreferLowest($input->getOption('prefer-lowest'))

+ 32 - 9
src/Composer/Installer.php

@@ -125,7 +125,8 @@ class Installer
      * @var array|null
      */
     protected $updateWhitelist = null;
-    protected $whitelistDependencies = false;
+    protected $whitelistNonRootDependencies = false;
+    protected $whitelistAllDependencies = false;
 
     /**
      * @var SuggestedPackagesReporter
@@ -1283,7 +1284,7 @@ class Installer
      *
      * Packages which are listed as requirements in the root package will be
      * skipped including their dependencies, unless they are listed in the
-     * update whitelist themselves.
+     * update whitelist themselves or $whitelistAllDependencies is true.
      *
      * @param RepositoryInterface $localOrLockRepo Use the locked repo if available, otherwise installed repo will do
      *                                             As we want the most accurate package list to work with, and installed
@@ -1305,8 +1306,10 @@ class Installer
         }
 
         $skipPackages = array();
-        foreach ($rootRequires as $require) {
-            $skipPackages[$require->getTarget()] = true;
+        if (!$this->whitelistAllDependencies) {
+          foreach ($rootRequires as $require) {
+            $skipPackages[$require->getTarget()] = TRUE;
+          }
         }
 
         $pool = new Pool('dev');
@@ -1351,7 +1354,7 @@ class Installer
                 $seen[$package->getId()] = true;
                 $this->updateWhitelist[$package->getName()] = true;
 
-                if (!$this->whitelistDependencies) {
+                if (!$this->whitelistNonRootDependencies && !$this->whitelistAllDependencies) {
                     continue;
                 }
 
@@ -1652,14 +1655,34 @@ class Installer
     }
 
     /**
-     * Should dependencies of whitelisted packages be updated recursively?
+     * Should indirect dependencies of whitelisted packages be updated?
+     *
+     * This will NOT whitelist any dependencies that are also directly defined
+     * in the root package.
+     *
+     * @param  bool      $updateNonRootDependencies
+     *
+     * @return Installer
+     */
+    public function setWhitelistNonRootDependencies($updateNonRootDependencies = true)
+    {
+        $this->whitelistNonRootDependencies = (bool) $updateNonRootDependencies;
+
+        return $this;
+    }
+
+    /**
+     * Should all dependencies of whitelisted packages be updated recursively?
+     *
+     * This will NOT whitelist any dependencies that are also defined in the
+     * root package.
      *
-     * @param  bool      $updateDependencies
+     * @param  bool      $updateAllDependencies
      * @return Installer
      */
-    public function setWhitelistDependencies($updateDependencies = true)
+    public function setWhitelistAllDependencies($updateAllDependencies = true)
     {
-        $this->whitelistDependencies = (bool) $updateDependencies;
+        $this->whitelistAllDependencies = (bool) $updateAllDependencies;
 
         return $this;
     }

+ 44 - 0
tests/Composer/Test/Fixtures/installer/update-with-all-dependencies.test

@@ -0,0 +1,44 @@
+--TEST--
+
+See Github issue #6661 ( github.com/composer/composer/issues/6661 ).
+
+When `--with-all-dependencies` is used, Composer\Installer::whitelistUpdateDependencies should update the dependencies of all whitelisted packages, even if the dependency is a root requirement.
+
+--COMPOSER--
+{
+    "repositories": [
+        {
+            "type": "package",
+            "package": [
+                { "name": "a", "version": "1.0.0" },
+                { "name": "a", "version": "1.1.0" },
+                { "name": "b", "version": "1.0.0", "require": { "a": "~1.0" } },
+                { "name": "b", "version": "1.1.0", "require": { "a": "~1.1" } }
+            ]
+        }
+    ],
+    "require": {
+        "a": "~1.0",
+        "b": "~1.0"
+    }
+}
+
+--INSTALLED--
+[
+    { "name": "a", "version": "1.0.0" },
+    { "name": "b", "version": "1.0.0", "require": { "a": "~1.0" } }
+]
+
+--RUN--
+update b --with-all-dependencies
+
+--EXPECT-OUTPUT--
+Loading composer repositories with package information
+Updating dependencies (including require-dev)
+Package operations: 0 installs, 2 updates, 0 removals
+Writing lock file
+Generating autoload files
+
+--EXPECT--
+Updating a (1.0.0) to a (1.1.0)
+Updating b (1.0.0) to b (1.1.0)

+ 2 - 1
tests/Composer/Test/InstallerTest.php

@@ -224,7 +224,8 @@ class InstallerTest extends TestCase
                 ->setUpdate(true)
                 ->setDryRun($input->getOption('dry-run'))
                 ->setUpdateWhitelist($input->getArgument('packages'))
-                ->setWhitelistDependencies($input->getOption('with-dependencies'))
+                ->setWhitelistNonRootDependencies($input->getOption('with-dependencies'))
+                ->setWhitelistAllDependencies($input->getOption('with-all-dependencies'))
                 ->setPreferStable($input->getOption('prefer-stable'))
                 ->setPreferLowest($input->getOption('prefer-lowest'))
                 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'));