Browse Source

Normalize URL updates to point to the correct reference and always update URLs consistently, fixes #3849, fixes #4126

Jordi Boggiano 9 years ago
parent
commit
6d20146d08

+ 29 - 13
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

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