Explorar o código

Merge remote-tracking branch 'hason/alias'

Jordi Boggiano %!s(int64=12) %!d(string=hai) anos
pai
achega
faa419cc0e

+ 5 - 3
src/Composer/DependencyResolver/Pool.php

@@ -170,12 +170,14 @@ class Pool
                         $name = $package->getName();
                         if (isset($rootAliases[$name][$package->getVersion()])) {
                             $alias = $rootAliases[$name][$package->getVersion()];
-                            $package->setAlias($alias['alias_normalized']);
-                            $package->setPrettyAlias($alias['alias']);
-                            $package->getRepository()->addPackage($aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']));
+                            if ($package instanceof AliasPackage) {
+                                $package = $package->getAliasOf();
+                            }
+                            $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
                             $aliasPackage->setRootPackageAlias(true);
                             $aliasPackage->setId($this->id++);
 
+                            $package->getRepository()->addPackage($aliasPackage);
                             $this->packages[] = $aliasPackage;
 
                             foreach ($aliasPackage->getNames() as $name) {

+ 6 - 6
src/Composer/Installer.php

@@ -709,8 +709,6 @@ class Installer
             foreach ($versions as $version => $alias) {
                 $packages = $platformRepo->findPackages($package, $version);
                 foreach ($packages as $package) {
-                    $package->setAlias($alias['alias_normalized']);
-                    $package->setPrettyAlias($alias['alias']);
                     $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
                     $aliasPackage->setRootPackageAlias(true);
                     $platformRepo->addPackage($aliasPackage);
@@ -833,12 +831,14 @@ class Installer
      */
     private function mockLocalRepositories(RepositoryManager $rm)
     {
-        $packages = array_map(function ($p) {
-            return clone $p;
-        }, $rm->getLocalRepository()->getPackages());
+        $packages = array();
+        foreach ($rm->getLocalRepository()->getPackages() as $package) {
+            $packages[(string) $package] = clone $package;
+        }
         foreach ($packages as $key => $package) {
             if ($package instanceof AliasPackage) {
-                unset($packages[$key]);
+                $alias = (string) $package->getAliasOf();
+                $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
             }
         }
         $rm->setLocalRepository(

+ 0 - 24
src/Composer/Package/AliasPackage.php

@@ -175,22 +175,6 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
         return $this->rootPackageAlias;
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    public function getAlias()
-    {
-        return '';
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function getPrettyAlias()
-    {
-        return '';
-    }
-
     /***************************************
      * Wrappers around the aliased package *
      ***************************************/
@@ -251,14 +235,6 @@ class AliasPackage extends BasePackage implements CompletePackageInterface
     {
         return $this->aliasOf->getScripts();
     }
-    public function setAliases(array $aliases)
-    {
-        return $this->aliasOf->setAliases($aliases);
-    }
-    public function getAliases()
-    {
-        return $this->aliasOf->getAliases();
-    }
     public function getLicense()
     {
         return $this->aliasOf->getLicense();

+ 1 - 1
src/Composer/Package/BasePackage.php

@@ -119,7 +119,7 @@ abstract class BasePackage implements PackageInterface
      */
     public function setRepository(RepositoryInterface $repository)
     {
-        if ($this->repository) {
+        if ($this->repository && $repository !== $this->repository) {
             throw new \LogicException('A package can only be added to one repository');
         }
         $this->repository = $repository;

+ 5 - 5
src/Composer/Package/Loader/ArrayLoader.php

@@ -13,6 +13,7 @@
 namespace Composer\Package\Loader;
 
 use Composer\Package;
+use Composer\Package\AliasPackage;
 use Composer\Package\Version\VersionParser;
 
 /**
@@ -100,11 +101,6 @@ class ArrayLoader implements LoaderInterface
             $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
         }
 
-        if ($aliasNormalized = $this->getBranchAlias($config)) {
-            $package->setAlias($aliasNormalized);
-            $package->setPrettyAlias(preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
-        }
-
         foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
             if (isset($config[$type])) {
                 $method = 'set'.ucfirst($opts['method']);
@@ -187,6 +183,10 @@ class ArrayLoader implements LoaderInterface
             }
         }
 
+        if ($aliasNormalized = $this->getBranchAlias($config)) {
+            $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
+        }
+
         return $package;
     }
 

+ 0 - 51
src/Composer/Package/Package.php

@@ -36,9 +36,6 @@ class Package extends BasePackage
     protected $releaseDate;
     protected $extra = array();
     protected $binaries = array();
-    protected $aliases = array();
-    protected $alias;
-    protected $prettyAlias;
     protected $dev;
     protected $stability;
     protected $notificationUrl;
@@ -155,54 +152,6 @@ class Package extends BasePackage
         return $this->binaries;
     }
 
-    /**
-     * @param array $aliases
-     */
-    public function setAliases(array $aliases)
-    {
-        $this->aliases = $aliases;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public function getAliases()
-    {
-        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}
      */

+ 0 - 14
src/Composer/Package/PackageInterface.php

@@ -267,20 +267,6 @@ interface PackageInterface
      */
     public function getBinaries();
 
-    /**
-     * Returns a version this package should be aliased to
-     *
-     * @return string
-     */
-    public function getAlias();
-
-    /**
-     * Returns a non-normalized version this package should be aliased to
-     *
-     * @return string
-     */
-    public function getPrettyAlias();
-
     /**
      * Returns package unique name, constructed from name and version.
      *

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

@@ -23,6 +23,7 @@ class RootPackage extends CompletePackage implements RootPackageInterface
     protected $preferStable = false;
     protected $stabilityFlags = array();
     protected $references = array();
+    protected $aliases = array();
 
     /**
      * Set the minimumStability
@@ -95,4 +96,22 @@ class RootPackage extends CompletePackage implements RootPackageInterface
     {
         return $this->references;
     }
+
+    /**
+     * Set the aliases
+     *
+     * @param array $aliases
+     */
+    public function setAliases(array $aliases)
+    {
+        $this->aliases = $aliases;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function getAliases()
+    {
+        return $this->aliases;
+    }
 }

+ 7 - 0
src/Composer/Package/RootPackageInterface.php

@@ -19,6 +19,13 @@ namespace Composer\Package;
  */
 interface RootPackageInterface extends CompletePackageInterface
 {
+    /**
+     * Returns a set of package names and theirs aliases
+     *
+     * @return array
+     */
+    public function getAliases();
+
     /**
      * Returns the minimum stability of the package
      *

+ 6 - 7
src/Composer/Repository/ArrayRepository.php

@@ -130,18 +130,17 @@ class ArrayRepository implements RepositoryInterface
         $package->setRepository($this);
         $this->packages[] = $package;
 
-        // create alias package on the fly if needed
-        if ($package->getAlias()) {
-            $alias = $this->createAliasPackage($package);
-            if (!$this->hasPackage($alias)) {
-                $this->addPackage($alias);
+        if ($package instanceof AliasPackage) {
+            $aliasedPackage = $package->getAliasOf();
+            if (null === $aliasedPackage->getRepository()) {
+                $this->addPackage($aliasedPackage);
             }
         }
     }
 
-    protected function createAliasPackage(PackageInterface $package, $alias = null, $prettyAlias = null)
+    protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
     {
-        return new AliasPackage($package, $alias ?: $package->getAlias(), $prettyAlias ?: $package->getPrettyAlias());
+        return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
     }
 
     /**

+ 11 - 9
src/Composer/Repository/ComposerRepository.php

@@ -322,16 +322,18 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
                     $package = $this->createPackage($version, 'Composer\Package\Package');
                     $package->setRepository($this);
 
-                    $this->providers[$name][$version['uid']] = $package;
-                    $this->providersByUid[$version['uid']] = $package;
+                    if ($package instanceof AliasPackage) {
+                        $aliased = $package->getAliasOf();
+                        $aliased->setRepository($this);
 
-                    if ($package->getAlias()) {
-                        $alias = $this->createAliasPackage($package);
-                        $alias->setRepository($this);
+                        $this->providers[$name][$version['uid']] = $aliased;
+                        $this->providers[$name][$version['uid'].'-alias'] = $package;
 
-                        $this->providers[$name][$version['uid'].'-alias'] = $alias;
                         // override provider with its alias so it can be expanded in the if block above
-                        $this->providersByUid[$version['uid']] = $alias;
+                        $this->providersByUid[$version['uid']] = $package;
+                    } else {
+                        $this->providers[$name][$version['uid']] = $package;
+                        $this->providersByUid[$version['uid']] = $package;
                     }
 
                     // handle root package aliases
@@ -339,8 +341,8 @@ class ComposerRepository extends ArrayRepository implements StreamableRepository
 
                     if (isset($this->rootAliases[$name][$package->getVersion()])) {
                         $rootAliasData = $this->rootAliases[$name][$package->getVersion()];
-                    } elseif (($aliasNormalized = $package->getAlias()) && isset($this->rootAliases[$name][$aliasNormalized])) {
-                        $rootAliasData = $this->rootAliases[$name][$aliasNormalized];
+                    } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$name][$package->getAliasOf()->getVersion()])) {
+                        $rootAliasData = $this->rootAliases[$name][$package->getAliasOf()->getVersion()];
                     }
 
                     if (isset($rootAliasData)) {

+ 36 - 0
tests/Composer/Test/Fixtures/installer/install-aliased-alias.test

@@ -0,0 +1,36 @@
+--TEST--
+Installing double aliased package
+--COMPOSER--
+{
+    "repositories": [
+        {
+            "type": "package",
+            "package": [
+                {
+                    "name": "a/a", "version": "dev-master",
+                    "dist": { "type": "file", "url": "" },
+                    "require": {
+                        "b/b": "dev-master"
+                    }
+                },
+                {
+                    "name": "b/b", "version": "dev-foo",
+                    "extra": { "branch-alias": { "dev-foo": "1.0.x-dev" } },
+                    "dist": { "type": "file", "url": "" }
+                }
+            ]
+        }
+    ],
+    "require": {
+        "a/a": "dev-master",
+        "b/b": "1.0.x-dev as dev-master"
+    },
+    "minimum-stability": "dev"
+}
+--RUN--
+install
+--EXPECT--
+Installing b/b (dev-foo)
+Marking b/b (dev-master) as installed, alias of b/b (dev-foo)
+Installing a/a (dev-master)
+Marking b/b (1.0.x-dev) as installed, alias of b/b (dev-foo)

+ 40 - 0
tests/Composer/Test/Fixtures/installer/update-all-dry-run.test

@@ -0,0 +1,40 @@
+--TEST--
+Updates updateable packages in dry-run mode
+--COMPOSER--
+{
+    "repositories": [
+        {
+            "type": "package",
+            "package": [
+                { "name": "a/a", "version": "1.0.0" },
+                { "name": "a/a", "version": "1.0.1" },
+                { "name": "a/a", "version": "1.1.0" },
+
+                { "name": "a/b", "version": "1.0.0" },
+                { "name": "a/b", "version": "1.0.1" },
+                { "name": "a/b", "version": "2.0.0" },
+
+                { "name": "a/c", "version": "1.0.0" },
+                { "name": "a/c", "version": "2.0.0" }
+            ]
+        }
+    ],
+    "require": {
+        "a/a": "1.0.*",
+        "a/c": "1.*"
+    },
+    "require-dev": {
+        "a/b": "*"
+    }
+}
+--INSTALLED--
+[
+    { "name": "a/a", "version": "1.0.0" },
+    { "name": "a/c", "version": "1.0.0" },
+    { "name": "a/b", "version": "1.0.0" }
+]
+--RUN--
+update --dev --dry-run
+--EXPECT--
+Updating a/a (1.0.0) to a/a (1.0.1)
+Updating a/b (1.0.0) to a/b (2.0.0)

+ 44 - 0
tests/Composer/Test/Fixtures/installer/update-installed-alias-dry-run.test

@@ -0,0 +1,44 @@
+--TEST--
+Updates installed alias packages in dry-run mode
+--COMPOSER--
+{
+    "repositories": [
+        {
+            "type": "package",
+            "package": [
+                {
+                    "name": "a/a", "version": "dev-master",
+                    "require": { "b/b": "2.0.*" },
+                    "source": { "reference": "abcdef", "url": "", "type": "git" },
+                    "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }
+                },
+                {
+                    "name": "b/b", "version": "dev-master",
+                    "source": { "reference": "123456", "url": "", "type": "git" },
+                    "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }
+                }
+            ]
+        }
+    ],
+    "require": {
+        "a/a": "~1.0@dev",
+        "b/b": "@dev"
+    }
+}
+--INSTALLED--
+[
+    {
+        "name": "a/a", "version": "dev-master",
+        "require": { "b/b": "2.0.*" },
+        "source": { "reference": "abcdef", "url": "", "type": "git" },
+        "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }
+    },
+    {
+        "name": "b/b", "version": "dev-master",
+        "source": { "reference": "123456", "url": "", "type": "git" },
+        "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }
+    }
+]
+--RUN--
+update --dry-run
+--EXPECT--

+ 44 - 0
tests/Composer/Test/Fixtures/installer/update-installed-alias.test

@@ -0,0 +1,44 @@
+--TEST--
+Updates installed alias packages
+--COMPOSER--
+{
+    "repositories": [
+        {
+            "type": "package",
+            "package": [
+                {
+                    "name": "a/a", "version": "dev-master",
+                    "require": { "b/b": "2.0.*" },
+                    "source": { "reference": "abcdef", "url": "", "type": "git" },
+                    "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }
+                },
+                {
+                    "name": "b/b", "version": "dev-master",
+                    "source": { "reference": "123456", "url": "", "type": "git" },
+                    "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }
+                }
+            ]
+        }
+    ],
+    "require": {
+        "a/a": "~1.0@dev",
+        "b/b": "@dev"
+    }
+}
+--INSTALLED--
+[
+    {
+        "name": "a/a", "version": "dev-master",
+        "require": { "b/b": "2.0.*" },
+        "source": { "reference": "abcdef", "url": "", "type": "git" },
+        "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }
+    },
+    {
+        "name": "b/b", "version": "dev-master",
+        "source": { "reference": "123456", "url": "", "type": "git" },
+        "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }
+    }
+]
+--RUN--
+update
+--EXPECT--

+ 4 - 1
tests/Composer/Test/InstallerTest.php

@@ -200,7 +200,9 @@ class InstallerTest extends TestCase
 
         $application = new Application;
         $application->get('install')->setCode(function ($input, $output) use ($installer) {
-            $installer->setDevMode($input->getOption('dev'));
+            $installer
+                ->setDevMode($input->getOption('dev'))
+                ->setDryRun($input->getOption('dry-run'));
 
             return $installer->run() ? 0 : 1;
         });
@@ -209,6 +211,7 @@ class InstallerTest extends TestCase
             $installer
                 ->setDevMode($input->getOption('dev'))
                 ->setUpdate(true)
+                ->setDryRun($input->getOption('dry-run'))
                 ->setUpdateWhitelist($input->getArgument('packages'));
 
             return $installer->run() ? 0 : 1;

+ 3 - 4
tests/Composer/Test/Mock/InstallationManagerMock.php

@@ -67,16 +67,15 @@ class InstallationManagerMock extends InstallationManager
         $this->installed[] = $package;
         $this->trace[] = (string) $operation;
 
-        if (!$repo->hasPackage($package)) {
-            $repo->addPackage($package);
-        }
+        parent::markAliasInstalled($repo, $operation);
     }
 
     public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
     {
         $this->uninstalled[] = $operation->getPackage();
         $this->trace[] = (string) $operation;
-        $repo->removePackage($operation->getPackage());
+
+        parent::markAliasUninstalled($repo, $operation);
     }
 
     public function getTrace()

+ 42 - 0
tests/Composer/Test/Package/BasePackageTest.php

@@ -0,0 +1,42 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Test\Package;
+
+use Composer\Package\BasePackage;
+
+class BasePackageTest extends \PHPUnit_Framework_TestCase
+{
+    public function testSetSameRepository()
+    {
+        $package = $this->getMockForAbstractClass('Composer\Package\BasePackage', array('foo'));
+        $repository = $this->getMock('Composer\Repository\RepositoryInterface');
+
+        $package->setRepository($repository);
+        try {
+            $package->setRepository($repository);
+        } catch (\Exception $e) {
+            $this->fail('Set againt the same repository is allowed.');
+        }
+    }
+
+    /**
+     * @expectedException LogicException
+     */
+    public function testSetAnotherRepository()
+    {
+        $package = $this->getMockForAbstractClass('Composer\Package\BasePackage', array('foo'));
+
+        $package->setRepository($this->getMock('Composer\Repository\RepositoryInterface'));
+        $package->setRepository($this->getMock('Composer\Repository\RepositoryInterface'));
+    }
+}

+ 14 - 0
tests/Composer/Test/Package/Loader/ArrayLoaderTest.php

@@ -123,4 +123,18 @@ class ArrayLoaderTest extends \PHPUnit_Framework_TestCase
         $dumper = new ArrayDumper;
         $this->assertEquals($config, $dumper->dump($package));
     }
+
+    public function testPackageWithBranchAlias()
+    {
+        $config = array(
+            'name' => 'A',
+            'version' => 'dev-master',
+            'extra' => array('branch-alias' => array('dev-master' => '1.0.x-dev')),
+        );
+
+        $package = $this->loader->load($config);
+
+        $this->assertInstanceOf('Composer\Package\AliasPackage', $package);
+        $this->assertEquals('1.0.x-dev', $package->getPrettyVersion());
+    }
 }

+ 14 - 0
tests/Composer/Test/Repository/ArrayRepositoryTest.php

@@ -66,4 +66,18 @@ class ArrayRepositoryTest extends TestCase
         $this->assertCount(2, $bar);
         $this->assertEquals('bar', $bar[0]->getName());
     }
+
+    public function testAutomaticallyAddAliasedPackage()
+    {
+        $repo = new ArrayRepository();
+
+        $package = $this->getPackage('foo', '1');
+        $alias = $this->getAliasPackage($package, '2');
+
+        $repo->addPackage($alias);
+
+        $this->assertEquals(2, count($repo));
+        $this->assertTrue($repo->hasPackage($this->getPackage('foo', '1')));
+        $this->assertTrue($repo->hasPackage($this->getPackage('foo', '2')));
+    }
 }

+ 72 - 0
tests/Composer/Test/Repository/ComposerRepositoryTest.php

@@ -16,6 +16,8 @@ use Composer\Repository\ComposerRepository;
 use Composer\IO\NullIO;
 use Composer\Test\Mock\FactoryMock;
 use Composer\Test\TestCase;
+use Composer\Package\Loader\ArrayLoader;
+use Composer\Package\Version\VersionParser;
 
 class ComposerRepositoryTest extends TestCase
 {
@@ -93,4 +95,74 @@ class ComposerRepositoryTest extends TestCase
             ),
         );
     }
+
+    public function testWhatProvides()
+    {
+        $repo = $this->getMockBuilder('Composer\Repository\ComposerRepository')
+            ->disableOriginalConstructor()
+            ->setMethods(array('fetchFile'))
+            ->getMock();
+
+        $cache = $this->getMockBuilder('Composer\Cache')->disableOriginalConstructor()->getMock();
+        $cache->expects($this->any())
+            ->method('sha256')
+            ->will($this->returnValue(false));
+
+        $properties = array(
+            'cache' => $cache,
+            'loader' => new ArrayLoader(),
+            'providerListing' => array('p/a.json' => array('sha256' => 'xxx'))
+        );
+
+        foreach ($properties as $property => $value) {
+            $ref = new \ReflectionProperty($repo, $property);
+            $ref->setAccessible(true);
+            $ref->setValue($repo, $value);
+        }
+
+        $repo->expects($this->any())
+            ->method('fetchFile')
+            ->will($this->returnValue(array(
+                'packages' => array(
+                    array(array(
+                        'uid' => 1,
+                        'name' => 'a',
+                        'version' => 'dev-master',
+                        'extra' => array('branch-alias' => array('dev-master' => '1.0.x-dev')),
+                    )),
+                    array(array(
+                        'uid' => 2,
+                        'name' => 'a',
+                        'version' => 'dev-develop',
+                        'extra' => array('branch-alias' => array('dev-develop' => '1.1.x-dev')),
+                    )),
+                    array(array(
+                        'uid' => 3,
+                        'name' => 'a',
+                        'version' => '0.6',
+                    )),
+                )
+            )));
+
+        $pool = $this->getMock('Composer\DependencyResolver\Pool');
+        $pool->expects($this->any())
+            ->method('isPackageAcceptable')
+            ->will($this->returnValue(true));
+
+        $versionParser = new VersionParser();
+        $repo->setRootAliases(array(
+            'a' => array(
+                $versionParser->normalize('0.6') => array('alias' => 'dev-feature', 'alias_normalized' => $versionParser->normalize('dev-feature')),
+                $versionParser->normalize('1.1.x-dev') => array('alias' => '1.0', 'alias_normalized' => $versionParser->normalize('1.0')),
+            ),
+        ));
+
+        $packages = $repo->whatProvides($pool, 'a');
+
+        $this->assertCount(7, $packages);
+        $this->assertEquals(array('1', '1-alias', '2', '2-alias', '2-root', '3', '3-root'), array_keys($packages));
+        $this->assertInstanceOf('Composer\Package\AliasPackage', $packages['2-root']);
+        $this->assertSame($packages['2'], $packages['2-root']->getAliasOf());
+        $this->assertSame($packages['2'], $packages['2-alias']->getAliasOf());
+    }
 }