Browse Source

Added references for dev versions, fixes #599

dev-<branch> and <n.m>.x-dev versions can now have a #<reference> appended
to them. This reference being a git/hg commit hash, or svn revision.
Jordi Boggiano 13 years ago
parent
commit
ba29b4bf94

+ 1 - 0
CHANGELOG.md

@@ -1,5 +1,6 @@
 * 1.0.0-alpha4
 
+  * Schema: Added references for dev versions, requiring 'dev-master#abcdef' for example will force the abcdef commit
   * Added caching of GitHub metadata (faster startup time with custom GitHub VCS repos)
 
 * 1.0.0-alpha3 (2012-05-13)

+ 49 - 26
src/Composer/Installer.php

@@ -294,42 +294,50 @@ class Installer
         }
 
         // force dev packages to be updated if we update or install from a (potentially new) lock
-        if ($this->update || $installFromLock) {
-            foreach ($localRepo->getPackages() as $package) {
-                // skip non-dev packages
-                if (!$package->isDev()) {
-                    continue;
+        foreach ($localRepo->getPackages() as $package) {
+            // skip non-dev packages
+            if (!$package->isDev()) {
+                continue;
+            }
+
+            // skip packages that will be updated/uninstalled
+            foreach ($operations as $operation) {
+                if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
+                    || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
+                ) {
+                    continue 2;
                 }
+            }
 
-                // skip packages that will be updated/uninstalled
-                foreach ($operations as $operation) {
-                    if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
-                        || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
-                    ) {
-                        continue 2;
+            // force update to locked version if it does not match the installed version
+            if ($installFromLock) {
+                $lockData = $this->locker->getLockData();
+                unset($lockedReference);
+                foreach ($lockData['packages'] as $lockedPackage) {
+                    if (!empty($lockedPackage['source-reference']) && strtolower($lockedPackage['package']) === $package->getName()) {
+                        $lockedReference = $lockedPackage['source-reference'];
+                        break;
                     }
                 }
-
+                if (isset($lockedReference) && $lockedReference !== $package->getSourceReference()) {
+                    // changing the source ref to update to will be handled in the operations loop below
+                    $operations[] = new UpdateOperation($package, clone $package);
+                }
+            } else {
                 // force update to latest on update
                 if ($this->update) {
                     $newPackage = $this->repositoryManager->findPackage($package->getName(), $package->getVersion());
                     if ($newPackage && $newPackage->getSourceReference() !== $package->getSourceReference()) {
                         $operations[] = new UpdateOperation($package, $newPackage);
                     }
-                } elseif ($installFromLock) {
-                    // force update to locked version if it does not match the installed version
-                    $lockData = $this->locker->getLockData();
-                    unset($lockedReference);
-                    foreach ($lockData['packages'] as $lockedPackage) {
-                        if (!empty($lockedPackage['source-reference']) && strtolower($lockedPackage['package']) === $package->getName()) {
-                            $lockedReference = $lockedPackage['source-reference'];
-                            break;
-                        }
-                    }
-                    if (isset($lockedReference) && $lockedReference !== $package->getSourceReference()) {
-                        // changing the source ref to update to will be handled in the operations loop below
-                        $operations[] = new UpdateOperation($package, $package);
-                    }
+                }
+
+                // force installed package to update to referenced version if it does not match the installed version
+                $references = $this->package->getReferences();
+
+                if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
+                    // changing the source ref to update to will be handled in the operations loop below
+                    $operations[] = new UpdateOperation($package, clone $package);
                 }
             }
         }
@@ -378,7 +386,22 @@ class Installer
                             }
                         }
                     }
+                } else {
+                    // not installing from lock, force dev packages' references if they're in root package refs
+                    $package = null;
+                    if ('update' === $operation->getJobType()) {
+                        $package = $operation->getTargetPackage();
+                    } elseif ('install' === $operation->getJobType()) {
+                        $package = $operation->getPackage();
+                    }
+                    if ($package && $package->isDev()) {
+                        $references = $this->package->getReferences();
+                        if (isset($references[$package->getName()])) {
+                            $package->setSourceReference($references[$package->getName()]);
+                        }
+                    }
                 }
