Browse Source

Added installer for metapackages

Martin Hasoň 13 years ago
parent
commit
528a058e40

+ 1 - 0
src/Composer/Factory.php

@@ -157,6 +157,7 @@ class Factory
         $im = new Installer\InstallationManager($vendorDir);
         $im->addInstaller(new Installer\LibraryInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), $io, null));
         $im->addInstaller(new Installer\InstallerInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), $io, $im));
+        $im->addInstaller(new Installer\MetapackageInstaller($rm->getLocalRepository(), $io));
 
         return $im;
     }

+ 97 - 0
src/Composer/Installer/MetapackageInstaller.php

@@ -0,0 +1,97 @@
+<?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\Installer;
+
+use Composer\IO\IOInterface;
+use Composer\Repository\WritableRepositoryInterface;
+use Composer\Package\PackageInterface;
+
+/**
+ * Metapackage installation manager.
+ *
+ * @author Martin Hasoň <martin.hason@gmail.com>
+ */
+class MetapackageInstaller implements InstallerInterface
+{
+    protected $repository;
+    protected $io;
+
+    /**
+     * @param   WritableRepositoryInterface $repository repository controller
+     * @param   IOInterface                 $io         io instance
+     */
+    public function __construct(WritableRepositoryInterface $repository, IOInterface $io)
+    {
+        $this->repository = $repository;
+        $this->io = $io;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function supports($packageType)
+    {
+        return $packageType === 'metapackage';
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function isInstalled(PackageInterface $package)
+    {
+        return $this->repository->hasPackage($package);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function install(PackageInterface $package)
+    {
+        $this->repository->addPackage(clone $package);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function update(PackageInterface $initial, PackageInterface $target)
+    {
+        if (!$this->repository->hasPackage($initial)) {
+            throw new \InvalidArgumentException('Package is not installed: '.$initial);
+        }
+
+        $this->repository->removePackage($initial);
+        $this->repository->addPackage(clone $target);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function uninstall(PackageInterface $package)
+    {
+        if (!$this->repository->hasPackage($package)) {
+            // TODO throw exception again here, when update is fixed and we don't have to remove+install (see #125)
+            return;
+            throw new \InvalidArgumentException('Package is not installed: '.$package);
+        }
+
+        $this->repository->removePackage($package);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function getInstallPath(PackageInterface $package)
+    {
+        return '';
+    }
+}

+ 0 - 2
src/Composer/Package/Loader/ArrayLoader.php

@@ -115,8 +115,6 @@ class ArrayLoader
             $package->setSourceType($config['source']['type']);
             $package->setSourceUrl($config['source']['url']);
             $package->setSourceReference($config['source']['reference']);
-        } elseif ($package->isDev()) {
-            throw new \UnexpectedValueException('Dev package '.$package.' must have a source specified');
         }
 
         if (isset($config['dist'])) {

+ 101 - 0
tests/Composer/Test/Installer/MetapackageInstallerTest.php

@@ -0,0 +1,101 @@
+<?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\Installer;
+
+use Composer\Installer\MetapackageInstaller;
+
+class MetapackageInstallerTest extends \PHPUnit_Framework_TestCase
+{
+    private $repository;
+    private $installer;
+    private $io;
+
+    protected function setUp()
+    {
+        $this->repository = $this->getMock('Composer\Repository\WritableRepositoryInterface');
+
+        $this->io = $this->getMock('Composer\IO\IOInterface');
+
+        $this->installer = new MetapackageInstaller($this->repository, $this->io);
+    }
+
+    public function testInstall()
+    {
+        $package = $this->createPackageMock();
+
+        $this->repository
+            ->expects($this->once())
+            ->method('addPackage')
+            ->with($package);
+
+        $this->installer->install($package);
+    }
+
+    public function testUpdate()
+    {
+        $initial = $this->createPackageMock();
+        $target  = $this->createPackageMock();
+
+        $this->repository
+            ->expects($this->exactly(2))
+            ->method('hasPackage')
+            ->with($initial)
+            ->will($this->onConsecutiveCalls(true, false));
+
+        $this->repository
+            ->expects($this->once())
+            ->method('removePackage')
+            ->with($initial);
+
+        $this->repository
+            ->expects($this->once())
+            ->method('addPackage')
+            ->with($target);
+
+        $this->installer->update($initial, $target);
+
+        $this->setExpectedException('InvalidArgumentException');
+
+        $this->installer->update($initial, $target);
+    }
+
+    public function testUninstall()
+    {
+        $package = $this->createPackageMock();
+
+        $this->repository
+            ->expects($this->exactly(2))
+            ->method('hasPackage')
+            ->with($package)
+            ->will($this->onConsecutiveCalls(true, false));
+
+        $this->repository
+            ->expects($this->once())
+            ->method('removePackage')
+            ->with($package);
+
+        $this->installer->uninstall($package);
+
+        // TODO re-enable once #125 is fixed and we throw exceptions again
+//        $this->setExpectedException('InvalidArgumentException');
+
+        $this->installer->uninstall($package);
+    }
+
+    private function createPackageMock()
+    {
+        return $this->getMockBuilder('Composer\Package\MemoryPackage')
+            ->setConstructorArgs(array(md5(rand()), '1.0.0.0', '1.0.0'))
+            ->getMock();
+    }
+}