diff --git a/doc/03-cli.md b/doc/03-cli.md index 69f8f58c5..1541c31fe 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -140,7 +140,9 @@ php composer.phar update vendor/* * **--lock:** Only updates the lock file hash to suppress warning about the lock file being out of date. * **--with-dependencies** Add also all dependencies of whitelisted packages to the whitelist. - So all packages with their dependencies are updated recursively. +* **--prefer-stable:** Prefer stable versions of dependencies. +* **--prefer-lowest:** Prefer lowest versions of dependencies. Useful for testing minimal + versions of requirements, generally used with `--prefer-stable`. ## require diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 58459f7a6..35df7e61b 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -309,7 +309,8 @@ class Installer $aliases, $this->package->getMinimumStability(), $this->package->getStabilityFlags(), - $this->package->getPreferStable() + $this->preferStable || $this->package->getPreferStable(), + $this->preferLowest ); if ($updatedLock) { $this->io->write('Writing lock file'); @@ -695,15 +696,18 @@ class Installer private function createPolicy() { - $preferLowest = false; $preferStable = null; + $preferLowest = null; if (!$this->update && $this->locker->isLocked()) { $preferStable = $this->locker->getPreferStable(); + $preferLowest = $this->locker->getPreferLowest(); } - // old lock file without prefer stable will return null + // old lock file without prefer stable/lowest will return null // so in this case we use the composer.json info if (null === $preferStable) { $preferStable = $this->preferStable || $this->package->getPreferStable(); + } + if (null === $preferLowest) { $preferLowest = $this->preferLowest; } diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index 9d49f6eaf..40ff8907c 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -182,6 +182,15 @@ class Locker return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null; } + public function getPreferLowest() + { + $lockData = $this->getLockData(); + + // return null if not set to allow caller logic to choose the + // right behavior since old lock files have no prefer-lowest + return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null; + } + public function getAliases() { $lockData = $this->getLockData(); @@ -213,10 +222,11 @@ class Locker * @param string $minimumStability * @param array $stabilityFlags * @param bool $preferStable + * @param bool $preferLowest * * @return bool */ - public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable) + public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest) { $lock = array( '_readme' => array('This file locks the dependencies of your project to a known state', @@ -229,6 +239,7 @@ class Locker 'minimum-stability' => $minimumStability, 'stability-flags' => $stabilityFlags, 'prefer-stable' => $preferStable, + 'prefer-lowest' => $preferLowest, ); foreach ($aliases as $package => $versions) { diff --git a/tests/Composer/Test/Fixtures/installer/install-dev-using-dist.test b/tests/Composer/Test/Fixtures/installer/install-dev-using-dist.test index af4eed811..ccc9ead1a 100644 --- a/tests/Composer/Test/Fixtures/installer/install-dev-using-dist.test +++ b/tests/Composer/Test/Fixtures/installer/install-dev-using-dist.test @@ -48,6 +48,7 @@ install --prefer-dist "a/a": 20 }, "prefer-stable": false, + "prefer-lowest": false, "platform": [], "platform-dev": [] } diff --git a/tests/Composer/Test/Fixtures/installer/install-from-empty-lock.test b/tests/Composer/Test/Fixtures/installer/install-from-empty-lock.test index 88c3e8fa7..7bb69f131 100644 --- a/tests/Composer/Test/Fixtures/installer/install-from-empty-lock.test +++ b/tests/Composer/Test/Fixtures/installer/install-from-empty-lock.test @@ -25,7 +25,8 @@ Requirements from the composer file are not installed if the lock file is presen "aliases": [], "minimum-stability": "stable", "stability-flags": [], - "prefer-stable": false + "prefer-stable": false, + "prefer-lowest": false } --RUN-- install diff --git a/tests/Composer/Test/Fixtures/installer/install-missing-alias-from-lock.test b/tests/Composer/Test/Fixtures/installer/install-missing-alias-from-lock.test index 298846609..5acb7a069 100644 --- a/tests/Composer/Test/Fixtures/installer/install-missing-alias-from-lock.test +++ b/tests/Composer/Test/Fixtures/installer/install-missing-alias-from-lock.test @@ -33,7 +33,8 @@ Installing an old alias that doesn't exist anymore from a lock is possible "aliases": [], "minimum-stability": "dev", "stability-flags": [], - "prefer-stable": false + "prefer-stable": false, + "prefer-lowest": false } --RUN-- install diff --git a/tests/Composer/Test/Fixtures/installer/partial-update-downgrades-non-whitelisted-unstable.test b/tests/Composer/Test/Fixtures/installer/partial-update-downgrades-non-whitelisted-unstable.test index f9fd5058a..4b2c62a53 100644 --- a/tests/Composer/Test/Fixtures/installer/partial-update-downgrades-non-whitelisted-unstable.test +++ b/tests/Composer/Test/Fixtures/installer/partial-update-downgrades-non-whitelisted-unstable.test @@ -36,6 +36,7 @@ Partial update from lock file should apply lock file and downgrade unstable pack "b/unstable": 15 }, "prefer-stable": false, + "prefer-lowest": false, "platform": [], "platform-dev": [] } @@ -59,6 +60,7 @@ update c/uptodate "minimum-stability": "stable", "stability-flags": [], "prefer-stable": false, + "prefer-lowest": false, "platform": [], "platform-dev": [] } diff --git a/tests/Composer/Test/Fixtures/installer/partial-update-from-lock.test b/tests/Composer/Test/Fixtures/installer/partial-update-from-lock.test index 5b904f9b5..5c3508840 100644 --- a/tests/Composer/Test/Fixtures/installer/partial-update-from-lock.test +++ b/tests/Composer/Test/Fixtures/installer/partial-update-from-lock.test @@ -36,6 +36,7 @@ Partial update from lock file should update everything to the state of the lock, "b/unstable": 15 }, "prefer-stable": false, + "prefer-lowest": false, "platform": [], "platform-dev": [] } @@ -59,6 +60,7 @@ update b/unstable "minimum-stability": "stable", "stability-flags": [], "prefer-stable": false, + "prefer-lowest": false, "platform": [], "platform-dev": [] } diff --git a/tests/Composer/Test/Fixtures/installer/partial-update-without-lock.test b/tests/Composer/Test/Fixtures/installer/partial-update-without-lock.test index 224e58f7d..e931a1f7d 100644 --- a/tests/Composer/Test/Fixtures/installer/partial-update-without-lock.test +++ b/tests/Composer/Test/Fixtures/installer/partial-update-without-lock.test @@ -43,6 +43,7 @@ update b/unstable "minimum-stability": "stable", "stability-flags": [], "prefer-stable": false, + "prefer-lowest": false, "platform": [], "platform-dev": [] } diff --git a/tests/Composer/Test/Fixtures/installer/update-alias-lock.test b/tests/Composer/Test/Fixtures/installer/update-alias-lock.test index bfe0bb8a8..920321a20 100644 --- a/tests/Composer/Test/Fixtures/installer/update-alias-lock.test +++ b/tests/Composer/Test/Fixtures/installer/update-alias-lock.test @@ -39,7 +39,8 @@ Update aliased package does not mess up the lock file "aliases": [], "minimum-stability": "dev", "stability-flags": [], - "prefer-stable": false + "prefer-stable": false, + "prefer-lowest": false } --INSTALLED-- [ @@ -66,6 +67,7 @@ update "minimum-stability": "dev", "stability-flags": [], "prefer-stable": false, + "prefer-lowest": false, "platform": [], "platform-dev": [] } diff --git a/tests/Composer/Test/Fixtures/installer/update-whitelist-reads-lock.test b/tests/Composer/Test/Fixtures/installer/update-whitelist-reads-lock.test index 3bc189015..96036e479 100644 --- a/tests/Composer/Test/Fixtures/installer/update-whitelist-reads-lock.test +++ b/tests/Composer/Test/Fixtures/installer/update-whitelist-reads-lock.test @@ -32,7 +32,8 @@ Limited update takes rules from lock if available, and not from the installed re "aliases": [], "minimum-stability": "stable", "stability-flags": [], - "prefer-stable": false + "prefer-stable": false, + "prefer-lowest": false } --INSTALLED-- [ diff --git a/tests/Composer/Test/Fixtures/installer/updating-dev-from-lock-removes-old-deps.test b/tests/Composer/Test/Fixtures/installer/updating-dev-from-lock-removes-old-deps.test index bd94617bc..04624561d 100644 --- a/tests/Composer/Test/Fixtures/installer/updating-dev-from-lock-removes-old-deps.test +++ b/tests/Composer/Test/Fixtures/installer/updating-dev-from-lock-removes-old-deps.test @@ -20,7 +20,8 @@ Installing locked dev packages should remove old dependencies "aliases": [], "minimum-stability": "dev", "stability-flags": [], - "prefer-stable": false + "prefer-stable": false, + "prefer-lowest": false } --INSTALLED-- [ diff --git a/tests/Composer/Test/Fixtures/installer/updating-dev-updates-url-and-reference.test b/tests/Composer/Test/Fixtures/installer/updating-dev-updates-url-and-reference.test index 849296850..c5c838517 100644 --- a/tests/Composer/Test/Fixtures/installer/updating-dev-updates-url-and-reference.test +++ b/tests/Composer/Test/Fixtures/installer/updating-dev-updates-url-and-reference.test @@ -32,7 +32,8 @@ Updating a dev package for new reference updates the url and reference "aliases": [], "minimum-stability": "dev", "stability-flags": {"a/a":20}, - "prefer-stable": false + "prefer-stable": false, + "prefer-lowest": false } --INSTALLED-- [ @@ -59,6 +60,7 @@ update "minimum-stability": "dev", "stability-flags": {"a/a":20}, "prefer-stable": false, + "prefer-lowest": false, "platform": [], "platform-dev": [] } diff --git a/tests/Composer/Test/Package/LockerTest.php b/tests/Composer/Test/Package/LockerTest.php index 7e1d2d3b1..913868cd1 100644 --- a/tests/Composer/Test/Package/LockerTest.php +++ b/tests/Composer/Test/Package/LockerTest.php @@ -135,9 +135,10 @@ class LockerTest extends \PHPUnit_Framework_TestCase 'platform' => array(), 'platform-dev' => array(), 'prefer-stable' => false, + 'prefer-lowest' => false, )); - $locker->setLockData(array($package1, $package2), array(), array(), array(), array(), 'dev', array(), false); + $locker->setLockData(array($package1, $package2), array(), array(), array(), array(), 'dev', array(), false, false); } public function testLockBadPackages() @@ -156,7 +157,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase $this->setExpectedException('LogicException'); - $locker->setLockData(array($package1), array(), array(), array(), array(), 'dev', array(), false); + $locker->setLockData(array($package1), array(), array(), array(), array(), 'dev', array(), false, false); } public function testIsFresh()