1
0
Fork 0

LibraryInstaller refactored and tested

pull/19/head
everzet 2011-09-24 00:23:16 +03:00
parent 0cc017a395
commit 067007656b
3 changed files with 341 additions and 52 deletions

View File

@ -12,14 +12,53 @@
namespace Composer\Installer;
use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\Package\PackageInterface;
use Composer\Downloader\DownloaderInterface;
/**
* Interface for the package installation manager.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
interface InstallerInterface
{
/**
* Executes specific solver operation.
*
* @param OperationInterface $operation solver operation instance
*/
function executeOperation(OperationInterface $operation);
/**
* Checks that provided package is installed.
*
* @param PackageInterface $package package instance
*
* @return Boolean
*/
function isInstalled(PackageInterface $package);
/**
* Installs specific package.
*
* @param PackageInterface $package package instance
*/
function install(PackageInterface $package);
/**
* Updates specific package.
*
* @param PackageInterface $initial already installed package version
* @param PackageInterface $target updated version
*
* @throws InvalidArgumentException if $from package is not installed
*/
function update(PackageInterface $initial, PackageInterface $target);
/**
* Uninstalls specific package.
*
* @param PackageInterface $package package instance
*/
function uninstall(PackageInterface $package);
}

View File

@ -12,24 +12,35 @@
namespace Composer\Installer;
use Composer\Downloader\DownloaderInterface;
use Composer\Downloader\DownloadManager;
use Composer\Installer\Registry\RegistryInterface;
use Composer\Installer\Registry\FilesystemRegistry;
use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\Package\PackageInterface;
use Composer\Downloader\DownloaderInterface;
/**
* Package installation manager.
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class LibraryInstaller implements InstallerInterface
{
private $dir;
private $preferSource;
private $downloaders = array();
private $dm;
private $registry;
public function __construct($dir = 'vendor', $preferSource = false)
/**
* Initializes library installer.
*
* @param string $dir relative path for packages home
* @param DownloadManager $dm download manager
* @param RegistryInterface $registry registry controller
*/
public function __construct($dir, DownloadManager $dm, RegistryInterface $registry = null)
{
$this->dir = $dir;
$this->preferSource = $preferSource;
$this->dm = $dm;
if (!is_dir($this->dir)) {
if (file_exists($this->dir)) {
@ -43,67 +54,99 @@ class LibraryInstaller implements InstallerInterface
);
}
}
if (null === $registry) {
$registry = new FilesystemRegistry('.composer', str_replace('/', '_', $dir));
}
public function setDownloader($type, DownloaderInterface $downloader = null)
$this->registry = $registry;
$this->registry->open();
}
/**
* Closes packages registry.
*/
public function __destruct()
{
if (null === $downloader) {
unset($this->downloaders[$type]);
return;
$this->registry->close();
}
$this->downloaders[$type] = $downloader;
}
public function getDownloader($type)
/**
* Executes specific solver operation.
*
* @param OperationInterface $operation solver operation instance
*/
public function executeOperation(OperationInterface $operation)
{
if (!isset($this->downloaders[$type])) {
throw new \UnexpectedValueException('Unknown source type: '.$type);
}
return $this->downloaders[$type];
}
public function install(PackageInterface $package)
{
if (!($this->preferSource && $package->getSourceType()) && $package->getDistType()) {
$downloader = $this->getDownloader($package->getDistType());
return $downloader->download(
$package, $this->dir, $package->getDistUrl(), $package->getDistSha1Checksum()
);
}
if ($package->getSourceType()) {
$downloader = $this->getDownloader($package->getSourceType());
return $downloader->download(
$package, $this->dir, $package->getSourceUrl()
);
}
throw new \InvalidArgumentException('Package should have dist or source specified');
$method = $operation->getJobType();
if ('update' === $method) {
$this->$method($operation->getPackage(), $operation->getTargetPackage());
} else {
$this->$method($operation->getPackage());
}
}
/**
* Checks that specific package is installed.
*
* @param PackageInterface $package package instance
*
* @return Boolean
*/
public function isInstalled(PackageInterface $package)
{
if ($package->getSourceType()) {
$downloader = $this->getDownloader($package->getSourceType());
if ($downloader->isDownloaded($package, $this->dir)) {
return true;
}
return $this->registry->isPackageRegistered($package);
}
if ($package->getDistType()) {
$downloader = $this->getDownloader($package->getDistType());
if ($downloader->isDownloaded($package, $this->dir)) {
return true;
}
/**
* Installs specific package.
*
* @param PackageInterface $package package instance
*
* @throws InvalidArgumentException if provided package have no urls to download from
*/
public function install(PackageInterface $package)
{
$type = $this->dm->download($package, $this->dir);
$this->registry->registerPackage($package, $type);
}
return false;
/**
* Updates specific package.
*
* @param PackageInterface $initial already installed package version
* @param PackageInterface $target updated version
*
* @throws InvalidArgumentException if $from package is not installed
*/
public function update(PackageInterface $initial, PackageInterface $target)
{
if (!$this->registry->isPackageRegistered($initial)) {
throw new \UnexpectedValueException('Package is not installed: '.$initial);
}
$type = $this->registry->getRegisteredPackageInstallerType($initial);
$this->dm->update($initial, $target, $this->dir, $type);
$this->registry->unregisterPackage($initial);
$this->registry->registerPackage($target, $type);
}
/**
* Uninstalls specific package.
*
* @param PackageInterface $package package instance
*
* @throws InvalidArgumentException if package is not installed
*/
public function uninstall(PackageInterface $package)
{
if (!$this->registry->isPackageRegistered($package)) {
throw new \UnexpectedValueException('Package is not installed: '.$package);
}
$type = $this->registry->getRegisteredPackageInstallerType($package);
$this->dm->remove($package, $this->dir, $type);
$this->registry->unregisterPackage($package);
}
}

View File

@ -0,0 +1,207 @@
<?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\LibraryInstaller;
use Composer\DependencyResolver\Operation;
class LibraryInstallerTest extends \PHPUnit_Framework_TestCase
{
private $dir;
private $dm;
private $registry;
private $library;
protected function setUp()
{
$this->dir = sys_get_temp_dir().'/composer';
if (is_dir($this->dir)) {
rmdir($this->dir);
}
$this->dm = $this->getMockBuilder('Composer\Downloader\DownloadManager')
->disableOriginalConstructor()
->getMock();
$this->registry = $this->getMockBuilder('Composer\Installer\Registry\RegistryInterface')
->disableOriginalConstructor()
->getMock();
}
public function testInstallerCreation()
{
$this->registry
->expects($this->once())
->method('open');
$this->registry
->expects($this->once())
->method('close');
$library = new LibraryInstaller($this->dir, $this->dm, $this->registry);
$this->assertTrue(is_dir($this->dir));
$file = sys_get_temp_dir().'/file';
touch($file);
$this->setExpectedException('UnexpectedValueException');
$library = new LibraryInstaller($file, $this->dm, $this->registry);
}
public function testExecuteOperation()
{
$library = $this->getMockBuilder('Composer\Installer\LibraryInstaller')
->setConstructorArgs(array($this->dir, $this->dm, $this->registry))
->setMethods(array('install', 'update', 'uninstall'))
->getMock();
$packageToInstall = $this->createPackageMock();
$packageToRemove = $this->createPackageMock();
$packageToUpdate = $this->createPackageMock();
$updatedPackage = $this->createPackageMock();
$library
->expects($this->once())
->method('install')
->with($packageToInstall);
$library
->expects($this->once())
->method('uninstall')
->with($packageToRemove);
$library
->expects($this->once())
->method('update')
->with($packageToUpdate, $updatedPackage);
$library->executeOperation(new Operation\InstallOperation($packageToInstall));
$library->executeOperation(new Operation\UninstallOperation($packageToRemove));
$library->executeOperation(new Operation\UpdateOperation($packageToUpdate, $updatedPackage));
}
public function testIsInstalled()
{
$library = new LibraryInstaller($this->dir, $this->dm, $this->registry);
$package = $this->createPackageMock();
$this->registry
->expects($this->exactly(2))
->method('isPackageRegistered')
->with($package)
->will($this->onConsecutiveCalls(true, false));
$this->assertTrue($library->isInstalled($package));
$this->assertFalse($library->isInstalled($package));
}
public function testInstall()
{
$library = new LibraryInstaller($this->dir, $this->dm, $this->registry);
$package = $this->createPackageMock();
$this->dm
->expects($this->once())
->method('download')
->with($package, $this->dir)
->will($this->returnValue('source'));
$this->registry
->expects($this->once())
->method('registerPackage')
->with($package, 'source');
$library->install($package);
}
public function testUpdate()
{
$library = new LibraryInstaller($this->dir, $this->dm, $this->registry);
$initial = $this->createPackageMock();
$target = $this->createPackageMock();
$this->registry
->expects($this->exactly(2))
->method('isPackageRegistered')
->with($initial)
->will($this->onConsecutiveCalls(true, false));
$this->registry
->expects($this->once())
->method('getRegisteredPackageInstallerType')
->with($initial)
->will($this->returnValue('dist'));
$this->dm
->expects($this->once())
->method('update')
->with($initial, $target, $this->dir, 'dist');
$this->registry
->expects($this->once())
->method('unregisterPackage')
->with($initial);
$this->registry
->expects($this->once())
->method('registerPackage')
->with($target, 'dist');
$library->update($initial, $target);
$this->setExpectedException('UnexpectedValueException');
$library->update($initial, $target);
}
public function testUninstall()
{
$library = new LibraryInstaller($this->dir, $this->dm, $this->registry);
$package = $this->createPackageMock();
$this->registry
->expects($this->exactly(2))
->method('isPackageRegistered')
->with($package)
->will($this->onConsecutiveCalls(true, false));
$this->registry
->expects($this->once())
->method('getRegisteredPackageInstallerType')
->with($package)
->will($this->returnValue('source'));
$this->dm
->expects($this->once())
->method('remove')
->with($package, $this->dir, 'source');
$this->registry
->expects($this->once())
->method('unregisterPackage')
->with($package);
$library->uninstall($package);
$this->setExpectedException('UnexpectedValueException');
$library->uninstall($package);
}
private function createPackageMock()
{
return $this->getMockBuilder('Composer\Package\MemoryPackage')
->setConstructorArgs(array(md5(rand()), '1.0.0'))
->getMock();
}
}