diff --git a/src/Composer/Command/InstallCommand.php b/src/Composer/Command/InstallCommand.php index 426c1fb9e..6b6120bb8 100644 --- a/src/Composer/Command/InstallCommand.php +++ b/src/Composer/Command/InstallCommand.php @@ -113,10 +113,10 @@ EOT } foreach ($aliases as $alias) { foreach ($repoManager->findPackages($alias['package'], $alias['version']) as $package) { - $package->getRepository()->addPackage(new AliasPackage($package, $alias['alias'])); + $package->getRepository()->addPackage(new AliasPackage($package, $alias['alias_normalized'], $alias['alias'])); } foreach ($repoManager->getLocalRepository()->findPackages($alias['package'], $alias['version']) as $package) { - $repoManager->getLocalRepository()->addPackage(new AliasPackage($package, $alias['alias'])); + $repoManager->getLocalRepository()->addPackage(new AliasPackage($package, $alias['alias_normalized'], $alias['alias'])); $repoManager->getLocalRepository()->removePackage($package); } } diff --git a/src/Composer/Package/AliasPackage.php b/src/Composer/Package/AliasPackage.php index 02c0a9510..b302868ee 100644 --- a/src/Composer/Package/AliasPackage.php +++ b/src/Composer/Package/AliasPackage.php @@ -23,6 +23,7 @@ use Composer\Repository\PlatformRepository; class AliasPackage extends BasePackage { protected $version; + protected $prettyVersion; protected $dev; protected $aliasOf; @@ -38,12 +39,14 @@ class AliasPackage extends BasePackage * * @param PackageInterface $aliasOf The package this package is an alias of * @param string $version The version the alias must report + * @param string $prettyVersion The alias's non-normalized version */ - public function __construct($aliasOf, $version) + public function __construct($aliasOf, $version, $prettyVersion) { parent::__construct($aliasOf->getName()); $this->version = $version; + $this->prettyVersion = $prettyVersion; $this->aliasOf = $aliasOf; $this->dev = 'dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4); @@ -78,7 +81,7 @@ class AliasPackage extends BasePackage */ public function getPrettyVersion() { - return $this->version; + return $this->prettyVersion; } /** @@ -92,7 +95,7 @@ class AliasPackage extends BasePackage /** * {@inheritDoc} */ - function getRequires() + public function getRequires() { return $this->requires; } @@ -100,7 +103,7 @@ class AliasPackage extends BasePackage /** * {@inheritDoc} */ - function getConflicts() + public function getConflicts() { return $this->conflicts; } @@ -108,7 +111,7 @@ class AliasPackage extends BasePackage /** * {@inheritDoc} */ - function getProvides() + public function getProvides() { return $this->provides; } @@ -116,7 +119,7 @@ class AliasPackage extends BasePackage /** * {@inheritDoc} */ - function getReplaces() + public function getReplaces() { return $this->replaces; } @@ -124,7 +127,7 @@ class AliasPackage extends BasePackage /** * {@inheritDoc} */ - function getRecommends() + public function getRecommends() { return $this->recommends; } @@ -132,11 +135,27 @@ class AliasPackage extends BasePackage /** * {@inheritDoc} */ - function getSuggests() + public function getSuggests() { return $this->suggests; } + /** + * {@inheritDoc} + */ + public function getAlias() + { + return ''; + } + + /** + * {@inheritDoc} + */ + public function getPrettyAlias() + { + return ''; + } + /*************************************** * Wrappers around the aliased package * ***************************************/ @@ -173,6 +192,10 @@ class AliasPackage extends BasePackage { return $this->aliasOf->getSourceReference(); } + public function setSourceReference($reference) + { + return $this->aliasOf->setSourceReference($reference); + } public function getDistType() { return $this->aliasOf->getDistType(); diff --git a/src/Composer/Package/Dumper/ArrayDumper.php b/src/Composer/Package/Dumper/ArrayDumper.php index f372929b1..4062d7f8d 100644 --- a/src/Composer/Package/Dumper/ArrayDumper.php +++ b/src/Composer/Package/Dumper/ArrayDumper.php @@ -42,6 +42,12 @@ class ArrayDumper $data['name'] = $package->getPrettyName(); $data['version'] = $package->getPrettyVersion(); $data['version_normalized'] = $package->getVersion(); + + if ($package->getAlias()) { + $data['alias'] = $package->getPrettyAlias(); + $data['alias_normalized'] = $package->getAlias(); + } + if ($package->getTargetDir()) { $data['target-dir'] = $package->getTargetDir(); } diff --git a/src/Composer/Package/Loader/ArrayLoader.php b/src/Composer/Package/Loader/ArrayLoader.php index 98733372b..7c8778af2 100644 --- a/src/Composer/Package/Loader/ArrayLoader.php +++ b/src/Composer/Package/Loader/ArrayLoader.php @@ -134,6 +134,12 @@ class ArrayLoader $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null); } + // load alias for named dev packages + if (!empty($config['alias']) && 'dev-' === substr($package->getPrettyVersion(), 0, 4)) { + $package->setAlias($config['alias_normalized']); + $package->setPrettyAlias($config['alias']); + } + foreach (Package\BasePackage::$supportedLinkTypes as $type => $description) { if (isset($config[$type])) { $method = 'set'.ucfirst($description); diff --git a/src/Composer/Package/Loader/RootPackageLoader.php b/src/Composer/Package/Loader/RootPackageLoader.php index a6865f01e..77b2599fb 100644 --- a/src/Composer/Package/Loader/RootPackageLoader.php +++ b/src/Composer/Package/Loader/RootPackageLoader.php @@ -50,7 +50,8 @@ class RootPackageLoader extends ArrayLoader $aliases[] = array( 'package' => strtolower($reqName), 'version' => $this->versionParser->normalize($match[1]), - 'alias' => $this->versionParser->normalize($match[2]), + 'alias' => $match[2], + 'alias_normalized' => $this->versionParser->normalize($match[2]), ); } } diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index 205372481..81843e8c1 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -14,6 +14,7 @@ namespace Composer\Package; use Composer\Json\JsonFile; use Composer\Repository\RepositoryManager; +use Composer\Package\AliasPackage; /** * Reads/writes project lockfile (composer.lock). @@ -72,10 +73,14 @@ class Locker $lockList = $this->getLockData(); $packages = array(); foreach ($lockList['packages'] as $info) { - $package = $this->repositoryManager->getLocalRepository()->findPackage($info['package'], $info['version']); + $resolvedVersion = !empty($info['alias']) ? $info['alias'] : $info['version']; + $package = $this->repositoryManager->getLocalRepository()->findPackage($info['package'], $resolvedVersion); if (!$package) { $package = $this->repositoryManager->findPackage($info['package'], $info['version']); + if ($package && !empty($info['alias'])) { + $package = new AliasPackage($package, $info['alias'], $info['alias']); + } } if (!$package) { @@ -134,6 +139,9 @@ class Locker if ($package->isDev()) { $spec['source-reference'] = $package->getSourceReference(); } + if ($package->getAlias()) { + $spec['alias'] = $package->getAlias(); + } $lock['packages'][] = $spec; } diff --git a/src/Composer/Package/MemoryPackage.php b/src/Composer/Package/MemoryPackage.php index a2a711027..6a38093a3 100644 --- a/src/Composer/Package/MemoryPackage.php +++ b/src/Composer/Package/MemoryPackage.php @@ -42,6 +42,8 @@ class MemoryPackage extends BasePackage protected $binaries = array(); protected $scripts = array(); protected $aliases = array(); + protected $alias; + protected $prettyAlias; protected $dev; protected $requires = array(); @@ -173,6 +175,38 @@ class MemoryPackage extends BasePackage return $this->aliases; } + /** + * @param string $alias + */ + public function setAlias($alias) + { + $this->alias = $alias; + } + + /** + * {@inheritDoc} + */ + public function getAlias() + { + return $this->alias; + } + + /** + * @param string $prettyAlias + */ + public function setPrettyAlias($prettyAlias) + { + $this->prettyAlias = $prettyAlias; + } + + /** + * {@inheritDoc} + */ + public function getPrettyAlias() + { + return $this->prettyAlias; + } + /** * {@inheritDoc} */ diff --git a/src/Composer/Package/PackageInterface.php b/src/Composer/Package/PackageInterface.php index cf68cc02d..97997f093 100644 --- a/src/Composer/Package/PackageInterface.php +++ b/src/Composer/Package/PackageInterface.php @@ -316,6 +316,20 @@ interface PackageInterface */ function getAuthors(); + /** + * Returns a version this package should be aliased to + * + * @return string + */ + function getAlias(); + + /** + * Returns a non-normalized version this package should be aliased to + * + * @return string + */ + function getPrettyAlias(); + /** * Returns package unique name, constructed from name and version. * diff --git a/src/Composer/Repository/ArrayRepository.php b/src/Composer/Repository/ArrayRepository.php index a46bfd20d..9dfde50fe 100644 --- a/src/Composer/Repository/ArrayRepository.php +++ b/src/Composer/Repository/ArrayRepository.php @@ -12,6 +12,7 @@ namespace Composer\Repository; +use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; @@ -96,6 +97,11 @@ class ArrayRepository implements RepositoryInterface $this->packages[] = $package; } + protected function createAliasPackage(PackageInterface $package) + { + return new AliasPackage($package, $package->getAlias(), $package->getPrettyAlias()); + } + /** * Removes package from repository. * diff --git a/src/Composer/Repository/FilesystemRepository.php b/src/Composer/Repository/FilesystemRepository.php index 73fc37305..7dc4e04a9 100644 --- a/src/Composer/Repository/FilesystemRepository.php +++ b/src/Composer/Repository/FilesystemRepository.php @@ -55,7 +55,12 @@ class FilesystemRepository extends ArrayRepository implements WritableRepository $loader = new ArrayLoader(); foreach ($packages as $package) { - $this->addPackage($loader->load($package)); + $package = $loader->load($package); + if ($package->getAlias()) { + $this->addPackage($this->createAliasPackage($package)); + } else { + $this->addPackage($package); + } } } diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index 2c4175fa0..03a78d798 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -4,6 +4,8 @@ namespace Composer\Repository; use Composer\Repository\Vcs\VcsDriverInterface; use Composer\Package\Version\VersionParser; +use Composer\Package\PackageInterface; +use Composer\Package\AliasPackage; use Composer\Package\Loader\ArrayLoader; use Composer\IO\IOInterface; @@ -16,6 +18,7 @@ class VcsRepository extends ArrayRepository protected $packageName; protected $debug; protected $io; + protected $versionParser; public function __construct(array $config, IOInterface $io, array $drivers = null) { @@ -67,7 +70,7 @@ class VcsRepository extends ArrayRepository throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url); } - $versionParser = new VersionParser; + $this->versionParser = new VersionParser; $loader = new ArrayLoader(); if ($driver->hasComposerFile($driver->getRootIdentifier())) { @@ -83,7 +86,7 @@ class VcsRepository extends ArrayRepository $this->io->overwrite($msg, false); } - $parsedTag = $this->validateTag($versionParser, $tag); + $parsedTag = $this->validateTag($tag); if ($parsedTag && $driver->hasComposerFile($identifier)) { try { $data = $driver->getComposerInformation($identifier); @@ -96,7 +99,7 @@ class VcsRepository extends ArrayRepository // manually versioned package if (isset($data['version'])) { - $data['version_normalized'] = $versionParser->normalize($data['version']); + $data['version_normalized'] = $this->versionParser->normalize($data['version']); } else { // auto-versionned package, read value from tag $data['version'] = $tag; @@ -135,7 +138,7 @@ class VcsRepository extends ArrayRepository $this->io->overwrite($msg, false); } - $parsedBranch = $this->validateBranch($versionParser, $branch); + $parsedBranch = $this->validateBranch($branch); if ($driver->hasComposerFile($identifier)) { $data = $driver->getComposerInformation($identifier); @@ -182,23 +185,50 @@ class VcsRepository extends ArrayRepository $data['source'] = $driver->getSource($identifier); } + // check for a branch alias (dev-master => 1.0.x-dev for example) if this is a named branch + if ('dev-' === substr($data['version'], 0, 4) && isset($data['extra']['branch-alias']) && is_array($data['extra']['branch-alias'])) { + foreach ($data['extra']['branch-alias'] as $sourceBranch => $targetBranch) { + // ensure it is an alias to a numeric branch that is parseable + if (!($validatedTargetBranch = $this->validateBranch($targetBranch)) || '-dev' !== substr($validatedTargetBranch, -4)) { + continue; + } + // ensure that it is the current branch aliasing itself + if ($data['version'] !== $sourceBranch && substr($data['version'], 4) !== $sourceBranch) { + continue; + } + + $data['alias'] = $targetBranch.'-dev'; + $data['alias_normalized'] = $validatedTargetBranch; + break; + } + } + return $data; } - private function validateBranch($versionParser, $branch) + public function addPackage(PackageInterface $package) + { + parent::addPackage($package); + + if ($package->getAlias()) { + $this->addPackage($this->createAliasPackage($package)); + } + } + + private function validateBranch($branch) { try { - return $versionParser->normalizeBranch($branch); + return $this->versionParser->normalizeBranch($branch); } catch (\Exception $e) { } return false; } - private function validateTag($versionParser, $version) + private function validateTag($version) { try { - return $versionParser->normalize($version); + return $this->versionParser->normalize($version); } catch (\Exception $e) { }