diff --git a/src/Composer/DependencyResolver/Pool.php b/src/Composer/DependencyResolver/Pool.php index b88666dda..c6f328c5e 100644 --- a/src/Composer/DependencyResolver/Pool.php +++ b/src/Composer/DependencyResolver/Pool.php @@ -13,6 +13,7 @@ namespace Composer\DependencyResolver; use Composer\Package\BasePackage; +use Composer\Package\AliasPackage; use Composer\Package\Version\VersionParser; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Link; @@ -64,8 +65,9 @@ class Pool * Adds a repository and its packages to this package pool * * @param RepositoryInterface $repo A package repository + * @param array $aliases */ - public function addRepository(RepositoryInterface $repo) + public function addRepository(RepositoryInterface $repo, $aliases = array()) { if ($repo instanceof CompositeRepository) { $repos = $repo->getRepositories(); @@ -81,7 +83,8 @@ class Pool if ($repo instanceof StreamableRepositoryInterface) { foreach ($repo->getMinimalPackages() as $package) { $name = $package['name']; - $stability = VersionParser::parseStability($package['version']); + $version = $package['version']; + $stability = VersionParser::parseStability($version); if ( // always allow exempt repos $exempt @@ -114,6 +117,35 @@ class Pool foreach (array_keys($names) as $name) { $this->packageByName[$name][] =& $this->packages[$id-2]; } + + // handle root package aliases + if (isset($aliases[$name][$version])) { + $alias = $package; + $alias['version'] = $aliases[$name][$version]['alias_normalized']; + $alias['alias'] = $aliases[$name][$version]['alias']; + $alias['alias_of'] = $package['id']; + $alias['id'] = $id++; + $alias['root_alias'] = true; + $this->packages[] = $alias; + + foreach (array_keys($names) as $name) { + $this->packageByName[$name][] =& $this->packages[$id-2]; + } + } + + // handle normal package aliases + if (isset($package['alias'])) { + $alias = $package; + $alias['version'] = $package['alias_normalized']; + $alias['alias'] = $package['alias']; + $alias['alias_of'] = $package['id']; + $alias['id'] = $id++; + $this->packages[] = $alias; + + foreach (array_keys($names) as $name) { + $this->packageByName[$name][] =& $this->packages[$id-2]; + } + } } } } else { @@ -137,6 +169,22 @@ class Pool foreach ($package->getNames() as $name) { $this->packageByName[$name][] = $package; } + + // handle root package aliases + if (isset($aliases[$name][$package->getVersion()])) { + $alias = $aliases[$name][$package->getVersion()]; + $package->setAlias($alias['alias_normalized']); + $package->setPrettyAlias($alias['alias']); + $package->getRepository()->addPackage($aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias'])); + $aliasPackage->setRootPackageAlias(true); + $aliasPackage->setId($id++); + + $this->packages[] = $aliasPackage; + + foreach ($aliasPackage->getNames() as $name) { + $this->packageByName[$name][] = $aliasPackage; + } + } } } } @@ -267,7 +315,20 @@ class Pool private function ensurePackageIsLoaded($data) { if (is_array($data)) { - $data = $this->packages[$data['id'] - 1] = $data['repo']->loadPackage($data, $data['id']); + if (isset($data['alias_of'])) { + // TODO move to $repo->loadAliasPackage? + $aliasOf = $this->packageById($data['alias_of']); + $rootAlias = !empty($data['root_alias']); + $package = $this->packages[$data['id'] - 1] = new AliasPackage($aliasOf, $data['version'], $data['alias']); + $package->setId($data['id']); + $package->setRootPackageAlias($rootAlias); + + return $package; + } + + $package = $this->packages[$data['id'] - 1] = $data['repo']->loadPackage($data, $data['id']); + + return $package; } return $data; diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 6d70126fb..09f8a77f4 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -244,9 +244,9 @@ class Installer // creating repository pool $pool = new Pool($minimumStability, $stabilityFlags); - $pool->addRepository($installedRepo); + $pool->addRepository($installedRepo, $aliases); foreach ($this->repositoryManager->getRepositories() as $repository) { - $pool->addRepository($repository); + $pool->addRepository($repository, $aliases); } // creating requirements request @@ -276,11 +276,8 @@ class Installer foreach ($lockedPackages as $package) { $version = $package->getVersion(); - foreach ($aliases as $alias) { - if ($alias['package'] === $package->getName() && $alias['version'] === $package->getVersion()) { - $version = $alias['alias_normalized']; - break; - } + if (isset($aliases[$package->getName()][$version])) { + $version = $aliases[$package->getName()][$version]['alias_normalized']; } $constraint = new VersionConstraint('=', $version); $request->install($package->getName(), $constraint); @@ -495,11 +492,11 @@ class Installer $aliases = $this->package->getAliases(); } + $normalizedAliases = array(); + foreach ($aliases as $alias) { - $packages = array_merge( - $platformRepo->findPackages($alias['package'], $alias['version']), - $this->repositoryManager->findPackages($alias['package'], $alias['version']) - ); + $normalizedAliases[$alias['package']][$alias['version']] = array('alias' => $alias['alias'], 'alias_normalized' => $alias['alias_normalized']); + $packages = $platformRepo->findPackages($alias['package'], $alias['version']); foreach ($packages as $package) { $package->setAlias($alias['alias_normalized']); $package->setPrettyAlias($alias['alias']); @@ -508,7 +505,7 @@ class Installer } } - return $aliases; + return $normalizedAliases; } private function isUpdateable(PackageInterface $package) diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index ee4558e23..9b3d2cd25 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -177,11 +177,22 @@ class Locker 'hash' => $this->hash, 'packages' => null, 'packages-dev' => null, - 'aliases' => $aliases, + 'aliases' => array(), 'minimum-stability' => $minimumStability, 'stability-flags' => $stabilityFlags, ); + foreach ($aliases as $package => $versions) { + foreach ($versions as $version => $alias) { + $lock['aliases'][] = array( + 'alias' => $alias['alias'], + 'alias_normalized' => $alias['alias_normalized'], + 'version' => $version, + 'package' => $package, + ); + } + } + $lock['packages'] = $this->lockPackages($packages); if (null !== $devPackages) { $lock['packages-dev'] = $this->lockPackages($devPackages); diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 5b74bc8af..816ed4463 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -107,6 +107,32 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository $data['provide'] = $package['provide']; } + // add branch aliases + if ('dev-' === substr($package['version'], 0, 4) && isset($package['extra']['branch-alias']) && is_array($package['extra']['branch-alias'])) { + foreach ($package['extra']['branch-alias'] as $sourceBranch => $targetBranch) { + // ensure it is an alias to a -dev package + if ('-dev' !== substr($targetBranch, -4)) { + continue; + } + // normalize without -dev and ensure it's a numeric branch that is parseable + $validatedTargetBranch = $versionParser->normalizeBranch(substr($targetBranch, 0, -4)); + if ('-dev' !== substr($validatedTargetBranch, -4)) { + continue; + } + + // ensure that it is the current branch aliasing itself + if (strtolower($package['version']) !== strtolower($sourceBranch)) { + continue; + } + + $alias = preg_replace('{(\.9{7})+}', '.x', $validatedTargetBranch); + $aliasNormalized = $validatedTargetBranch; + $data['alias'] = $alias; + $data['alias_normalized'] = $aliasNormalized; + break; + } + } + $this->minimalPackages[] = $data; } @@ -115,9 +141,9 @@ class ComposerRepository extends ArrayRepository implements NotifiableRepository public function loadPackage(array $data, $id) { - $package = $this->loader->load($data); + $package = $this->loader->load($data['raw']); $package->setId($id); - $package->setRepository($data['repo']); + $package->setRepository($this); return $package; }