Merge branch 'refactoring'
commit
c6d7760145
44
bin/composer
44
bin/composer
|
@ -4,21 +4,43 @@
|
|||
require __DIR__.'/../tests/bootstrap.php';
|
||||
|
||||
use Composer\Composer;
|
||||
use Composer\Downloader\GitDownloader;
|
||||
use Composer\Downloader\PearDownloader;
|
||||
use Composer\Downloader\ZipDownloader;
|
||||
use Composer\Installer\LibraryInstaller;
|
||||
use Composer\Console\Application;
|
||||
use Composer\Installer;
|
||||
use Composer\Downloader;
|
||||
use Composer\Repository;
|
||||
use Composer\Package;
|
||||
use Composer\Console\Application as ComposerApplication;
|
||||
|
||||
setlocale(LC_ALL, 'C');
|
||||
// initialize repository manager
|
||||
$rm = new Repository\RepositoryManager();
|
||||
$localRepository = new Repository\WrapperRepository(array(
|
||||
new Repository\ArrayRepository('.composer/installed.json'),
|
||||
new Repository\PlatformRepository(),
|
||||
));
|
||||
$rm->setLocalRepository($localRepository);
|
||||
$rm->setRepository('Packagist', new Repository\ComposerRepository('http://packagist.org'));
|
||||
|
||||
// initialize download manager
|
||||
$dm = new Downloader\DownloadManager($preferSource = false);
|
||||
$dm->setDownloader('git', new Downloader\GitDownloader());
|
||||
//$dm->setDownloader('pear', new Downloader\PearDownloader());
|
||||
//$dm->setDownloader('zip', new Downloader\ZipDownloader());
|
||||
|
||||
// initialize installation manager
|
||||
$im = new Installer\InstallationManager();
|
||||
$im->setInstaller('library', new Installer\LibraryInstaller('vendor', $dm, $rm->getLocalRepository()));
|
||||
|
||||
// load package
|
||||
$loader = new Package\Loader\JsonLoader();
|
||||
$package = $loader->load('composer.json');
|
||||
|
||||
// initialize composer
|
||||
$composer = new Composer();
|
||||
$composer->addDownloader('git', new GitDownloader);
|
||||
$composer->addDownloader('pear', new PearDownloader);
|
||||
$composer->addDownloader('zip', new ZipDownloader);
|
||||
$composer->addInstaller('library', new LibraryInstaller);
|
||||
$composer->setPackage($package);
|
||||
$composer->setPackageLock(new Package\PackageLock('composer.lock'));
|
||||
$composer->setRepositoryManager($rm);
|
||||
$composer->setDownloadManager($dm);
|
||||
$composer->setInstallationManager($im);
|
||||
|
||||
// run the command application
|
||||
$application = new Application($composer);
|
||||
$application = new ComposerApplication($composer);
|
||||
$application->run();
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"required": true
|
||||
},
|
||||
"type": {
|
||||
"description": "Package type, either 'Library', or the parent project it applies to if it's a plugin for a framework or application (e.g. 'Symfony2', 'Typo3', 'Drupal', ..).",
|
||||
"description": "Package type, either 'Library', or the parent project it applies to if it's a plugin for a framework or application (e.g. 'Symfony2', 'Typo3', 'Drupal', ..), note that this has to be defined and communicated by any project implementing a custom composer installer, those are just unreliable examples.",
|
||||
"type": "string",
|
||||
"optional": true
|
||||
},
|
||||
|
|
|
@ -13,11 +13,17 @@
|
|||
namespace Composer\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command as BaseCommand;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Composer\DependencyResolver\Request;
|
||||
use Composer\DependencyResolver\Solver;
|
||||
use Composer\Installer\Operation;
|
||||
|
||||
/**
|
||||
* Base class for Composer commands
|
||||
*
|
||||
* @author Ryan Weaver <ryan@knplabs.com>
|
||||
* @authro Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
abstract class Command extends BaseCommand
|
||||
{
|
||||
|
@ -28,4 +34,4 @@ abstract class Command extends BaseCommand
|
|||
{
|
||||
return $this->getApplication()->getComposer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,20 +12,17 @@
|
|||
|
||||
namespace Composer\Command;
|
||||
|
||||
use Composer\DependencyResolver;
|
||||
use Composer\DependencyResolver\Pool;
|
||||
use Composer\DependencyResolver\Request;
|
||||
use Composer\DependencyResolver\DefaultPolicy;
|
||||
use Composer\DependencyResolver\Solver;
|
||||
use Composer\Repository\PlatformRepository;
|
||||
use Composer\Package\MemoryPackage;
|
||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||
use Composer\DependencyResolver\Operation;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @author Ryan Weaver <ryan@knplabs.com>
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
class InstallCommand extends Command
|
||||
{
|
||||
|
@ -48,130 +45,53 @@ EOT
|
|||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
// TODO this needs a parameter to enable installing from source (i.e. git clone, instead of downloading archives)
|
||||
$sourceInstall = false;
|
||||
$composer = $this->getComposer();
|
||||
|
||||
$config = $this->loadConfig();
|
||||
if ($composer->getPackageLock()->isLocked()) {
|
||||
$output->writeln('<info>Found lockfile. Reading</info>');
|
||||
|
||||
$output->writeln('<info>Loading repositories</info>');
|
||||
|
||||
if (isset($config['repositories'])) {
|
||||
foreach ($config['repositories'] as $name => $spec) {
|
||||
$this->getComposer()->addRepository($name, $spec);
|
||||
$installationManager = $composer->getInstallationManager();
|
||||
foreach ($composer->getPackageLock()->getLockedPackages() as $package) {
|
||||
if (!$installationManager->isPackageInstalled($package)) {
|
||||
$operation = new Operation\InstallOperation($package, 'lock resolving');
|
||||
$installationManager->execute($operation);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// creating repository pool
|
||||
$pool = new Pool;
|
||||
|
||||
$repoInstalled = new PlatformRepository;
|
||||
$pool->addRepository($repoInstalled);
|
||||
|
||||
// TODO check the lock file to see what's currently installed
|
||||
// $repoInstalled->addPackage(new MemoryPackage('$Package', '$Version'));
|
||||
|
||||
$output->writeln('Loading package list');
|
||||
|
||||
foreach ($this->getComposer()->getRepositories() as $repository) {
|
||||
$pool->addRepository($composer->getRepositoryManager()->getLocalRepository());
|
||||
foreach ($composer->getRepositoryManager()->getRepositories() as $repository) {
|
||||
$pool->addRepository($repository);
|
||||
}
|
||||
|
||||
// creating requirements request
|
||||
$request = new Request($pool);
|
||||
|
||||
$output->writeln('Building up request');
|
||||
|
||||
// TODO there should be an update flag or dedicated update command
|
||||
// TODO check lock file to remove packages that disappeared from the requirements
|
||||
foreach ($config['require'] as $name => $version) {
|
||||
if ('latest' === $version) {
|
||||
$request->install($name);
|
||||
} else {
|
||||
preg_match('#^([>=<~]*)([\d.]+.*)$#', $version, $match);
|
||||
if (!$match[1]) {
|
||||
$match[1] = '=';
|
||||
}
|
||||
$constraint = new VersionConstraint($match[1], $match[2]);
|
||||
$request->install($name, $constraint);
|
||||
}
|
||||
foreach ($composer->getPackage()->getRequires() as $link) {
|
||||
$request->install($link->getTarget(), $link->getConstraint());
|
||||
}
|
||||
|
||||
$output->writeln('Solving dependencies');
|
||||
// prepare solver
|
||||
$installationManager = $composer->getInstallationManager();
|
||||
$localRepo = $composer->getRepositoryManager()->getLocalRepository();
|
||||
$policy = new DependencyResolver\DefaultPolicy();
|
||||
$solver = new DependencyResolver\Solver($policy, $pool, $localRepo);
|
||||
|
||||
$policy = new DefaultPolicy;
|
||||
$solver = new Solver($policy, $pool, $repoInstalled);
|
||||
$transaction = $solver->solve($request);
|
||||
|
||||
$lock = array();
|
||||
|
||||
foreach ($transaction as $task) {
|
||||
switch ($task['job']) {
|
||||
case 'install':
|
||||
$package = $task['package'];
|
||||
$output->writeln('> Installing '.$package->getPrettyName());
|
||||
if ($sourceInstall) {
|
||||
// TODO
|
||||
} else {
|
||||
if ($package->getDistType()) {
|
||||
$downloaderType = $package->getDistType();
|
||||
$type = 'dist';
|
||||
} elseif ($package->getSourceType()) {
|
||||
$output->writeln('Package '.$package->getPrettyName().' has no dist url, installing from source instead.');
|
||||
$downloaderType = $package->getSourceType();
|
||||
$type = 'source';
|
||||
} else {
|
||||
throw new \UnexpectedValueException('Package '.$package->getPrettyName().' has no source or dist URL.');
|
||||
}
|
||||
$downloader = $this->getComposer()->getDownloader($downloaderType);
|
||||
$installer = $this->getComposer()->getInstaller($package->getType());
|
||||
if (!$installer->install($package, $downloader, $type)) {
|
||||
throw new \LogicException($package->getPrettyName().' could not be installed.');
|
||||
}
|
||||
}
|
||||
$lock[$package->getName()] = array('version' => $package->getVersion());
|
||||
break;
|
||||
default:
|
||||
throw new \UnexpectedValueException('Unhandled job type : '.$task['job']);
|
||||
}
|
||||
// solve dependencies and execute operations
|
||||
foreach ($solver->solve($request) as $operation) {
|
||||
$installationManager->execute($operation);
|
||||
}
|
||||
|
||||
if (false) {
|
||||
$composer->getPackageLock()->lock($localRepo->getPackages());
|
||||
$output->writeln('> Locked');
|
||||
}
|
||||
|
||||
$localRepo->write();
|
||||
|
||||
$output->writeln('> Done');
|
||||
|
||||
$this->storeLockFile($lock, $output);
|
||||
}
|
||||
|
||||
protected function loadConfig()
|
||||
{
|
||||
if (!file_exists('composer.json')) {
|
||||
throw new \UnexpectedValueException('composer.json config file not found in '.getcwd());
|
||||
}
|
||||
$config = json_decode(file_get_contents('composer.json'), true);
|
||||
if (!$config) {
|
||||
switch (json_last_error()) {
|
||||
case JSON_ERROR_NONE:
|
||||
$msg = 'No error has occurred, is your composer.json file empty?';
|
||||
break;
|
||||
case JSON_ERROR_DEPTH:
|
||||
$msg = 'The maximum stack depth has been exceeded';
|
||||
break;
|
||||
case JSON_ERROR_STATE_MISMATCH:
|
||||
$msg = 'Invalid or malformed JSON';
|
||||
break;
|
||||
case JSON_ERROR_CTRL_CHAR:
|
||||
$msg = 'Control character error, possibly incorrectly encoded';
|
||||
break;
|
||||
case JSON_ERROR_SYNTAX:
|
||||
$msg = 'Syntax error';
|
||||
break;
|
||||
case JSON_ERROR_UTF8:
|
||||
$msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
|
||||
break;
|
||||
}
|
||||
throw new \UnexpectedValueException('Incorrect composer.json file: '.$msg);
|
||||
}
|
||||
return $config;
|
||||
}
|
||||
|
||||
protected function storeLockFile(array $content, OutputInterface $output)
|
||||
{
|
||||
file_put_contents('composer.lock', json_encode($content, JSON_FORCE_OBJECT)."\n");
|
||||
$output->writeln('> composer.lock dumped');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,125 +12,74 @@
|
|||
|
||||
namespace Composer;
|
||||
|
||||
use Composer\Downloader\DownloaderInterface;
|
||||
use Composer\Installer\InstallerInterface;
|
||||
use Composer\Repository\ComposerRepository;
|
||||
use Composer\Repository\PlatformRepository;
|
||||
use Composer\Repository\GitRepository;
|
||||
use Composer\Repository\PearRepository;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Package\PackageLock;
|
||||
use Composer\Repository\RepositoryManager;
|
||||
use Composer\Installer\InstallationManager;
|
||||
use Composer\Downloader\DownloadManager;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @author Konstantin Kudryashiv <ever.zet@gmail.com>
|
||||
*/
|
||||
class Composer
|
||||
{
|
||||
const VERSION = '1.0.0-DEV';
|
||||
|
||||
protected $repositories = array();
|
||||
protected $downloaders = array();
|
||||
protected $installers = array();
|
||||
private $package;
|
||||
private $lock;
|
||||
|
||||
public function __construct()
|
||||
private $rm;
|
||||
private $dm;
|
||||
private $im;
|
||||
|
||||
public function setPackage(PackageInterface $package)
|
||||
{
|
||||
$this->addRepository('Packagist', array('composer' => 'http://packagist.org'));
|
||||
$this->package = $package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add downloader for type
|
||||
*
|
||||
* @param string $type
|
||||
* @param DownloaderInterface $downloader
|
||||
*/
|
||||
public function addDownloader($type, DownloaderInterface $downloader)
|
||||
public function getPackage()
|
||||
{
|
||||
$type = strtolower($type);
|
||||
$this->downloaders[$type] = $downloader;
|
||||
return $this->package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type downloader
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return DownloaderInterface
|
||||
*/
|
||||
public function getDownloader($type)
|
||||
public function setPackageLock($lock)
|
||||
{
|
||||
$type = strtolower($type);
|
||||
if (!isset($this->downloaders[$type])) {
|
||||
throw new \UnexpectedValueException('Unknown source type: '.$type);
|
||||
}
|
||||
return $this->downloaders[$type];
|
||||
$this->lock = $lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add installer for type
|
||||
*
|
||||
* @param string $type
|
||||
* @param InstallerInterface $installer
|
||||
*/
|
||||
public function addInstaller($type, InstallerInterface $installer)
|
||||
public function getPackageLock()
|
||||
{
|
||||
$type = strtolower($type);
|
||||
$this->installers[$type] = $installer;
|
||||
return $this->lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type installer
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return InstallerInterface
|
||||
*/
|
||||
public function getInstaller($type)
|
||||
public function setRepositoryManager(RepositoryManager $manager)
|
||||
{
|
||||
$type = strtolower($type);
|
||||
if (!isset($this->installers[$type])) {
|
||||
throw new \UnexpectedValueException('Unknown dependency type: '.$type);
|
||||
}
|
||||
return $this->installers[$type];
|
||||
$this->rm = $manager;
|
||||
}
|
||||
|
||||
public function addRepository($name, $spec)
|
||||
public function getRepositoryManager()
|
||||
{
|
||||
if (null === $spec) {
|
||||
unset($this->repositories[$name]);
|
||||
}
|
||||
if (is_array($spec) && count($spec) === 1) {
|
||||
return $this->repositories[$name] = $this->createRepository($name, key($spec), current($spec));
|
||||
}
|
||||
throw new \UnexpectedValueException('Invalid repositories specification '.json_encode($spec).', should be: {"type": "url"}');
|
||||
return $this->rm;
|
||||
}
|
||||
|
||||
public function getRepositories()
|
||||
public function setDownloadManager(DownloadManager $manager)
|
||||
{
|
||||
return $this->repositories;
|
||||
$this->dm = $manager;
|
||||
}
|
||||
|
||||
public function createRepository($name, $type, $spec)
|
||||
public function getDownloadManager()
|
||||
{
|
||||
if (is_string($spec)) {
|
||||
$spec = array('url' => $spec);
|
||||
}
|
||||
$spec['url'] = rtrim($spec['url'], '/');
|
||||
return $this->dm;
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case 'git-bare':
|
||||
case 'git-multi':
|
||||
throw new \Exception($type.' repositories not supported yet');
|
||||
break;
|
||||
public function setInstallationManager(InstallationManager $manager)
|
||||
{
|
||||
$this->im = $manager;
|
||||
}
|
||||
|
||||
case 'git':
|
||||
return new GitRepository($spec['url']);
|
||||
|
||||
case 'composer':
|
||||
return new ComposerRepository($spec['url']);
|
||||
|
||||
case 'pear':
|
||||
return new PearRepository($spec['url'], $name);
|
||||
|
||||
default:
|
||||
throw new \UnexpectedValueException('Unknown repository type: '.$type.', could not create repository '.$name);
|
||||
}
|
||||
public function getInstallationManager()
|
||||
{
|
||||
return $this->im;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,13 @@
|
|||
namespace Composer\Console;
|
||||
|
||||
use Symfony\Component\Console\Application as BaseApplication;
|
||||
use Composer\Composer;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Composer\Command\InstallCommand;
|
||||
use Composer\Composer;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Package\PackageLock;
|
||||
|
||||
/**
|
||||
* The console application that handles the commands
|
||||
|
@ -59,10 +61,10 @@ class Application extends BaseApplication
|
|||
}
|
||||
|
||||
/**
|
||||
* Initializes all the composer commands
|
||||
* Looks for all *Command files in Composer's Command directory
|
||||
*/
|
||||
protected function registerCommands()
|
||||
{
|
||||
$this->add(new InstallCommand());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<?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\DependencyResolver\Operation;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Solver install operation.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
class InstallOperation extends SolverOperation
|
||||
{
|
||||
protected $package;
|
||||
|
||||
/**
|
||||
* Initializes operation.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
* @param string $reason operation reason
|
||||
*/
|
||||
public function __construct(PackageInterface $package, $reason = null)
|
||||
{
|
||||
parent::__construct($reason);
|
||||
|
||||
$this->package = $package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns package instance.
|
||||
*
|
||||
* @return PackageInterface
|
||||
*/
|
||||
public function getPackage()
|
||||
{
|
||||
return $this->package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns job type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getJobType()
|
||||
{
|
||||
return 'install';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?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\DependencyResolver\Operation;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Solver operation interface.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
interface OperationInterface
|
||||
{
|
||||
/**
|
||||
* Returns job type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getJobType();
|
||||
|
||||
/**
|
||||
* Returns operation reason.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getReason();
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?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\DependencyResolver\Operation;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Abstract solver operation class.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
abstract class SolverOperation implements OperationInterface
|
||||
{
|
||||
protected $reason;
|
||||
|
||||
/**
|
||||
* Initializes operation.
|
||||
*
|
||||
* @param string $reason operation reason
|
||||
*/
|
||||
public function __construct($reason = null)
|
||||
{
|
||||
$this->reason = $reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns operation reason.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReason()
|
||||
{
|
||||
return $this->reason;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?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\DependencyResolver\Operation;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Solver uninstall operation.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
class UninstallOperation extends SolverOperation
|
||||
{
|
||||
protected $package;
|
||||
|
||||
/**
|
||||
* Initializes operation.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
* @param string $reason operation reason
|
||||
*/
|
||||
public function __construct(PackageInterface $package, $reason = null)
|
||||
{
|
||||
parent::__construct($reason);
|
||||
|
||||
$this->package = $package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns package instance.
|
||||
*
|
||||
* @return PackageInterface
|
||||
*/
|
||||
public function getPackage()
|
||||
{
|
||||
return $this->package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns job type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getJobType()
|
||||
{
|
||||
return 'uninstall';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?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\DependencyResolver\Operation;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Solver update operation.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
class UpdateOperation extends SolverOperation
|
||||
{
|
||||
protected $initialPackage;
|
||||
protected $targetPackage;
|
||||
|
||||
/**
|
||||
* Initializes update operation.
|
||||
*
|
||||
* @param PackageInterface $initial initial package
|
||||
* @param PackageInterface $target target package (updated)
|
||||
* @param string $reason update reason
|
||||
*/
|
||||
public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
|
||||
{
|
||||
parent::__construct($reason);
|
||||
|
||||
$this->initialPackage = $initial;
|
||||
$this->targetPackage = $target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns initial package.
|
||||
*
|
||||
* @return PackageInterface
|
||||
*/
|
||||
public function getInitialPackage()
|
||||
{
|
||||
return $this->initialPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns target package.
|
||||
*
|
||||
* @return PackageInterface
|
||||
*/
|
||||
public function getTargetPackage()
|
||||
{
|
||||
return $this->targetPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns job type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getJobType()
|
||||
{
|
||||
return 'update';
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ namespace Composer\DependencyResolver;
|
|||
|
||||
use Composer\Repository\RepositoryInterface;
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\DependencyResolver\Operation;
|
||||
|
||||
/**
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
|
@ -49,6 +50,7 @@ class Solver
|
|||
protected $watches = array();
|
||||
protected $removeWatches = array();
|
||||
protected $decisionMap;
|
||||
protected $installedPackageMap;
|
||||
|
||||
protected $packageToUpdateRule = array();
|
||||
protected $packageToFeatureRule = array();
|
||||
|
@ -251,7 +253,7 @@ class Solver
|
|||
$this->addedMap[$package->getId()] = true;
|
||||
|
||||
$dontFix = 0;
|
||||
if ($this->installed === $package->getRepository() && !isset($this->fixMap[$package->getId()])) {
|
||||
if (isset($this->installedPackageMap[$package->getId()]) && !isset($this->fixMap[$package->getId()])) {
|
||||
$dontFix = 1;
|
||||
}
|
||||
|
||||
|
@ -270,7 +272,7 @@ class Solver
|
|||
if ($dontFix) {
|
||||
$foundInstalled = false;
|
||||
foreach ($possibleRequires as $require) {
|
||||
if ($this->installed === $require->getRepository()) {
|
||||
if (isset($this->installedPackageMap[$require->getId()])) {
|
||||
$foundInstalled = true;
|
||||
break;
|
||||
}
|
||||
|
@ -293,7 +295,7 @@ class Solver
|
|||
$possibleConflicts = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
|
||||
|
||||
foreach ($possibleConflicts as $conflict) {
|
||||
if ($dontFix && $this->installed === $conflict->getRepository()) {
|
||||
if ($dontFix && isset($this->installedPackageMap[$conflict->getId()])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -308,7 +310,7 @@ class Solver
|
|||
/** @TODO: if ($this->noInstalledObsoletes) */
|
||||
if (true) {
|
||||
$noObsoletes = isset($this->noObsoletes[$package->getId()]);
|
||||
$isInstalled = ($this->installed === $package->getRepository());
|
||||
$isInstalled = (isset($this->installedPackageMap[$package->getId()]));
|
||||
|
||||
foreach ($package->getReplaces() as $link) {
|
||||
$obsoleteProviders = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
|
||||
|
@ -757,7 +759,7 @@ class Solver
|
|||
switch ($job['cmd']) {
|
||||
case 'install':
|
||||
foreach ($job['packages'] as $package) {
|
||||
if ($this->installed === $package->getRepository()) {
|
||||
if (isset($this->installedPackageMap[$package->getId()])) {
|
||||
$disableQueue[] = array('type' => 'update', 'package' => $package);
|
||||
}
|
||||
|
||||
|
@ -870,7 +872,7 @@ class Solver
|
|||
|
||||
case 'remove':
|
||||
foreach ($job['packages'] as $package) {
|
||||
if ($this->installed === $package->getRepository()) {
|
||||
if (isset($this->installedPackageMap[$package->getId()])) {
|
||||
$disableQueue[] = array('type' => 'update', 'package' => $package);
|
||||
}
|
||||
}
|
||||
|
@ -932,6 +934,10 @@ class Solver
|
|||
{
|
||||
$this->jobs = $request->getJobs();
|
||||
$installedPackages = $this->installed->getPackages();
|
||||
$this->installedPackageMap = array();
|
||||
foreach ($installedPackages as $package) {
|
||||
$this->installedPackageMap[$package->getId()] = $package;
|
||||
}
|
||||
|
||||
$this->decisionMap = new \SplFixedArray($this->pool->getMaxId() + 1);
|
||||
|
||||
|
@ -953,12 +959,12 @@ class Solver
|
|||
foreach ($job['packages'] as $package) {
|
||||
switch ($job['cmd']) {
|
||||
case 'fix':
|
||||
if ($this->installed === $package->getRepository()) {
|
||||
if (isset($this->installedPackageMap[$package->getId()])) {
|
||||
$this->fixMap[$package->getId()] = true;
|
||||
}
|
||||
break;
|
||||
case 'update':
|
||||
if ($this->installed === $package->getRepository()) {
|
||||
if (isset($this->installedPackageMap[$package->getId()])) {
|
||||
$this->updateMap[$package->getId()] = true;
|
||||
}
|
||||
break;
|
||||
|
@ -1038,7 +1044,7 @@ class Solver
|
|||
break;
|
||||
case 'lock':
|
||||
foreach ($job['packages'] as $package) {
|
||||
if ($this->installed === $package->getRepository()) {
|
||||
if (isset($this->installedPackageMap[$package->getId()])) {
|
||||
$rule = $this->createInstallRule($package, self::RULE_JOB_LOCK);
|
||||
} else {
|
||||
$rule = $this->createRemoveRule($package, self::RULE_JOB_LOCK);
|
||||
|
@ -1082,7 +1088,7 @@ class Solver
|
|||
$package = $literal->getPackage();
|
||||
|
||||
// !wanted & installed
|
||||
if (!$literal->isWanted() && $this->installed === $package->getRepository()) {
|
||||
if (!$literal->isWanted() && isset($this->installedPackageMap[$package->getId()])) {
|
||||
$updateRule = $this->packageToUpdateRule[$package->getId()];
|
||||
|
||||
foreach ($updateRule->getLiterals() as $updateLiteral) {
|
||||
|
@ -1097,7 +1103,7 @@ class Solver
|
|||
$package = $literal->getPackage();
|
||||
|
||||
// wanted & installed || !wanted & !installed
|
||||
if ($literal->isWanted() == ($this->installed === $package->getRepository())) {
|
||||
if ($literal->isWanted() == (isset($this->installedPackageMap[$package->getId()]))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1105,28 +1111,21 @@ class Solver
|
|||
if (isset($installMeansUpdateMap[$literal->getPackageId()])) {
|
||||
$source = $installMeansUpdateMap[$literal->getPackageId()];
|
||||
|
||||
$transaction[] = array(
|
||||
'job' => 'update',
|
||||
'from' => $source,
|
||||
'to' => $package,
|
||||
'why' => $this->decisionQueueWhy[$i],
|
||||
$transaction[] = new Operation\UpdateOperation(
|
||||
$source, $package, $this->decisionQueueWhy[$i]
|
||||
);
|
||||
|
||||
// avoid updates to one package from multiple origins
|
||||
unset($installMeansUpdateMap[$literal->getPackageId()]);
|
||||
$ignoreRemove[$source->getId()] = true;
|
||||
} else {
|
||||
$transaction[] = array(
|
||||
'job' => 'install',
|
||||
'package' => $package,
|
||||
'why' => $this->decisionQueueWhy[$i],
|
||||
$transaction[] = new Operation\InstallOperation(
|
||||
$package, $this->decisionQueueWhy[$i]
|
||||
);
|
||||
}
|
||||
} else if (!isset($ignoreRemove[$package->getId()])) {
|
||||
$transaction[] = array(
|
||||
'job' => 'remove',
|
||||
'package' => $package,
|
||||
'why' => $this->decisionQueueWhy[$i],
|
||||
$transaction[] = new Operation\UninstallOperation(
|
||||
$package, $this->decisionQueueWhy[$i]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2060,4 +2059,4 @@ class Solver
|
|||
}
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
<?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\Downloader;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Downloader\DownloaderInterface;
|
||||
|
||||
/**
|
||||
* Downloaders manager.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
class DownloadManager
|
||||
{
|
||||
private $preferSource = false;
|
||||
private $downloaders = array();
|
||||
|
||||
/**
|
||||
* Initializes download manager.
|
||||
*
|
||||
* @param Boolean $preferSource prefer downloading from source
|
||||
*/
|
||||
public function __construct($preferSource = false)
|
||||
{
|
||||
$this->preferSource = $preferSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes downloader prefer source installation over the dist.
|
||||
*
|
||||
* @param Boolean $preferSource prefer downloading from source
|
||||
*/
|
||||
public function preferSource($preferSource = true)
|
||||
{
|
||||
$this->preferSource = $preferSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets installer downloader for a specific installation type.
|
||||
*
|
||||
* @param string $type installation type
|
||||
* @param DownloaderInterface $downloader downloader instance
|
||||
*/
|
||||
public function setDownloader($type, DownloaderInterface $downloader)
|
||||
{
|
||||
$this->downloaders[$type] = $downloader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns downloader for a specific installation type.
|
||||
*
|
||||
* @param string $type installation type
|
||||
*
|
||||
* @return DownloaderInterface
|
||||
*
|
||||
* @throws UnexpectedValueException if downloader for provided type is not registeterd
|
||||
*/
|
||||
public function getDownloader($type)
|
||||
{
|
||||
if (!isset($this->downloaders[$type])) {
|
||||
throw new \UnexpectedValueException('Unknown source type: '.$type);
|
||||
}
|
||||
|
||||
return $this->downloaders[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads package into target dir.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
* @param string $targetDir target dir
|
||||
* @param Boolean $preferSource prefer installation from source
|
||||
*
|
||||
* @return string downloader type (source/dist)
|
||||
*
|
||||
* @throws InvalidArgumentException if package have no urls to download from
|
||||
*/
|
||||
public function download(PackageInterface $package, $targetDir, $preferSource = null)
|
||||
{
|
||||
$preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
|
||||
$sourceType = $package->getSourceType();
|
||||
$distType = $package->getDistType();
|
||||
|
||||
if (!($preferSource && $sourceType) && $distType) {
|
||||
$downloader = $this->getDownloader($distType);
|
||||
$downloader->download(
|
||||
$package, $targetDir,
|
||||
$package->getDistUrl(), $package->getDistSha1Checksum(),
|
||||
$preferSource
|
||||
);
|
||||
$package->setInstallationSource('dist');
|
||||
} elseif ($sourceType) {
|
||||
$downloader = $this->getDownloader($sourceType);
|
||||
$downloader->download($package, $targetDir, $package->getSourceUrl(), $preferSource);
|
||||
$package->setInstallationSource('source');
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Package should have dist or source specified');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates package from initial to target version.
|
||||
*
|
||||
* @param PackageInterface $initial initial package version
|
||||
* @param PackageInterface $target target package version
|
||||
* @param string $targetDir target dir
|
||||
*
|
||||
* @throws InvalidArgumentException if initial package is not installed
|
||||
*/
|
||||
public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
|
||||
{
|
||||
if (null === $installationType = $initial->getInstallationSource()) {
|
||||
throw new \InvalidArgumentException(
|
||||
'Package '.$initial.' was not been installed propertly and can not be updated'
|
||||
);
|
||||
}
|
||||
$useSource = 'source' === $installationType;
|
||||
|
||||
if (!$useSource) {
|
||||
$initialType = $initial->getDistType();
|
||||
$targetType = $target->getDistType();
|
||||
} else {
|
||||
$initialType = $initial->getSourceType();
|
||||
$targetType = $target->getSourceType();
|
||||
}
|
||||
|
||||
$downloader = $this->getDownloader($initialType);
|
||||
|
||||
if ($initialType === $targetType) {
|
||||
$downloader->update($initial, $target, $targetDir, $useSource);
|
||||
} else {
|
||||
$downloader->remove($initial, $targetDir, $useSource);
|
||||
$this->download($target, $targetDir, $useSource);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes package from target dir.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
* @param string $targetDir target dir
|
||||
*/
|
||||
public function remove(PackageInterface $package, $targetDir)
|
||||
{
|
||||
if (null === $installationType = $package->getInstallationSource()) {
|
||||
throw new \InvalidArgumentException(
|
||||
'Package '.$package.' was not been installed propertly and can not be removed'
|
||||
);
|
||||
}
|
||||
$useSource = 'source' === $installationType;
|
||||
|
||||
// get proper downloader
|
||||
if (!$useSource) {
|
||||
$downloader = $this->getDownloader($package->getDistType());
|
||||
} else {
|
||||
$downloader = $this->getDownloader($package->getSourceType());
|
||||
}
|
||||
|
||||
$downloader->remove($package, $targetDir, $useSource);
|
||||
}
|
||||
}
|
|
@ -15,21 +15,39 @@ namespace Composer\Downloader;
|
|||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Package Downloader
|
||||
*
|
||||
* @author Kirill chEbba Chebunin <iam@chebba.org>
|
||||
*/
|
||||
interface DownloaderInterface
|
||||
* Downloader interface.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
interface DownloaderInterface
|
||||
{
|
||||
/**
|
||||
* Download package
|
||||
* Downloads specific package into specific folder.
|
||||
*
|
||||
* @param PackageInterface $package Downloaded package
|
||||
* @param string $path Download to
|
||||
* @param string $url Download from
|
||||
* @param string|null $checksum Package checksum
|
||||
*
|
||||
* @throws \UnexpectedValueException
|
||||
* @param PackageInterface $package package instance
|
||||
* @param string $path download path
|
||||
* @param string $url download url
|
||||
* @param string $checksum package checksum (for dists)
|
||||
* @param Boolean $useSource download as source
|
||||
*/
|
||||
function download(PackageInterface $package, $path, $url, $checksum = null);
|
||||
function download(PackageInterface $package, $path, $url, $checksum = null, $useSource = false);
|
||||
|
||||
/**
|
||||
* Updates specific package in specific folder from initial to target version.
|
||||
*
|
||||
* @param PackageInterface $initial initial package
|
||||
* @param PackageInterface $target updated package
|
||||
* @param string $path download path
|
||||
* @param Boolean $useSource download as source
|
||||
*/
|
||||
function update(PackageInterface $initial, PackageInterface $target, $path, $useSource = false);
|
||||
|
||||
/**
|
||||
* Removes specific package from specific folder.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
* @param string $path download path
|
||||
* @param Boolean $useSource download as source
|
||||
*/
|
||||
function remove(PackageInterface $package, $path, $useSource = false);
|
||||
}
|
||||
|
|
|
@ -19,27 +19,33 @@ use Composer\Package\PackageInterface;
|
|||
*/
|
||||
class GitDownloader implements DownloaderInterface
|
||||
{
|
||||
protected $clone;
|
||||
|
||||
public function __construct($clone = true)
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function download(PackageInterface $package, $path, $url, $checksum = null, $useSource = false)
|
||||
{
|
||||
$this->clone = $clone;
|
||||
system('git clone '.escapeshellarg($url).' -b master '.escapeshellarg($path));
|
||||
|
||||
// TODO non-source installs:
|
||||
// system('git archive --format=tar --prefix='.escapeshellarg($package->getName()).' --remote='.escapeshellarg($url).' master | tar -xf -');
|
||||
}
|
||||
|
||||
public function download(PackageInterface $package, $path, $url, $checksum = null)
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function update(PackageInterface $initial, PackageInterface $target, $path, $useSource = false)
|
||||
{
|
||||
if (!is_dir($path)) {
|
||||
if (file_exists($path)) {
|
||||
throw new \UnexpectedValueException($path.' exists and is not a directory.');
|
||||
}
|
||||
if (!mkdir($path, 0777, true)) {
|
||||
throw new \UnexpectedValueException($path.' does not exist and could not be created.');
|
||||
}
|
||||
}
|
||||
if ($this->clone) {
|
||||
system('git clone '.escapeshellarg($url).' -b master '.escapeshellarg($path.'/'.$package->getName()));
|
||||
} else {
|
||||
system('git archive --format=tar --prefix='.escapeshellarg($package->getName()).' --remote='.escapeshellarg($url).' master | tar -xf -');
|
||||
}
|
||||
$cwd = getcwd();
|
||||
chdir($path);
|
||||
system('git pull');
|
||||
chdir($cwd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function remove(PackageInterface $package, $path, $useSource = false)
|
||||
{
|
||||
echo 'rm -rf '.$path; // TODO
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,4 +66,4 @@ class PearDownloader implements DownloaderInterface
|
|||
}
|
||||
chdir($cwd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,4 +73,4 @@ class ZipDownloader implements DownloaderInterface
|
|||
throw new \UnexpectedValueException($zipName.' is not a valid zip archive, got error code '.$retval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
<?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\Package\PackageInterface;
|
||||
use Composer\DependencyResolver\Operation\OperationInterface;
|
||||
use Composer\DependencyResolver\Operation\InstallOperation;
|
||||
use Composer\DependencyResolver\Operation\UpdateOperation;
|
||||
use Composer\DependencyResolver\Operation\UninstallOperation;
|
||||
|
||||
/**
|
||||
* Package operation manager.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
class InstallationManager
|
||||
{
|
||||
private $installers = array();
|
||||
|
||||
/**
|
||||
* Sets installer for a specific package type.
|
||||
*
|
||||
* @param string $type package type (library f.e.)
|
||||
* @param InstallerInterface $installer installer instance
|
||||
*/
|
||||
public function setInstaller($type, InstallerInterface $installer)
|
||||
{
|
||||
$this->installers[$type] = $installer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns installer for a specific package type.
|
||||
*
|
||||
* @param string $type package type
|
||||
*
|
||||
* @return InstallerInterface
|
||||
*
|
||||
* @throws InvalidArgumentException if installer for provided type is not registered
|
||||
*/
|
||||
public function getInstaller($type)
|
||||
{
|
||||
if (!isset($this->installers[$type])) {
|
||||
throw new \InvalidArgumentException('Unknown installer type: '.$type);
|
||||
}
|
||||
|
||||
return $this->installers[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether provided package is installed in one of the registered installers.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isPackageInstalled(PackageInterface $package)
|
||||
{
|
||||
foreach ($this->installers as $installer) {
|
||||
if ($installer->isInstalled($package)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes solver operation.
|
||||
*
|
||||
* @param OperationInterface $operation operation instance
|
||||
*/
|
||||
public function execute(OperationInterface $operation)
|
||||
{
|
||||
$method = $operation->getJobType();
|
||||
$this->$method($operation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes install operation.
|
||||
*
|
||||
* @param InstallOperation $operation operation instance
|
||||
*/
|
||||
public function install(InstallOperation $operation)
|
||||
{
|
||||
$installer = $this->getInstaller($operation->getPackage()->getType());
|
||||
$installer->install($operation->getPackage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes update operation.
|
||||
*
|
||||
* @param InstallOperation $operation operation instance
|
||||
*/
|
||||
public function update(UpdateOperation $operation)
|
||||
{
|
||||
$initial = $operation->getInitialPackage();
|
||||
$target = $operation->getTargetPackage();
|
||||
|
||||
$initialType = $initial->getType();
|
||||
$targetType = $target->getType();
|
||||
|
||||
if ($initialType === $targetType) {
|
||||
$installer = $this->getInstaller($initialType);
|
||||
$installer->update($initial, $target);
|
||||
} else {
|
||||
$this->getInstaller($initialType)->uninstall($initial);
|
||||
$this->getInstaller($targetType)->install($target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstalls package.
|
||||
*
|
||||
* @param UninstallOperation $operation operation instance
|
||||
*/
|
||||
public function uninstall(UninstallOperation $operation)
|
||||
{
|
||||
$installer = $this->getInstaller($operation->getPackage()->getType());
|
||||
$installer->uninstall($operation->getPackage());
|
||||
}
|
||||
}
|
|
@ -12,22 +12,46 @@
|
|||
|
||||
namespace Composer\Installer;
|
||||
|
||||
use Composer\Downloader\DownloaderInterface;
|
||||
use Composer\DependencyResolver\Operation\OperationInterface;
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Package Installer
|
||||
*
|
||||
* @author Kirill chEbba Chebunin <iam@chebba.org>
|
||||
*/
|
||||
* Interface for the package installation manager.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
interface InstallerInterface
|
||||
{
|
||||
/**
|
||||
* Install package
|
||||
* Checks that provided package is installed.
|
||||
*
|
||||
* @param PackageInterface $package
|
||||
* @param DownloaderInterface $downloader
|
||||
* @param string $type
|
||||
* @param PackageInterface $package package instance
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
function install(PackageInterface $package, DownloaderInterface $downloader, $type);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -12,30 +12,115 @@
|
|||
|
||||
namespace Composer\Installer;
|
||||
|
||||
use Composer\Downloader\DownloaderInterface;
|
||||
use Composer\Downloader\DownloadManager;
|
||||
use Composer\Repository\WritableRepositoryInterface;
|
||||
use Composer\DependencyResolver\Operation\OperationInterface;
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Package installation manager.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
class LibraryInstaller implements InstallerInterface
|
||||
{
|
||||
protected $dir;
|
||||
private $dir;
|
||||
private $dm;
|
||||
private $repository;
|
||||
|
||||
public function __construct($dir = 'vendor')
|
||||
/**
|
||||
* Initializes library installer.
|
||||
*
|
||||
* @param string $dir relative path for packages home
|
||||
* @param DownloadManager $dm download manager
|
||||
* @param WritableRepositoryInterface $repository repository controller
|
||||
*/
|
||||
public function __construct($dir, DownloadManager $dm, WritableRepositoryInterface $repository)
|
||||
{
|
||||
$this->dir = $dir;
|
||||
$this->dm = $dm;
|
||||
|
||||
if (!is_dir($this->dir)) {
|
||||
if (file_exists($this->dir)) {
|
||||
throw new \UnexpectedValueException(
|
||||
$this->dir.' exists and is not a directory.'
|
||||
);
|
||||
}
|
||||
if (!mkdir($this->dir, 0777, true)) {
|
||||
throw new \UnexpectedValueException(
|
||||
$this->dir.' does not exist and could not be created.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
public function install(PackageInterface $package, DownloaderInterface $downloader, $type)
|
||||
/**
|
||||
* Checks that specific package is installed.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isInstalled(PackageInterface $package)
|
||||
{
|
||||
if ($type === 'dist') {
|
||||
$downloader->download($package, $this->dir, $package->getDistUrl(), $package->getDistSha1Checksum());
|
||||
} elseif ($type === 'source') {
|
||||
$downloader->download($package, $this->dir, $package->getSourceUrl());
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Type must be one of (dist, source), '.$type.' given.');
|
||||
}
|
||||
return true;
|
||||
return $this->repository->hasPackage($package);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs specific package.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
*
|
||||
* @throws InvalidArgumentException if provided package have no urls to download from
|
||||
*/
|
||||
public function install(PackageInterface $package)
|
||||
{
|
||||
$downloadPath = $this->dir.DIRECTORY_SEPARATOR.$package->getName();
|
||||
|
||||
$this->dm->download($package, $downloadPath);
|
||||
$this->repository->addPackage($package);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->repository->hasPackage($initial)) {
|
||||
throw new \InvalidArgumentException('Package is not installed: '.$initial);
|
||||
}
|
||||
|
||||
$downloadPath = $this->dir.DIRECTORY_SEPARATOR.$initial->getName();
|
||||
|
||||
$this->dm->update($initial, $target, $downloadPath);
|
||||
$this->repository->removePackage($initial);
|
||||
$this->repository->addPackage($target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstalls specific package.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
*
|
||||
* @throws InvalidArgumentException if package is not installed
|
||||
*/
|
||||
public function uninstall(PackageInterface $package)
|
||||
{
|
||||
if (!$this->repository->hasPackage($package)) {
|
||||
throw new \InvalidArgumentException('Package is not installed: '.$package);
|
||||
}
|
||||
|
||||
$downloadPath = $this->dir.DIRECTORY_SEPARATOR.$package->getName();
|
||||
|
||||
$this->dm->remove($package, $downloadPath);
|
||||
$this->repository->removePackage($package);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,6 +134,16 @@ abstract class BasePackage implements PackageInterface
|
|||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns package unique name, constructed from name, version and release type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUniqueName()
|
||||
{
|
||||
return $this->getName().'-'.$this->getVersion().'-'.$this->getReleaseType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the package into a readable and unique string
|
||||
*
|
||||
|
@ -141,27 +151,6 @@ abstract class BasePackage implements PackageInterface
|
|||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->getName().'-'.$this->getVersion().'-'.$this->getReleaseType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a version string and returns an array with the version, its type (alpha, beta, RC, stable) and a dev flag (for development branches tracking)
|
||||
*
|
||||
* @param string $version
|
||||
* @return array
|
||||
*/
|
||||
public static function parseVersion($version)
|
||||
{
|
||||
if (!preg_match('#^v?(\d+)(\.\d+)?(\.\d+)?-?((?:beta|RC|alpha)\d*)?-?(dev)?$#i', $version, $matches)) {
|
||||
throw new \UnexpectedValueException('Invalid version string '.$version);
|
||||
}
|
||||
|
||||
return array(
|
||||
'version' => $matches[1]
|
||||
.(!empty($matches[2]) ? $matches[2] : '.0')
|
||||
.(!empty($matches[3]) ? $matches[3] : '.0'),
|
||||
'type' => !empty($matches[4]) ? strtolower($matches[4]) : 'stable',
|
||||
'dev' => !empty($matches[5]),
|
||||
);
|
||||
return $this->getUniqueName();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<?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\Package\Dumper;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kudryashiv <ever.zet@gmail.com>
|
||||
*/
|
||||
class ArrayDumper
|
||||
{
|
||||
public function dump(PackageInterface $package)
|
||||
{
|
||||
$keys = array(
|
||||
'type',
|
||||
'names',
|
||||
'extra',
|
||||
'installationSource',
|
||||
'sourceType',
|
||||
'sourceUrl',
|
||||
'distType',
|
||||
'distUrl',
|
||||
'distSha1Checksum',
|
||||
'releaseType',
|
||||
'version',
|
||||
'license',
|
||||
'requires',
|
||||
'conflicts',
|
||||
'provides',
|
||||
'replaces',
|
||||
'recommends',
|
||||
'suggests'
|
||||
);
|
||||
|
||||
$data = array();
|
||||
$data['name'] = $package->getPrettyName();
|
||||
foreach ($keys as $key) {
|
||||
$getter = 'get'.ucfirst($key);
|
||||
$value = $package->$getter();
|
||||
|
||||
if (null !== $value && !(is_array($value) && 0 === count($value))) {
|
||||
$data[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
<?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\Package\Loader;
|
||||
|
||||
use Composer\Package;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kudryashiv <ever.zet@gmail.com>
|
||||
*/
|
||||
class ArrayLoader
|
||||
{
|
||||
protected $supportedLinkTypes = array(
|
||||
'require' => 'requires',
|
||||
'conflict' => 'conflicts',
|
||||
'provide' => 'provides',
|
||||
'replace' => 'replaces',
|
||||
'recommend' => 'recommends',
|
||||
'suggest' => 'suggests',
|
||||
);
|
||||
|
||||
public function load($config)
|
||||
{
|
||||
$this->validateConfig($config);
|
||||
|
||||
$versionParser = new Package\Version\VersionParser();
|
||||
$version = $versionParser->parse($config['version']);
|
||||
$package = new Package\MemoryPackage($config['name'], $version['version'], $version['type']);
|
||||
|
||||
$package->setType(isset($config['type']) ? $config['type'] : 'library');
|
||||
|
||||
if (isset($config['extra'])) {
|
||||
$package->setExtra($config['extra']);
|
||||
}
|
||||
|
||||
if (isset($config['license'])) {
|
||||
$package->setLicense($config['license']);
|
||||
}
|
||||
|
||||
if (isset($config['source'])) {
|
||||
if (!isset($config['source']['type']) || !isset($config['source']['url'])) {
|
||||
throw new \UnexpectedValueException(sprintf(
|
||||
"package source should be specified as {\"type\": ..., \"url\": ...},\n%s given",
|
||||
json_encode($config['source'])
|
||||
));
|
||||
}
|
||||
$package->setSourceType($config['source']['type']);
|
||||
$package->setSourceUrl($config['source']['url']);
|
||||
}
|
||||
|
||||
if (isset($config['dist'])) {
|
||||
if (!isset($config['dist']['type'])
|
||||
|| !isset($config['dist']['url'])
|
||||
|| !isset($config['dist']['shasum'])) {
|
||||
throw new \UnexpectedValueException(sprintf(
|
||||
"package dist should be specified as ".
|
||||
"{\"type\": ..., \"url\": ..., \"shasum\": ...},\n%s given",
|
||||
json_encode($config['source'])
|
||||
));
|
||||
}
|
||||
$package->setDistType($config['dist']['type']);
|
||||
$package->setDistUrl($config['dist']['url']);
|
||||
$package->setDistSha1Checksum($config['dist']['shasum']);
|
||||
}
|
||||
|
||||
foreach ($this->supportedLinkTypes as $type => $description) {
|
||||
if (isset($config[$type])) {
|
||||
$method = 'set'.ucfirst($description);
|
||||
$package->{$method}(
|
||||
$this->loadLinksFromConfig($package->getName(), $description, $config['require'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $package;
|
||||
}
|
||||
|
||||
private function loadLinksFromConfig($srcPackageName, $description, array $linksSpecs)
|
||||
{
|
||||
$links = array();
|
||||
foreach ($linksSpecs as $packageName => $version) {
|
||||
$name = strtolower($packageName);
|
||||
|
||||
preg_match('#^([>=<~]*)([\d.]+.*)$#', $version, $match);
|
||||
if (!$match[1]) {
|
||||
$match[1] = '=';
|
||||
}
|
||||
|
||||
$constraint = new Package\LinkConstraint\VersionConstraint($match[1], $match[2]);
|
||||
$links[] = new Package\Link($srcPackageName, $packageName, $constraint, $description);
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
private function validateConfig(array $config)
|
||||
{
|
||||
if (!isset($config['name'])) {
|
||||
throw new \UnexpectedValueException('name is required for package');
|
||||
}
|
||||
if (!isset($config['version'])) {
|
||||
throw new \UnexpectedValueException('version is required for package');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?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\Package\Loader;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kudryashiv <ever.zet@gmail.com>
|
||||
*/
|
||||
class JsonLoader extends ArrayLoader
|
||||
{
|
||||
public function load($json)
|
||||
{
|
||||
$config = $this->loadJsonConfig($json);
|
||||
|
||||
return parent::load($config);
|
||||
}
|
||||
|
||||
private function loadJsonConfig($json)
|
||||
{
|
||||
if (is_file($json)) {
|
||||
$json = file_get_contents($json);
|
||||
}
|
||||
|
||||
$config = json_decode($json, true);
|
||||
if (!$config) {
|
||||
switch (json_last_error()) {
|
||||
case JSON_ERROR_NONE:
|
||||
$msg = 'No error has occurred, is your composer.json file empty?';
|
||||
break;
|
||||
case JSON_ERROR_DEPTH:
|
||||
$msg = 'The maximum stack depth has been exceeded';
|
||||
break;
|
||||
case JSON_ERROR_STATE_MISMATCH:
|
||||
$msg = 'Invalid or malformed JSON';
|
||||
break;
|
||||
case JSON_ERROR_CTRL_CHAR:
|
||||
$msg = 'Control character error, possibly incorrectly encoded';
|
||||
break;
|
||||
case JSON_ERROR_SYNTAX:
|
||||
$msg = 'Syntax error';
|
||||
break;
|
||||
case JSON_ERROR_UTF8:
|
||||
$msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
|
||||
break;
|
||||
}
|
||||
throw new \UnexpectedValueException('Incorrect composer.json file: '.$msg);
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ namespace Composer\Package;
|
|||
class MemoryPackage extends BasePackage
|
||||
{
|
||||
protected $type;
|
||||
protected $installationSource;
|
||||
protected $sourceType;
|
||||
protected $sourceUrl;
|
||||
protected $distType;
|
||||
|
@ -84,6 +85,22 @@ class MemoryPackage extends BasePackage
|
|||
return $this->extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setInstallationSource($type)
|
||||
{
|
||||
$this-> installationSource = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getInstallationSource()
|
||||
{
|
||||
return $this->installationSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
*/
|
||||
|
|
|
@ -82,6 +82,20 @@ interface PackageInterface
|
|||
*/
|
||||
function getExtra();
|
||||
|
||||
/**
|
||||
* Sets source from which this package was installed (source/dist).
|
||||
*
|
||||
* @param string $type source/dist
|
||||
*/
|
||||
function setInstallationSource($type);
|
||||
|
||||
/**
|
||||
* Returns source from which this package was installed (source/dist).
|
||||
*
|
||||
* @param string $type source/dist
|
||||
*/
|
||||
function getInstallationSource();
|
||||
|
||||
/**
|
||||
* Returns the repository type of this package, e.g. git, svn
|
||||
*
|
||||
|
@ -202,6 +216,13 @@ interface PackageInterface
|
|||
*/
|
||||
function getRepository();
|
||||
|
||||
/**
|
||||
* Returns package unique name, constructed from name, version and release type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getUniqueName();
|
||||
|
||||
/**
|
||||
* Converts the package into a readable and unique string
|
||||
*
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
<?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\Package;
|
||||
|
||||
use Composer\Package\MemoryPackage;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
|
||||
/**
|
||||
* @author Konstantin Kudryashiv <ever.zet@gmail.com>
|
||||
*/
|
||||
class PackageLock
|
||||
{
|
||||
private $file;
|
||||
private $isLocked = false;
|
||||
|
||||
public function __construct($file = 'composer.lock')
|
||||
{
|
||||
if (file_exists($file)) {
|
||||
$this->file = $file;
|
||||
$this->isLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function isLocked()
|
||||
{
|
||||
return $this->isLocked;
|
||||
}
|
||||
|
||||
public function getLockedPackages()
|
||||
{
|
||||
$lockList = $this->loadJsonConfig($this->file);
|
||||
|
||||
$versionParser = new VersionParser();
|
||||
$packages = array();
|
||||
foreach ($lockList as $info) {
|
||||
$version = $versionParser->parse($info['version']);
|
||||
$packages[] = new MemoryPackage($info['package'], $version['version'], $version['type']);
|
||||
}
|
||||
|
||||
return $packages;
|
||||
}
|
||||
|
||||
public function lock(array $packages)
|
||||
{
|
||||
// TODO: write installed packages info into $this->file
|
||||
}
|
||||
|
||||
private function loadJsonConfig($json)
|
||||
{
|
||||
if (is_file($json)) {
|
||||
$json = file_get_contents($json);
|
||||
}
|
||||
|
||||
$config = json_decode($json, true);
|
||||
if (!$config) {
|
||||
switch (json_last_error()) {
|
||||
case JSON_ERROR_NONE:
|
||||
$msg = 'No error has occurred, is your composer.json file empty?';
|
||||
break;
|
||||
case JSON_ERROR_DEPTH:
|
||||
$msg = 'The maximum stack depth has been exceeded';
|
||||
break;
|
||||
case JSON_ERROR_STATE_MISMATCH:
|
||||
$msg = 'Invalid or malformed JSON';
|
||||
break;
|
||||
case JSON_ERROR_CTRL_CHAR:
|
||||
$msg = 'Control character error, possibly incorrectly encoded';
|
||||
break;
|
||||
case JSON_ERROR_SYNTAX:
|
||||
$msg = 'Syntax error';
|
||||
break;
|
||||
case JSON_ERROR_UTF8:
|
||||
$msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
|
||||
break;
|
||||
}
|
||||
throw new \UnexpectedValueException('Incorrect composer.json file: '.$msg);
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?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\Package\Version;
|
||||
|
||||
/**
|
||||
* Version parser
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
*/
|
||||
class VersionParser
|
||||
{
|
||||
/**
|
||||
* Parses a version string and returns an array with the version, its type (alpha, beta, RC, stable) and a dev flag (for development branches tracking)
|
||||
*
|
||||
* @param string $version
|
||||
* @return array
|
||||
*/
|
||||
public function parse($version)
|
||||
{
|
||||
if (!preg_match('#^v?(\d+)(\.\d+)?(\.\d+)?-?((?:beta|RC|alpha)\d*)?-?(dev)?$#i', $version, $matches)) {
|
||||
throw new \UnexpectedValueException('Invalid version string '.$version);
|
||||
}
|
||||
|
||||
return array(
|
||||
'version' => $matches[1]
|
||||
.(!empty($matches[2]) ? $matches[2] : '.0')
|
||||
.(!empty($matches[3]) ? $matches[3] : '.0'),
|
||||
'type' => strtolower(!empty($matches[4]) ? $matches[4] : 'stable'),
|
||||
'dev' => !empty($matches[5]),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -23,6 +23,26 @@ class ArrayRepository implements RepositoryInterface
|
|||
{
|
||||
protected $packages;
|
||||
|
||||
/**
|
||||
* Checks if specified package in this repository.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function hasPackage(PackageInterface $package)
|
||||
{
|
||||
$packageId = $package->getUniqueName();
|
||||
|
||||
foreach ($this->getPackages() as $repoPackage) {
|
||||
if ($packageId === $repoPackage->getUniqueName()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new package to the repository
|
||||
*
|
||||
|
@ -37,6 +57,24 @@ class ArrayRepository implements RepositoryInterface
|
|||
$this->packages[] = $package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes package from repository.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
*/
|
||||
public function removePackage(PackageInterface $package)
|
||||
{
|
||||
$packageId = $package->getUniqueName();
|
||||
|
||||
foreach ($this->getPackages() as $key => $repoPackage) {
|
||||
if ($packageId === $repoPackage->getUniqueName()) {
|
||||
array_splice($this->packages, $key, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all contained packages
|
||||
*
|
||||
|
|
|
@ -12,9 +12,7 @@
|
|||
|
||||
namespace Composer\Repository;
|
||||
|
||||
use Composer\Package\MemoryPackage;
|
||||
use Composer\Package\BasePackage;
|
||||
use Composer\Package\Link;
|
||||
use Composer\Package\Loader\ArrayLoader;
|
||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||
|
||||
/**
|
||||
|
@ -22,10 +20,16 @@ use Composer\Package\LinkConstraint\VersionConstraint;
|
|||
*/
|
||||
class ComposerRepository extends ArrayRepository
|
||||
{
|
||||
protected $url;
|
||||
protected $packages;
|
||||
|
||||
public function __construct($url)
|
||||
{
|
||||
$url = rtrim($url, '/');
|
||||
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
||||
throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$url);
|
||||
}
|
||||
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
|
@ -42,60 +46,11 @@ class ComposerRepository extends ArrayRepository
|
|||
}
|
||||
}
|
||||
|
||||
protected function createPackages($data)
|
||||
private function createPackages($data)
|
||||
{
|
||||
foreach ($data['versions'] as $rev) {
|
||||
$version = BasePackage::parseVersion($rev['version']);
|
||||
|
||||
$package = new MemoryPackage($rev['name'], $version['version'], $version['type']);
|
||||
$package->setSourceType($rev['source']['type']);
|
||||
$package->setSourceUrl($rev['source']['url']);
|
||||
|
||||
$package->setDistType($rev['dist']['type']);
|
||||
$package->setDistUrl($rev['dist']['url']);
|
||||
$package->setDistSha1Checksum($rev['dist']['shasum']);
|
||||
|
||||
if (isset($rev['type'])) {
|
||||
$package->setType($rev['type']);
|
||||
}
|
||||
|
||||
if (isset($rev['extra'])) {
|
||||
$package->setExtra($rev['extra']);
|
||||
}
|
||||
|
||||
if (isset($rev['license'])) {
|
||||
$package->setLicense($rev['license']);
|
||||
}
|
||||
|
||||
$links = array(
|
||||
'require',
|
||||
'conflict',
|
||||
'provide',
|
||||
'replace',
|
||||
'recommend',
|
||||
'suggest',
|
||||
);
|
||||
foreach ($links as $link) {
|
||||
if (isset($rev[$link])) {
|
||||
$method = 'set'.$link.'s';
|
||||
$package->{$method}($this->createLinks($rev['name'], $link.'s', $rev[$link]));
|
||||
}
|
||||
}
|
||||
$this->addPackage($package);
|
||||
$loader = new ArrayLoader();
|
||||
$this->addPackage($loader->load($rev));
|
||||
}
|
||||
}
|
||||
|
||||
protected function createLinks($name, $description, $linkSpecs)
|
||||
{
|
||||
$links = array();
|
||||
foreach ($linkSpecs as $dep => $ver) {
|
||||
preg_match('#^([>=<~]*)([\d.]+.*)$#', $ver, $match);
|
||||
if (!$match[1]) {
|
||||
$match[1] = '=';
|
||||
}
|
||||
$constraint = new VersionConstraint($match[1], $match[2]);
|
||||
$links[] = new Link($name, $dep, $constraint, $description);
|
||||
}
|
||||
return $links;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
<?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\Repository;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
use Composer\Package\Loader\ArrayLoader;
|
||||
use Composer\Package\Dumper\ArrayDumper;
|
||||
|
||||
/**
|
||||
* Filesystem repository.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
class FilesystemRepository extends ArrayRepository implements WritableRepositoryInterface
|
||||
{
|
||||
private $file;
|
||||
|
||||
/**
|
||||
* Initializes filesystem repository.
|
||||
*
|
||||
* @param string $group registry (installer) group
|
||||
*/
|
||||
public function __construct($repositoryFile)
|
||||
{
|
||||
$this->file = $repositoryFile;
|
||||
$path = dirname($this->file);
|
||||
|
||||
if (!is_dir($path)) {
|
||||
if (file_exists($path)) {
|
||||
throw new \UnexpectedValueException(
|
||||
$path.' exists and is not a directory.'
|
||||
);
|
||||
}
|
||||
if (!mkdir($path, 0777, true)) {
|
||||
throw new \UnexpectedValueException(
|
||||
$path.' does not exist and could not be created.'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes repository (reads file, or remote address).
|
||||
*/
|
||||
protected function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
$packages = @json_decode(file_get_contents($this->file), true);
|
||||
|
||||
if (is_array($packages)) {
|
||||
$loader = new ArrayLoader();
|
||||
foreach ($packages as $package) {
|
||||
$this->addPackage($loader->load($package));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes writable repository.
|
||||
*/
|
||||
public function write()
|
||||
{
|
||||
$packages = array();
|
||||
$dumper = new ArrayDumper();
|
||||
foreach ($this->getPackages() as $package) {
|
||||
$packages[] = $dumper->dump($package);
|
||||
}
|
||||
|
||||
file_put_contents($this->file, json_encode($packages));
|
||||
}
|
||||
}
|
|
@ -24,11 +24,13 @@ use Composer\Package\LinkConstraint\VersionConstraint;
|
|||
*/
|
||||
class GitRepository extends ArrayRepository
|
||||
{
|
||||
protected $packages;
|
||||
protected $url;
|
||||
protected $cacheDir;
|
||||
|
||||
public function __construct($url)
|
||||
public function __construct($url, $cacheDir)
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->cacheDir = $cacheDir;
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
|
@ -98,4 +100,4 @@ class GitRepository extends ArrayRepository
|
|||
}
|
||||
return $links;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,16 +23,17 @@ use Composer\Package\LinkConstraint\VersionConstraint;
|
|||
*/
|
||||
class PearRepository extends ArrayRepository
|
||||
{
|
||||
private $name;
|
||||
private $url;
|
||||
protected $url;
|
||||
protected $cacheDir;
|
||||
|
||||
public function __construct($url, $name = '')
|
||||
public function __construct($url, $cacheDir)
|
||||
{
|
||||
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
||||
throw new \UnexpectedValueException('Invalid url given for PEAR repository "'.$name.'": '.$url);
|
||||
throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$url);
|
||||
}
|
||||
|
||||
$this->url = $url;
|
||||
$this->cacheDir = $cacheDir;
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
|
|
|
@ -14,22 +14,23 @@ namespace Composer\Repository;
|
|||
|
||||
use Composer\Package\MemoryPackage;
|
||||
use Composer\Package\BasePackage;
|
||||
use Composer\Package\Version\VersionParser;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class PlatformRepository extends ArrayRepository
|
||||
{
|
||||
protected $packages;
|
||||
|
||||
protected function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
$versionParser = new VersionParser();
|
||||
|
||||
try {
|
||||
$version = BasePackage::parseVersion(PHP_VERSION);
|
||||
$version = $versionParser->parse(PHP_VERSION);
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
$version = BasePackage::parseVersion(preg_replace('#^(.+?)(-.+)?$#', '$1', PHP_VERSION));
|
||||
$version = $versionParser->parse(preg_replace('#^(.+?)(-.+)?$#', '$1', PHP_VERSION));
|
||||
}
|
||||
|
||||
$php = new MemoryPackage('php', $version['version'], $version['type']);
|
||||
|
@ -42,7 +43,7 @@ class PlatformRepository extends ArrayRepository
|
|||
|
||||
$reflExt = new \ReflectionExtension($ext);
|
||||
try {
|
||||
$version = BasePackage::parseVersion($reflExt->getVersion());
|
||||
$version = $versionParser->parse($reflExt->getVersion());
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
$version = array('version' => '0', 'type' => 'stable');
|
||||
}
|
||||
|
@ -51,4 +52,4 @@ class PlatformRepository extends ArrayRepository
|
|||
$this->addPackage($ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,29 @@
|
|||
|
||||
namespace Composer\Repository;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Repository interface.
|
||||
*
|
||||
* @author Nils Adermann <naderman@naderman.de>
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
interface RepositoryInterface extends \Countable
|
||||
{
|
||||
/**
|
||||
* Checks if specified package registered (installed).
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
function hasPackage(PackageInterface $package);
|
||||
|
||||
/**
|
||||
* Returns list of registered packages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function getPackages();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
<?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\Repository;
|
||||
|
||||
/**
|
||||
* Repositories manager.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
class RepositoryManager
|
||||
{
|
||||
private $localRepository;
|
||||
private $repositories = array();
|
||||
|
||||
/**
|
||||
* Sets repository with specific name.
|
||||
*
|
||||
* @param string $type repository name
|
||||
* @param RepositoryInterface $repository repository instance
|
||||
*/
|
||||
public function setRepository($type, RepositoryInterface $repository)
|
||||
{
|
||||
$this->repositories[$type] = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns repository for a specific installation type.
|
||||
*
|
||||
* @param string $type installation type
|
||||
*
|
||||
* @return RepositoryInterface
|
||||
*
|
||||
* @throws InvalidArgumentException if repository for provided type is not registeterd
|
||||
*/
|
||||
public function getRepository($type)
|
||||
{
|
||||
if (!isset($this->repositories[$type])) {
|
||||
throw new \InvalidArgumentException('Repository is not registered: '.$type);
|
||||
}
|
||||
|
||||
return $this->repositories[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all repositories, except local one.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRepositories()
|
||||
{
|
||||
return $this->repositories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets local repository for the project.
|
||||
*
|
||||
* @param RepositoryInterface $repository repository instance
|
||||
*/
|
||||
public function setLocalRepository(RepositoryInterface $repository)
|
||||
{
|
||||
$this->localRepository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns local repository for the project.
|
||||
*
|
||||
* @return RepositoryInterface
|
||||
*/
|
||||
public function getLocalRepository()
|
||||
{
|
||||
return $this->localRepository;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
<?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\Repository;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class WrapperRepository extends ArrayRepository implements WritableRepositoryInterface
|
||||
{
|
||||
private $repositories;
|
||||
|
||||
public function __construct(array $repositories)
|
||||
{
|
||||
$this->repositories = $repositories;
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
|
||||
foreach ($this->repositories as $repo) {
|
||||
foreach ($repo->getPackages() as $package) {
|
||||
$this->packages[] = $package;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function addPackage(PackageInterface $package)
|
||||
{
|
||||
throw new \LogicException('Can not add packages to a wrapper repository');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function removePackage(PackageInterface $package)
|
||||
{
|
||||
throw new \LogicException('Can not remove packages to a wrapper repository');
|
||||
}
|
||||
|
||||
public function write()
|
||||
{
|
||||
foreach ($this->repositories as $repo) {
|
||||
if ($repo instanceof WritableRepositoryInterface) {
|
||||
$repo->write();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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\Repository;
|
||||
|
||||
use Composer\Package\PackageInterface;
|
||||
|
||||
/**
|
||||
* Writable repository interface.
|
||||
*
|
||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||
*/
|
||||
interface WritableRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Writes repository (f.e. to the disc).
|
||||
*/
|
||||
function write();
|
||||
|
||||
/**
|
||||
* Adds package to the repository.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
*/
|
||||
function addPackage(PackageInterface $package);
|
||||
|
||||
/**
|
||||
* Removes package from the repository.
|
||||
*
|
||||
* @param PackageInterface $package package instance
|
||||
*/
|
||||
function removePackage(PackageInterface $package);
|
||||
}
|
|
@ -213,25 +213,6 @@ class SolverTest extends \PHPUnit_Framework_TestCase
|
|||
));
|
||||
}
|
||||
|
||||
public function testSolverWithComposerRepo()
|
||||
{
|
||||
$this->repoInstalled = new PlatformRepository;
|
||||
|
||||
// overwrite solver with custom installed repo
|
||||
$this->solver = new Solver($this->policy, $this->pool, $this->repoInstalled);
|
||||
|
||||
$this->repo = new ComposerRepository('http://packagist.org');
|
||||
list($monolog) = $this->repo->getPackages();
|
||||
|
||||
$this->reposComplete();
|
||||
|
||||
$this->request->install('Monolog');
|
||||
|
||||
$this->checkSolverResult(array(
|
||||
array('job' => 'install', 'package' => $monolog),
|
||||
));
|
||||
}
|
||||
|
||||
protected function reposComplete()
|
||||
{
|
||||
$this->pool->addRepository($this->repoInstalled);
|
||||
|
@ -240,10 +221,23 @@ class SolverTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
protected function checkSolverResult(array $expected)
|
||||
{
|
||||
$result = $this->solver->solve($this->request);
|
||||
$transaction = $this->solver->solve($this->request);
|
||||
|
||||
foreach ($result as &$step) {
|
||||
unset($step['why']);
|
||||
$result = array();
|
||||
foreach ($transaction as $operation) {
|
||||
if ('update' === $operation->getJobType()) {
|
||||
$result[] = array(
|
||||
'job' => 'update',
|
||||
'from' => $operation->getInitialPackage(),
|
||||
'to' => $operation->getTargetPackage()
|
||||
);
|
||||
} else {
|
||||
$job = ('uninstall' === $operation->getJobType() ? 'remove' : 'install');
|
||||
$result[] = array(
|
||||
'job' => $job,
|
||||
'package' => $operation->getPackage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
|
|
|
@ -0,0 +1,499 @@
|
|||
<?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\Downloader;
|
||||
|
||||
use Composer\Downloader\DownloadManager;
|
||||
|
||||
class DownloadManagerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testSetGetDownloader()
|
||||
{
|
||||
$downloader = $this->createDownloaderMock();
|
||||
$manager = new DownloadManager();
|
||||
|
||||
$manager->setDownloader('test', $downloader);
|
||||
$this->assertSame($downloader, $manager->getDownloader('test'));
|
||||
|
||||
$this->setExpectedException('UnexpectedValueException');
|
||||
$manager->getDownloader('unregistered');
|
||||
}
|
||||
|
||||
public function testFullPackageDownload()
|
||||
{
|
||||
$package = $this->createPackageMock();
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue('git'));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue('pear'));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistUrl')
|
||||
->will($this->returnValue('dist_url'));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistSha1Checksum')
|
||||
->will($this->returnValue('sha1'));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('setInstallationSource')
|
||||
->with('dist');
|
||||
|
||||
$pearDownloader = $this->createDownloaderMock();
|
||||
$pearDownloader
|
||||
->expects($this->once())
|
||||
->method('download')
|
||||
->with($package, 'target_dir', 'dist_url', 'sha1', false);
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->setDownloader('pear', $pearDownloader);
|
||||
|
||||
$manager->download($package, 'target_dir');
|
||||
}
|
||||
|
||||
public function testBadPackageDownload()
|
||||
{
|
||||
$package = $this->createPackageMock();
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue(null));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue(null));
|
||||
|
||||
$manager = new DownloadManager();
|
||||
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
$manager->download($package, 'target_dir');
|
||||
}
|
||||
|
||||
public function testDistOnlyPackageDownload()
|
||||
{
|
||||
$package = $this->createPackageMock();
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue(null));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue('pear'));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistUrl')
|
||||
->will($this->returnValue('dist_url'));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistSha1Checksum')
|
||||
->will($this->returnValue('sha1'));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('setInstallationSource')
|
||||
->with('dist');
|
||||
|
||||
$pearDownloader = $this->createDownloaderMock();
|
||||
$pearDownloader
|
||||
->expects($this->once())
|
||||
->method('download')
|
||||
->with($package, 'target_dir', 'dist_url', 'sha1', false);
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->setDownloader('pear', $pearDownloader);
|
||||
|
||||
$manager->download($package, 'target_dir');
|
||||
}
|
||||
|
||||
public function testSourceOnlyPackageDownload()
|
||||
{
|
||||
$package = $this->createPackageMock();
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue('git'));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue(null));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceUrl')
|
||||
->will($this->returnValue('source_url'));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('setInstallationSource')
|
||||
->with('source');
|
||||
|
||||
$gitDownloader = $this->createDownloaderMock();
|
||||
$gitDownloader
|
||||
->expects($this->once())
|
||||
->method('download')
|
||||
->with($package, 'vendor/pkg', 'source_url', false);
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->setDownloader('git', $gitDownloader);
|
||||
|
||||
$manager->download($package, 'vendor/pkg');
|
||||
}
|
||||
|
||||
public function testFullPackageDownloadWithSourcePreferred()
|
||||
{
|
||||
$package = $this->createPackageMock();
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue('git'));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue('pear'));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceUrl')
|
||||
->will($this->returnValue('source_url'));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('setInstallationSource')
|
||||
->with('source');
|
||||
|
||||
$gitDownloader = $this->createDownloaderMock();
|
||||
$gitDownloader
|
||||
->expects($this->once())
|
||||
->method('download')
|
||||
->with($package, 'vendor/pkg', 'source_url', true);
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->setDownloader('git', $gitDownloader);
|
||||
$manager->preferSource();
|
||||
|
||||
$manager->download($package, 'vendor/pkg');
|
||||
}
|
||||
|
||||
public function testDistOnlyPackageDownloadWithSourcePreferred()
|
||||
{
|
||||
$package = $this->createPackageMock();
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue(null));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue('pear'));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistUrl')
|
||||
->will($this->returnValue('dist_url'));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistSha1Checksum')
|
||||
->will($this->returnValue('sha1'));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('setInstallationSource')
|
||||
->with('dist');
|
||||
|
||||
$pearDownloader = $this->createDownloaderMock();
|
||||
$pearDownloader
|
||||
->expects($this->once())
|
||||
->method('download')
|
||||
->with($package, 'target_dir', 'dist_url', 'sha1', true);
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->setDownloader('pear', $pearDownloader);
|
||||
$manager->preferSource();
|
||||
|
||||
$manager->download($package, 'target_dir');
|
||||
}
|
||||
|
||||
public function testSourceOnlyPackageDownloadWithSourcePreferred()
|
||||
{
|
||||
$package = $this->createPackageMock();
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue('git'));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue(null));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceUrl')
|
||||
->will($this->returnValue('source_url'));
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('setInstallationSource')
|
||||
->with('source');
|
||||
|
||||
$gitDownloader = $this->createDownloaderMock();
|
||||
$gitDownloader
|
||||
->expects($this->once())
|
||||
->method('download')
|
||||
->with($package, 'vendor/pkg', 'source_url', true);
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->setDownloader('git', $gitDownloader);
|
||||
$manager->preferSource();
|
||||
|
||||
$manager->download($package, 'vendor/pkg');
|
||||
}
|
||||
|
||||
public function testBadPackageDownloadWithSourcePreferred()
|
||||
{
|
||||
$package = $this->createPackageMock();
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue(null));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue(null));
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->preferSource();
|
||||
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
$manager->download($package, 'target_dir');
|
||||
}
|
||||
|
||||
public function testUpdateDistWithEqualTypes()
|
||||
{
|
||||
$initial = $this->createPackageMock();
|
||||
$initial
|
||||
->expects($this->once())
|
||||
->method('getInstallationSource')
|
||||
->will($this->returnValue('dist'));
|
||||
$initial
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue('pear'));
|
||||
|
||||
$target = $this->createPackageMock();
|
||||
$target
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue('pear'));
|
||||
|
||||
$pearDownloader = $this->createDownloaderMock();
|
||||
$pearDownloader
|
||||
->expects($this->once())
|
||||
->method('update')
|
||||
->with($initial, $target, 'vendor/bundles/FOS/UserBundle', false);
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->setDownloader('pear', $pearDownloader);
|
||||
|
||||
$manager->update($initial, $target, 'vendor/bundles/FOS/UserBundle');
|
||||
}
|
||||
|
||||
public function testUpdateDistWithNotEqualTypes()
|
||||
{
|
||||
$initial = $this->createPackageMock();
|
||||
$initial
|
||||
->expects($this->once())
|
||||
->method('getInstallationSource')
|
||||
->will($this->returnValue('dist'));
|
||||
$initial
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue('pear'));
|
||||
|
||||
$target = $this->createPackageMock();
|
||||
$target
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue('composer'));
|
||||
|
||||
$pearDownloader = $this->createDownloaderMock();
|
||||
$pearDownloader
|
||||
->expects($this->once())
|
||||
->method('remove')
|
||||
->with($initial, 'vendor/bundles/FOS/UserBundle', false);
|
||||
|
||||
$manager = $this->getMockBuilder('Composer\Downloader\DownloadManager')
|
||||
->setMethods(array('download'))
|
||||
->getMock();
|
||||
$manager
|
||||
->expects($this->once())
|
||||
->method('download')
|
||||
->with($target, 'vendor/bundles/FOS/UserBundle', false);
|
||||
|
||||
$manager->setDownloader('pear', $pearDownloader);
|
||||
$manager->update($initial, $target, 'vendor/bundles/FOS/UserBundle');
|
||||
}
|
||||
|
||||
public function testUpdateSourceWithEqualTypes()
|
||||
{
|
||||
$initial = $this->createPackageMock();
|
||||
$initial
|
||||
->expects($this->once())
|
||||
->method('getInstallationSource')
|
||||
->will($this->returnValue('source'));
|
||||
$initial
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue('svn'));
|
||||
|
||||
$target = $this->createPackageMock();
|
||||
$target
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue('svn'));
|
||||
|
||||
$svnDownloader = $this->createDownloaderMock();
|
||||
$svnDownloader
|
||||
->expects($this->once())
|
||||
->method('update')
|
||||
->with($initial, $target, 'vendor/pkg', true);
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->setDownloader('svn', $svnDownloader);
|
||||
|
||||
$manager->update($initial, $target, 'vendor/pkg');
|
||||
}
|
||||
|
||||
public function testUpdateSourceWithNotEqualTypes()
|
||||
{
|
||||
$initial = $this->createPackageMock();
|
||||
$initial
|
||||
->expects($this->once())
|
||||
->method('getInstallationSource')
|
||||
->will($this->returnValue('source'));
|
||||
$initial
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue('svn'));
|
||||
|
||||
$target = $this->createPackageMock();
|
||||
$target
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue('git'));
|
||||
|
||||
$svnDownloader = $this->createDownloaderMock();
|
||||
$svnDownloader
|
||||
->expects($this->once())
|
||||
->method('remove')
|
||||
->with($initial, 'vendor/pkg', true);
|
||||
|
||||
$manager = $this->getMockBuilder('Composer\Downloader\DownloadManager')
|
||||
->setMethods(array('download'))
|
||||
->getMock();
|
||||
$manager
|
||||
->expects($this->once())
|
||||
->method('download')
|
||||
->with($target, 'vendor/pkg', true);
|
||||
$manager->setDownloader('svn', $svnDownloader);
|
||||
|
||||
$manager->update($initial, $target, 'vendor/pkg');
|
||||
}
|
||||
|
||||
public function testUpdateBadlyInstalledPackage()
|
||||
{
|
||||
$initial = $this->createPackageMock();
|
||||
$target = $this->createPackageMock();
|
||||
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->update($initial, $target, 'vendor/pkg');
|
||||
}
|
||||
|
||||
public function testRemoveDist()
|
||||
{
|
||||
$package = $this->createPackageMock();
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getInstallationSource')
|
||||
->will($this->returnValue('dist'));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getDistType')
|
||||
->will($this->returnValue('pear'));
|
||||
|
||||
$pearDownloader = $this->createDownloaderMock();
|
||||
$pearDownloader
|
||||
->expects($this->once())
|
||||
->method('remove')
|
||||
->with($package, 'vendor/bundles/FOS/UserBundle');
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->setDownloader('pear', $pearDownloader);
|
||||
|
||||
$manager->remove($package, 'vendor/bundles/FOS/UserBundle');
|
||||
}
|
||||
|
||||
public function testRemoveSource()
|
||||
{
|
||||
$package = $this->createPackageMock();
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getInstallationSource')
|
||||
->will($this->returnValue('source'));
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getSourceType')
|
||||
->will($this->returnValue('svn'));
|
||||
|
||||
$svnDownloader = $this->createDownloaderMock();
|
||||
$svnDownloader
|
||||
->expects($this->once())
|
||||
->method('remove')
|
||||
->with($package, 'vendor/pkg');
|
||||
|
||||
$manager = new DownloadManager();
|
||||
$manager->setDownloader('svn', $svnDownloader);
|
||||
|
||||
$manager->remove($package, 'vendor/pkg');
|
||||
}
|
||||
|
||||
public function testRemoveBadlyInstalledPackage()
|
||||
{
|
||||
$package = $this->createPackageMock();
|
||||
$manager = new DownloadManager();
|
||||
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
$manager->remove($package, 'vendor/pkg');
|
||||
}
|
||||
|
||||
private function createDownloaderMock()
|
||||
{
|
||||
return $this->getMockBuilder('Composer\Downloader\DownloaderInterface')
|
||||
->getMock();
|
||||
}
|
||||
|
||||
private function createPackageMock()
|
||||
{
|
||||
return $this->getMockBuilder('Composer\Package\PackageInterface')
|
||||
->getMock();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
<?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\InstallationManager;
|
||||
use Composer\DependencyResolver\Operation\InstallOperation;
|
||||
use Composer\DependencyResolver\Operation\UpdateOperation;
|
||||
use Composer\DependencyResolver\Operation\UninstallOperation;
|
||||
|
||||
class InstallationManagerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testSetGetInstaller()
|
||||
{
|
||||
$installer = $this->createInstallerMock();
|
||||
$manager = new InstallationManager();
|
||||
|
||||
$manager->setInstaller('vendor', $installer);
|
||||
$this->assertSame($installer, $manager->getInstaller('vendor'));
|
||||
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
$manager->getInstaller('unregistered');
|
||||
}
|
||||
|
||||
public function testExecute()
|
||||
{
|
||||
$manager = $this->getMockBuilder('Composer\Installer\InstallationManager')
|
||||
->setMethods(array('install', 'update', 'uninstall'))
|
||||
->getMock();
|
||||
|
||||
$installOperation = new InstallOperation($this->createPackageMock());
|
||||
$removeOperation = new UninstallOperation($this->createPackageMock());
|
||||
$updateOperation = new UpdateOperation(
|
||||
$this->createPackageMock(), $this->createPackageMock()
|
||||
);
|
||||
|
||||
$manager
|
||||
->expects($this->once())
|
||||
->method('install')
|
||||
->with($installOperation);
|
||||
$manager
|
||||
->expects($this->once())
|
||||
->method('uninstall')
|
||||
->with($removeOperation);
|
||||
$manager
|
||||
->expects($this->once())
|
||||
->method('update')
|
||||
->with($updateOperation);
|
||||
|
||||
$manager->execute($installOperation);
|
||||
$manager->execute($removeOperation);
|
||||
$manager->execute($updateOperation);
|
||||
}
|
||||
|
||||
public function testInstall()
|
||||
{
|
||||
$installer = $this->createInstallerMock();
|
||||
$manager = new InstallationManager();
|
||||
$manager->setInstaller('library', $installer);
|
||||
|
||||
$package = $this->createPackageMock();
|
||||
$operation = new InstallOperation($package, 'test');
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getType')
|
||||
->will($this->returnValue('library'));
|
||||
|
||||
$installer
|
||||
->expects($this->once())
|
||||
->method('install')
|
||||
->with($package);
|
||||
|
||||
$manager->install($operation);
|
||||
}
|
||||
|
||||
public function testUpdateWithEqualTypes()
|
||||
{
|
||||
$installer = $this->createInstallerMock();
|
||||
$manager = new InstallationManager();
|
||||
$manager->setInstaller('library', $installer);
|
||||
|
||||
$initial = $this->createPackageMock();
|
||||
$target = $this->createPackageMock();
|
||||
$operation = new UpdateOperation($initial, $target, 'test');
|
||||
|
||||
$initial
|
||||
->expects($this->once())
|
||||
->method('getType')
|
||||
->will($this->returnValue('library'));
|
||||
$target
|
||||
->expects($this->once())
|
||||
->method('getType')
|
||||
->will($this->returnValue('library'));
|
||||
|
||||
$installer
|
||||
->expects($this->once())
|
||||
->method('update')
|
||||
->with($initial, $target);
|
||||
|
||||
$manager->update($operation);
|
||||
}
|
||||
|
||||
public function testUpdateWithNotEqualTypes()
|
||||
{
|
||||
$installer1 = $this->createInstallerMock();
|
||||
$installer2 = $this->createInstallerMock();
|
||||
$manager = new InstallationManager();
|
||||
$manager->setInstaller('library', $installer1);
|
||||
$manager->setInstaller('bundles', $installer2);
|
||||
|
||||
$initial = $this->createPackageMock();
|
||||
$target = $this->createPackageMock();
|
||||
$operation = new UpdateOperation($initial, $target, 'test');
|
||||
|
||||
$initial
|
||||
->expects($this->once())
|
||||
->method('getType')
|
||||
->will($this->returnValue('library'));
|
||||
$target
|
||||
->expects($this->once())
|
||||
->method('getType')
|
||||
->will($this->returnValue('bundles'));
|
||||
|
||||
$installer1
|
||||
->expects($this->once())
|
||||
->method('uninstall')
|
||||
->with($initial);
|
||||
|
||||
$installer2
|
||||
->expects($this->once())
|
||||
->method('install')
|
||||
->with($target);
|
||||
|
||||
$manager->update($operation);
|
||||
}
|
||||
|
||||
public function testUninstall()
|
||||
{
|
||||
$installer = $this->createInstallerMock();
|
||||
$manager = new InstallationManager();
|
||||
$manager->setInstaller('library', $installer);
|
||||
|
||||
$package = $this->createPackageMock();
|
||||
$operation = new UninstallOperation($package, 'test');
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getType')
|
||||
->will($this->returnValue('library'));
|
||||
|
||||
$installer
|
||||
->expects($this->once())
|
||||
->method('uninstall')
|
||||
->with($package);
|
||||
|
||||
$manager->uninstall($operation);
|
||||
}
|
||||
|
||||
private function createInstallerMock()
|
||||
{
|
||||
return $this->getMockBuilder('Composer\Installer\InstallerInterface')
|
||||
->getMock();
|
||||
}
|
||||
|
||||
private function createPackageMock()
|
||||
{
|
||||
return $this->getMockBuilder('Composer\Package\PackageInterface')
|
||||
->getMock();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
<?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 $repository;
|
||||
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->repository = $this->getMockBuilder('Composer\Repository\WritableRepositoryInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
public function testInstallerCreation()
|
||||
{
|
||||
$library = new LibraryInstaller($this->dir, $this->dm, $this->repository);
|
||||
$this->assertTrue(is_dir($this->dir));
|
||||
|
||||
$file = sys_get_temp_dir().'/file';
|
||||
touch($file);
|
||||
|
||||
$this->setExpectedException('UnexpectedValueException');
|
||||
$library = new LibraryInstaller($file, $this->dm, $this->repository);
|
||||
}
|
||||
|
||||
public function testIsInstalled()
|
||||
{
|
||||
$library = new LibraryInstaller($this->dir, $this->dm, $this->repository);
|
||||
$package = $this->createPackageMock();
|
||||
|
||||
$this->repository
|
||||
->expects($this->exactly(2))
|
||||
->method('hasPackage')
|
||||
->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->repository);
|
||||
$package = $this->createPackageMock();
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getName')
|
||||
->will($this->returnValue('some/package'));
|
||||
|
||||
$this->dm
|
||||
->expects($this->once())
|
||||
->method('download')
|
||||
->with($package, $this->dir.'/some/package');
|
||||
|
||||
$this->repository
|
||||
->expects($this->once())
|
||||
->method('addPackage')
|
||||
->with($package);
|
||||
|
||||
$library->install($package);
|
||||
}
|
||||
|
||||
public function testUpdate()
|
||||
{
|
||||
$library = new LibraryInstaller($this->dir, $this->dm, $this->repository);
|
||||
$initial = $this->createPackageMock();
|
||||
$target = $this->createPackageMock();
|
||||
|
||||
$initial
|
||||
->expects($this->once())
|
||||
->method('getName')
|
||||
->will($this->returnValue('package1'));
|
||||
|
||||
$this->repository
|
||||
->expects($this->exactly(2))
|
||||
->method('hasPackage')
|
||||
->with($initial)
|
||||
->will($this->onConsecutiveCalls(true, false));
|
||||
|
||||
$this->dm
|
||||
->expects($this->once())
|
||||
->method('update')
|
||||
->with($initial, $target, $this->dir.'/package1');
|
||||
|
||||
$this->repository
|
||||
->expects($this->once())
|
||||
->method('removePackage')
|
||||
->with($initial);
|
||||
|
||||
$this->repository
|
||||
->expects($this->once())
|
||||
->method('addPackage')
|
||||
->with($target);
|
||||
|
||||
$library->update($initial, $target);
|
||||
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
$library->update($initial, $target);
|
||||
}
|
||||
|
||||
public function testUninstall()
|
||||
{
|
||||
$library = new LibraryInstaller($this->dir, $this->dm, $this->repository);
|
||||
$package = $this->createPackageMock();
|
||||
|
||||
$package
|
||||
->expects($this->once())
|
||||
->method('getName')
|
||||
->will($this->returnValue('pkg'));
|
||||
|
||||
$this->repository
|
||||
->expects($this->exactly(2))
|
||||
->method('hasPackage')
|
||||
->with($package)
|
||||
->will($this->onConsecutiveCalls(true, false));
|
||||
|
||||
$this->dm
|
||||
->expects($this->once())
|
||||
->method('remove')
|
||||
->with($package, $this->dir.'/pkg');
|
||||
|
||||
$this->repository
|
||||
->expects($this->once())
|
||||
->method('removePackage')
|
||||
->with($package);
|
||||
|
||||
$library->uninstall($package);
|
||||
|
||||
$this->setExpectedException('InvalidArgumentException');
|
||||
|
||||
$library->uninstall($package);
|
||||
}
|
||||
|
||||
private function createPackageMock()
|
||||
{
|
||||
return $this->getMockBuilder('Composer\Package\MemoryPackage')
|
||||
->setConstructorArgs(array(md5(rand()), '1.0.0'))
|
||||
->getMock();
|
||||
}
|
||||
}
|
|
@ -17,11 +17,37 @@ use Composer\Package\MemoryPackage;
|
|||
|
||||
class ArrayRepositoryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testAddLiteral()
|
||||
public function testAddPackage()
|
||||
{
|
||||
$repo = new ArrayRepository;
|
||||
$repo->addPackage(new MemoryPackage('foo', '1'));
|
||||
|
||||
$this->assertEquals(1, count($repo));
|
||||
}
|
||||
|
||||
public function testRemovePackage()
|
||||
{
|
||||
$package = new MemoryPackage('bar', '2');
|
||||
|
||||
$repo = new ArrayRepository;
|
||||
$repo->addPackage(new MemoryPackage('foo', '1'));
|
||||
$repo->addPackage($package);
|
||||
|
||||
$this->assertEquals(2, count($repo));
|
||||
|
||||
$repo->removePackage(new MemoryPackage('foo', '1'));
|
||||
|
||||
$this->assertEquals(1, count($repo));
|
||||
$this->assertEquals(array($package), $repo->getPackages());
|
||||
}
|
||||
|
||||
public function testHasPackage()
|
||||
{
|
||||
$repo = new ArrayRepository;
|
||||
$repo->addPackage(new MemoryPackage('foo', '1'));
|
||||
$repo->addPackage(new MemoryPackage('bar', '2'));
|
||||
|
||||
$this->assertTrue($repo->hasPackage(new MemoryPackage('foo', '1')));
|
||||
$this->assertFalse($repo->hasPackage(new MemoryPackage('bar', '1')));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<?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\Repository;
|
||||
|
||||
use Composer\Repository\FilesystemRepository;
|
||||
|
||||
class FilesystemRepositoryTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $dir;
|
||||
private $repositoryFile;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->dir = sys_get_temp_dir().'/.composer';
|
||||
$this->repositoryFile = $this->dir.'/some_registry-reg.json';
|
||||
|
||||
if (file_exists($this->repositoryFile)) {
|
||||
unlink($this->repositoryFile);
|
||||
}
|
||||
}
|
||||
|
||||
public function testRepositoryReadWrite()
|
||||
{
|
||||
$this->assertFileNotExists($this->repositoryFile);
|
||||
$repository = new FilesystemRepository($this->repositoryFile);
|
||||
|
||||
$repository->getPackages();
|
||||
$repository->write();
|
||||
$this->assertFileExists($this->repositoryFile);
|
||||
|
||||
file_put_contents($this->repositoryFile, json_encode(array(
|
||||
array('name' => 'package1', 'version' => '1.0.0-beta', 'type' => 'vendor')
|
||||
)));
|
||||
|
||||
$repository = new FilesystemRepository($this->repositoryFile);
|
||||
$repository->getPackages();
|
||||
$repository->write();
|
||||
$this->assertFileExists($this->repositoryFile);
|
||||
|
||||
$data = json_decode(file_get_contents($this->repositoryFile), true);
|
||||
$this->assertEquals(array(
|
||||
array('name' => 'package1', 'type' => 'vendor', 'version' => '1.0.0', 'releaseType' => 'beta', 'names' => array('package1'))
|
||||
), $data);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue