diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ee708109..f3e5abd98 100644 --- a/CHANGELOG.md +++ b/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) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 0eed0050a..6de106741 100644 --- a/src/Composer/Installer.php +++ b/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()); diff --git a/src/Composer/Package/Loader/RootPackageLoader.php b/src/Composer/Package/Loader/RootPackageLoader.php index 1742b5632..4d4df156e 100644 --- a/src/Composer/Package/Loader/RootPackageLoader.php +++ b/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; + } } diff --git a/src/Composer/Package/MemoryPackage.php b/src/Composer/Package/MemoryPackage.php index dcb973a5b..6a1fc58db 100644 --- a/src/Composer/Package/MemoryPackage.php +++ b/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 * diff --git a/tests/Composer/Test/Fixtures/installer/install-reference.test b/tests/Composer/Test/Fixtures/installer/install-reference.test new file mode 100644 index 000000000..433b6fcbd --- /dev/null +++ b/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) diff --git a/tests/Composer/Test/Fixtures/installer/update-reference.test b/tests/Composer/Test/Fixtures/installer/update-reference.test new file mode 100644 index 000000000..c6418a8eb --- /dev/null +++ b/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)