From 528a058e405b00017e5dc535d0e87e3acaf88a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Wed, 25 Jan 2012 13:40:16 +0100 Subject: [PATCH] Added installer for metapackages --- src/Composer/Factory.php | 1 + .../Installer/MetapackageInstaller.php | 97 +++++++++++++++++ src/Composer/Package/Loader/ArrayLoader.php | 2 - .../Installer/MetapackageInstallerTest.php | 101 ++++++++++++++++++ 4 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 src/Composer/Installer/MetapackageInstaller.php create mode 100644 tests/Composer/Test/Installer/MetapackageInstallerTest.php diff --git a/src/Composer/Factory.php b/src/Composer/Factory.php index e27976a4b..8429221a3 100644 --- a/src/Composer/Factory.php +++ b/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; } diff --git a/src/Composer/Installer/MetapackageInstaller.php b/src/Composer/Installer/MetapackageInstaller.php new file mode 100644 index 000000000..ceee0f1a3 --- /dev/null +++ b/src/Composer/Installer/MetapackageInstaller.php @@ -0,0 +1,97 @@ + + * Jordi Boggiano + * + * 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Ċˆ + */ +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 ''; + } +} diff --git a/src/Composer/Package/Loader/ArrayLoader.php b/src/Composer/Package/Loader/ArrayLoader.php index 98733372b..8731cfb21 100644 --- a/src/Composer/Package/Loader/ArrayLoader.php +++ b/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'])) { diff --git a/tests/Composer/Test/Installer/MetapackageInstallerTest.php b/tests/Composer/Test/Installer/MetapackageInstallerTest.php new file mode 100644 index 000000000..fd71eb1b6 --- /dev/null +++ b/tests/Composer/Test/Installer/MetapackageInstallerTest.php @@ -0,0 +1,101 @@ + + * Jordi Boggiano + * + * 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(); + } +}