diff --git a/src/Composer/DependencyResolver/PoolBuilder.php b/src/Composer/DependencyResolver/PoolBuilder.php index f765d45e4..f4500cc0d 100644 --- a/src/Composer/DependencyResolver/PoolBuilder.php +++ b/src/Composer/DependencyResolver/PoolBuilder.php @@ -441,6 +441,16 @@ class PoolBuilder */ private function isUpdateAllowed(PackageInterface $package) { + // Path repo packages are never loaded from lock, to force them to always remain in sync + // unless symlinking is disabled in which case we probably should rather treat them like + // regular packages + if ($package->getDistType() === 'path') { + $transportOptions = $package->getTransportOptions(); + if (!isset($transportOptions['symlink']) || $transportOptions['symlink'] !== false) { + return true; + } + } + foreach ($this->updateAllowList as $pattern => $void) { $patternRegexp = BasePackage::packageNameToRegexp($pattern); if (preg_match($patternRegexp, $package->getName())) { diff --git a/tests/Composer/Test/Fixtures/installer/partial-update-always-updates-symlinked-path-repos.test b/tests/Composer/Test/Fixtures/installer/partial-update-always-updates-symlinked-path-repos.test new file mode 100644 index 000000000..e30d3a405 --- /dev/null +++ b/tests/Composer/Test/Fixtures/installer/partial-update-always-updates-symlinked-path-repos.test @@ -0,0 +1,63 @@ +--TEST-- +Partial updates always update path repos which are symlinked, but not those which are not + +--COMPOSER-- +{ + "repositories": [ + { + "type": "path", + "url": "Fixtures/functional/installed-versions/plugin-a" + }, + { + "type": "path", + "url": "Fixtures/functional/installed-versions/plugin-b", + "options": { + "symlink": false + } + }, + { + "type": "package", + "package": [ + { "name": "symfony/console", "version": "1.0.0" }, + { "name": "c/uptodate", "version": "2.0.0" } + ] + } + ], + "require": { + "plugin/a": "*", + "plugin/b": "*", + "c/uptodate": "*" + } +} + +--LOCK-- +{ + "packages": [ + { "name": "plugin/a", "version": "1.0.0", "dist": { "type": "path", "url": "..." }, "transport-options": {} }, + { "name": "plugin/b", "version": "1.0.0", "dist": { "type": "path", "url": "..." }, "transport-options": {"symlink": false} }, + { "name": "c/uptodate", "version": "2.0.0" } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} + +--INSTALLED-- +[ + { "name": "plugin/a", "version": "1.0.0" }, + { "name": "plugin/b", "version": "1.0.0" }, + { "name": "c/uptodate", "version": "2.0.0" } +] + +--RUN-- +update c/uptodate + +--EXPECT-- +Installing symfony/console (1.0.0) +Upgrading plugin/a (1.0.0 => 1.1.1)