diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 73056d854..8f9c51c51 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -535,8 +535,7 @@ class Installer if ($package && $package->isDev()) { $references = $this->package->getReferences(); if (isset($references[$package->getName()])) { - $package->setSourceReference($references[$package->getName()]); - $package->setDistReference($references[$package->getName()]); + $this->updateInstallReferences($package, $references[$package->getName()]); } } if ('update' === $operation->getJobType() @@ -993,21 +992,38 @@ class Installer $sourceUrl = $package->getSourceUrl(); $newSourceUrl = $newPackage->getSourceUrl(); - if ($sourceUrl !== $newSourceUrl) { - $package->setSourceType($newPackage->getSourceType()); - $package->setSourceUrl($newSourceUrl); - $package->setSourceReference($newPackage->getSourceReference()); - } - - // only update dist url for github/bitbucket dists as they use a combination of dist url + dist reference to install - // but for other urls this is ambiguous and could result in bad outcomes - if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}', $newPackage->getDistUrl())) { - $package->setDistUrl($newPackage->getDistUrl()); - } + $this->updatePackageUrl($package, $newSourceUrl, $newPackage->getSourceType(), $newPackage->getSourceReference(), $newPackage->getDistUrl()); } } } + private function updatePackageUrl(PackageInterface $package, $sourceUrl, $sourceType, $sourceReference, $distUrl) + { + if ($package->getSourceUrl() !== $sourceUrl) { + $package->setSourceType($sourceType); + $package->setSourceUrl($sourceUrl); + $package->setSourceReference($sourceReference); + } + + // only update dist url for github/bitbucket dists as they use a combination of dist url + dist reference to install + // but for other urls this is ambiguous and could result in bad outcomes + if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $distUrl)) { + $package->setDistUrl($distUrl); + $this->updateInstallReferences($package, $sourceReference); + } + } + + private function updateInstallReferences(PackageInterface $package, $reference) + { + $package->setSourceReference($reference); + $package->setDistReference($reference); + + if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $package->getDistUrl())) { + $package->setDistUrl(preg_replace('{(?<=/)[a-f0-9]{40}(?=/|$)}i', $reference, $package->getDistUrl())); + } + } + + /** * @param PlatformRepository $platformRepo * @param array $aliases diff --git a/src/Composer/Installer/BinaryInstaller.php b/src/Composer/Installer/BinaryInstaller.php index a02477bba..bbf57f8bf 100644 --- a/src/Composer/Installer/BinaryInstaller.php +++ b/src/Composer/Installer/BinaryInstaller.php @@ -173,7 +173,7 @@ class BinaryInstaller return "@ECHO OFF\r\n". "setlocal DISABLEDELAYEDEXPANSION\r\n". - "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"')."\r\n". + "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"\'')."\r\n". "{$caller} \"%BIN_TARGET%\" %*\r\n"; } diff --git a/tests/Composer/Test/Fixtures/installer/update-changes-url.test b/tests/Composer/Test/Fixtures/installer/update-changes-url.test new file mode 100644 index 000000000..83e3538b7 --- /dev/null +++ b/tests/Composer/Test/Fixtures/installer/update-changes-url.test @@ -0,0 +1,125 @@ +--TEST-- +Update updates URLs for updated packages if they have changed + +a/a gets everything updated as it updates to a new ref +b/b gets everything updated by updating the package URL directly +c/c is not whitelisted but still gets its URL updated +d/d is dev but with a #ref so it should get URL updated but not the reference +e/e is newly installed with a #ref so it should get the correct URL but with the #111 ref +--COMPOSER-- +{ + "repositories": [ + { + "type": "package", + "package": [ + { + "name": "a/a", "version": "dev-master", + "source": { "reference": "2222222222222222222222222222222222222222", "url": "https://github.com/a/newa", "type": "git" }, + "dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/a/newa/zipball/2222222222222222222222222222222222222222", "type": "zip" } + }, + { + "name": "b/b", "version": "2.0.3", + "source": { "reference": "2222222222222222222222222222222222222222", "url": "https://github.com/b/newb", "type": "git" }, + "dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/b/newb/zipball/2222222222222222222222222222222222222222", "type": "zip" } + }, + { + "name": "c/c", "version": "1.0.0", + "source": { "reference": "2222222222222222222222222222222222222222", "url": "https://github.com/c/newc", "type": "git" }, + "dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/c/newc/zipball/2222222222222222222222222222222222222222", "type": "zip" } + }, + { + "name": "d/d", "version": "dev-master", + "source": { "reference": "2222222222222222222222222222222222222222", "url": "https://github.com/d/newd", "type": "git" }, + "dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/d/newd/zipball/2222222222222222222222222222222222222222", "type": "zip" } + }, + { + "name": "e/e", "version": "dev-master", + "source": { "reference": "2222222222222222222222222222222222222222", "url": "https://github.com/e/newe", "type": "git" }, + "dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/e/newe/zipball/2222222222222222222222222222222222222222", "type": "zip" } + } + ] + } + ], + "require": { + "a/a": "dev-master", + "b/b": "2.0.3", + "c/c": "1.0.0", + "d/d": "dev-master#1111111111111111111111111111111111111111", + "e/e": "dev-master#1111111111111111111111111111111111111111" + } +} +--INSTALLED-- +[ + { + "name": "a/a", "version": "dev-master", + "source": { "reference": "1111111111111111111111111111111111111111", "url": "https://github.com/a/a", "type": "git" }, + "dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/a/a/zipball/1111111111111111111111111111111111111111", "type": "zip" } + }, + { + "name": "b/b", "version": "2.0.3", + "source": { "reference": "1111111111111111111111111111111111111111", "url": "https://github.com/b/b", "type": "git" }, + "dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/b/b/zipball/1111111111111111111111111111111111111111", "type": "zip" } + }, + { + "name": "c/c", "version": "1.0.0", + "source": { "reference": "1111111111111111111111111111111111111111", "url": "https://github.com/c/c", "type": "git" }, + "dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/c/c/zipball/1111111111111111111111111111111111111111", "type": "zip" } + }, + { + "name": "d/d", "version": "dev-master", + "source": { "reference": "1111111111111111111111111111111111111111", "url": "https://github.com/d/d", "type": "git" }, + "dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/d/d/zipball/1111111111111111111111111111111111111111", "type": "zip" } + } +] +--EXPECT-LOCK-- +{ + "packages": [ + { + "name": "a/a", "version": "dev-master", + "source": { "reference": "2222222222222222222222222222222222222222", "url": "https://github.com/a/newa", "type": "git" }, + "dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/a/newa/zipball/2222222222222222222222222222222222222222", "type": "zip", "shasum": null }, + "type": "library" + }, + { + "name": "b/b", "version": "2.0.3", + "source": { "reference": "2222222222222222222222222222222222222222", "url": "https://github.com/b/newb", "type": "git" }, + "dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/b/newb/zipball/2222222222222222222222222222222222222222", "type": "zip", "shasum": null }, + "type": "library" + }, + { + "name": "c/c", "version": "1.0.0", + "source": { "reference": "2222222222222222222222222222222222222222", "url": "https://github.com/c/newc", "type": "git" }, + "dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/c/newc/zipball/2222222222222222222222222222222222222222", "type": "zip", "shasum": null }, + "type": "library" + }, + { + "name": "d/d", "version": "dev-master", + "source": { "reference": "1111111111111111111111111111111111111111", "url": "https://github.com/d/newd", "type": "git" }, + "dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/d/newd/zipball/1111111111111111111111111111111111111111", "type": "zip", "shasum": null }, + "type": "library" + }, + { + "name": "e/e", "version": "dev-master", + "source": { "reference": "1111111111111111111111111111111111111111", "url": "https://github.com/e/newe", "type": "git" }, + "dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/e/newe/zipball/1111111111111111111111111111111111111111", "type": "zip", "shasum": null }, + "type": "library" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "a/a": 20, + "d/d": 20, + "e/e": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} +--RUN-- +update a/a b/b d/d +--EXPECT-- +Installing e/e (dev-master 1111111) +Updating a/a (dev-master 1111111) to a/a (dev-master 2222222)