+
                 $this->installationManager->execute($localRepo, $operation);
 
                 $event = 'Composer\Script\ScriptEvents::POST_PACKAGE_'.strtoupper($operation->getJobType());

+ 20 - 7
src/Composer/Package/Loader/RootPackageLoader.php

@@ -63,17 +63,18 @@ class RootPackageLoader extends ArrayLoader
 
         $aliases = array();
         $stabilityFlags = array();
-        if (isset($config['require'])) {
-            $aliases = $this->extractAliases($config['require'], $aliases);
-            $stabilityFlags = $this->extractStabilityFlags($config['require'], $stabilityFlags);
-        }
-        if (isset($config['require-dev'])) {
-            $aliases = $this->extractAliases($config['require-dev'], $aliases);
-            $stabilityFlags = $this->extractStabilityFlags($config['require-dev'], $stabilityFlags);
+        $references = array();
+        foreach (array('require', 'require-dev') as $linkType) {
+            if (isset($config[$linkType])) {
+                $aliases = $this->extractAliases($config[$linkType], $aliases);
+                $stabilityFlags = $this->extractStabilityFlags($config[$linkType], $stabilityFlags);
+                $references = $this->extractReferences($config[$linkType], $references);
+            }
         }
 
         $package->setAliases($aliases);
         $package->setStabilityFlags($stabilityFlags);
+        $package->setReferences($references);
 
         if (isset($config['minimum-stability'])) {
             $package->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
@@ -145,4 +146,16 @@ class RootPackageLoader extends ArrayLoader
 
         return $stabilityFlags;
     }
+
+    private function extractReferences(array $requires, array $references)
+    {
+        foreach ($requires as $reqName => $reqVersion) {
+            if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === ($stabilityName = VersionParser::parseStability($reqVersion))) {
+                $name = strtolower($reqName);
+                $references[$name] = $match[1];
+            }
+        }
+
+        return $references;
+    }
 }

+ 19 - 0
src/Composer/Package/MemoryPackage.php

@@ -51,6 +51,7 @@ class MemoryPackage extends BasePackage
     // TODO BC change dev to stable end of june?
     protected $minimumStability = 'dev';
     protected $stabilityFlags = array();
+    protected $references = array();
 
     protected $requires = array();
     protected $conflicts = array();
@@ -637,6 +638,24 @@ class MemoryPackage extends BasePackage
         return $this->stabilityFlags;
     }
 
+    /**
+     * Set the references
+     *
+     * @param array $references
+     */
+    public function setReferences(array $references)
+    {
+        $this->references = $references;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function getReferences()
+    {
+        return $this->references;
+    }
+
     /**
      * Set the autoload mapping
      *

+ 21 - 0
tests/Composer/Test/Fixtures/installer/install-reference.test

@@ -0,0 +1,21 @@
+--TEST--
+Installs a dev package forcing it's reference
+--COMPOSER--
+{
+    "repositories": [
+        {
+            "type": "package",
+            "package": [
+                {
+                    "name": "a/a", "version": "dev-master",
+                    "source": { "reference": "abc123", "url": "", "type": "git" }
+                }
+            ]
+        }
+    ],
+    "require": {
+        "a/a": "dev-master#def000"
+    }
+}
+--EXPECT--
+Installing a/a (dev-master def000)

+ 28 - 0
tests/Composer/Test/Fixtures/installer/update-reference.test

@@ -0,0 +1,28 @@
+--TEST--
+Updates a dev package forcing it's reference
+--COMPOSER--
+{
+    "repositories": [
+        {
+            "type": "package",
+            "package": [
+                {
+                    "name": "a/a", "version": "dev-master",
+                    "source": { "reference": "abc123", "url": "", "type": "git" }
+                }
+            ]
+        }
+    ],
+    "require": {
+        "a/a": "dev-master#def000"
+    }
+}
+--INSTALLED--
+[
+    {
+        "name": "a/a", "version": "dev-master",
+        "source": { "reference": "abc123", "url": "", "type": "git" }
+    }
+]
+--EXPECT--
+Updating a/a (dev-master abc123) to a/a (dev-master def000)