Integrating the command system with Symfony's command system
Parts are still a WIP, as there are some embedded echo statements that should eventually be run through some sort of output interface.pull/12/merge^2
parent
61917cb7f7
commit
f5b054985a
|
@ -9,12 +9,15 @@ use Composer\Downloader\PearDownloader;
|
||||||
use Composer\Downloader\ZipDownloader;
|
use Composer\Downloader\ZipDownloader;
|
||||||
use Composer\Command\InstallCommand;
|
use Composer\Command\InstallCommand;
|
||||||
use Composer\Installer\LibraryInstaller;
|
use Composer\Installer\LibraryInstaller;
|
||||||
|
use Composer\Console\Application;
|
||||||
|
|
||||||
|
// initialize composer
|
||||||
$composer = new Composer();
|
$composer = new Composer();
|
||||||
$composer->addDownloader('git', new GitDownloader);
|
$composer->addDownloader('git', new GitDownloader);
|
||||||
$composer->addDownloader('pear', new PearDownloader);
|
$composer->addDownloader('pear', new PearDownloader);
|
||||||
$composer->addDownloader('zip', new ZipDownloader);
|
$composer->addDownloader('zip', new ZipDownloader);
|
||||||
$composer->addInstaller('library', new LibraryInstaller);
|
$composer->addInstaller('library', new LibraryInstaller);
|
||||||
|
|
||||||
$cmd = new InstallCommand();
|
// run the command application
|
||||||
$cmd->install($composer);
|
$application = new Application($composer);
|
||||||
|
$application->run();
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?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\Command;
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Command\Command as BaseCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for Composer commands
|
||||||
|
*
|
||||||
|
* @author Ryan Weaver <ryan@knplabs.com>
|
||||||
|
*/
|
||||||
|
abstract class Command extends BaseCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return \Composer\Composer
|
||||||
|
*/
|
||||||
|
public function getComposer()
|
||||||
|
{
|
||||||
|
return $this->getApplication()->getComposer();
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,27 +20,36 @@ use Composer\Repository\PlatformRepository;
|
||||||
use Composer\Package\MemoryPackage;
|
use Composer\Package\MemoryPackage;
|
||||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @author Ryan Weaver <ryan@knplabs.com>
|
||||||
*/
|
*/
|
||||||
class InstallCommand
|
class InstallCommand extends Command
|
||||||
{
|
{
|
||||||
protected $composer;
|
protected function configure()
|
||||||
|
|
||||||
public function install($composer)
|
|
||||||
{
|
{
|
||||||
$this->composer = $composer;
|
$this
|
||||||
|
->setName('install')
|
||||||
|
->setDescription('Parses the composer.json file and downloads the needed dependencies.')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
// TODO this needs a parameter to enable installing from source (i.e. git clone, instead of downloading archives)
|
||||||
$sourceInstall = false;
|
$sourceInstall = false;
|
||||||
|
|
||||||
$config = $this->loadConfig();
|
$config = $this->loadConfig();
|
||||||
|
|
||||||
echo 'Loading repositories'.PHP_EOL;
|
$output->writeln('<info>Loading repositories</info>');
|
||||||
|
|
||||||
if (isset($config['repositories'])) {
|
if (isset($config['repositories'])) {
|
||||||
foreach ($config['repositories'] as $name => $spec) {
|
foreach ($config['repositories'] as $name => $spec) {
|
||||||
$composer->addRepository($name, $spec);
|
$this->getComposer()->addRepository($name, $spec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,15 +61,15 @@ class InstallCommand
|
||||||
// TODO check the lock file to see what's currently installed
|
// TODO check the lock file to see what's currently installed
|
||||||
// $repoInstalled->addPackage(new MemoryPackage('$Package', '$Version'));
|
// $repoInstalled->addPackage(new MemoryPackage('$Package', '$Version'));
|
||||||
|
|
||||||
echo 'Loading package list'.PHP_EOL;
|
$output->writeln('Loading package list');
|
||||||
|
|
||||||
foreach ($composer->getRepositories() as $repository) {
|
foreach ($this->getComposer()->getRepositories() as $repository) {
|
||||||
$pool->addRepository($repository);
|
$pool->addRepository($repository);
|
||||||
}
|
}
|
||||||
|
|
||||||
$request = new Request($pool);
|
$request = new Request($pool);
|
||||||
|
|
||||||
echo 'Building up request'.PHP_EOL;
|
$output->writeln('Building up request');
|
||||||
|
|
||||||
// TODO there should be an update flag or dedicated update command
|
// TODO there should be an update flag or dedicated update command
|
||||||
// TODO check lock file to remove packages that disappeared from the requirements
|
// TODO check lock file to remove packages that disappeared from the requirements
|
||||||
|
@ -78,7 +87,7 @@ class InstallCommand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
echo 'Solving dependencies'.PHP_EOL;
|
$output->writeln('Solving dependencies');
|
||||||
|
|
||||||
$policy = new DefaultPolicy;
|
$policy = new DefaultPolicy;
|
||||||
$solver = new Solver($policy, $pool, $repoInstalled);
|
$solver = new Solver($policy, $pool, $repoInstalled);
|
||||||
|
@ -90,7 +99,7 @@ class InstallCommand
|
||||||
switch ($task['job']) {
|
switch ($task['job']) {
|
||||||
case 'install':
|
case 'install':
|
||||||
$package = $task['package'];
|
$package = $task['package'];
|
||||||
echo '> Installing '.$package->getName().PHP_EOL;
|
$output->writeln('> Installing '.$package->getName());
|
||||||
if ($sourceInstall) {
|
if ($sourceInstall) {
|
||||||
// TODO
|
// TODO
|
||||||
} else {
|
} else {
|
||||||
|
@ -98,14 +107,14 @@ class InstallCommand
|
||||||
$downloaderType = $package->getDistType();
|
$downloaderType = $package->getDistType();
|
||||||
$type = 'dist';
|
$type = 'dist';
|
||||||
} elseif ($package->getSourceType()) {
|
} elseif ($package->getSourceType()) {
|
||||||
echo 'Package '.$package->getName().' has no dist url, installing from source instead.';
|
$output->writeln('Package '.$package->getName().' has no dist url, installing from source instead.');
|
||||||
$downloaderType = $package->getSourceType();
|
$downloaderType = $package->getSourceType();
|
||||||
$type = 'source';
|
$type = 'source';
|
||||||
} else {
|
} else {
|
||||||
throw new \UnexpectedValueException('Package '.$package->getName().' has no source or dist URL.');
|
throw new \UnexpectedValueException('Package '.$package->getName().' has no source or dist URL.');
|
||||||
}
|
}
|
||||||
$downloader = $composer->getDownloader($downloaderType);
|
$downloader = $this->getComposer()->getDownloader($downloaderType);
|
||||||
$installer = $composer->getInstaller($package->getType());
|
$installer = $this->getComposer()->getInstaller($package->getType());
|
||||||
if (!$installer->install($package, $downloader, $type)) {
|
if (!$installer->install($package, $downloader, $type)) {
|
||||||
throw new \LogicException($package->getName().' could not be installed.');
|
throw new \LogicException($package->getName().' could not be installed.');
|
||||||
}
|
}
|
||||||
|
@ -116,9 +125,9 @@ class InstallCommand
|
||||||
throw new \UnexpectedValueException('Unhandled job type : '.$task['job']);
|
throw new \UnexpectedValueException('Unhandled job type : '.$task['job']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
echo '> Done'.PHP_EOL;
|
$output->writeln('> Done');
|
||||||
|
|
||||||
$this->storeLockFile($lock);
|
$this->storeLockFile($lock, $output);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function loadConfig()
|
protected function loadConfig()
|
||||||
|
@ -153,10 +162,11 @@ class InstallCommand
|
||||||
return $config;
|
return $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function storeLockFile(array $content)
|
protected function storeLockFile(array $content, OutputInterface $output)
|
||||||
{
|
{
|
||||||
file_put_contents('composer.lock', json_encode($content, JSON_FORCE_OBJECT)."\n");
|
file_put_contents('composer.lock', json_encode($content, JSON_FORCE_OBJECT)."\n");
|
||||||
echo '> composer.lock dumped'.PHP_EOL;
|
$output->writeln('> composer.lock dumped');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function lowercase($str)
|
protected function lowercase($str)
|
||||||
|
|
|
@ -22,6 +22,8 @@ use Composer\Repository\PearRepository;
|
||||||
*/
|
*/
|
||||||
class Composer
|
class Composer
|
||||||
{
|
{
|
||||||
|
const VERSION = '1.0.0-DEV';
|
||||||
|
|
||||||
protected $repositories = array();
|
protected $repositories = array();
|
||||||
protected $downloaders = array();
|
protected $downloaders = array();
|
||||||
protected $installers = array();
|
protected $installers = array();
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?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\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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console application that handles the commands
|
||||||
|
*
|
||||||
|
* @author Ryan Weaver <ryan@knplabs.com>
|
||||||
|
*/
|
||||||
|
class Application extends BaseApplication
|
||||||
|
{
|
||||||
|
private $composer;
|
||||||
|
|
||||||
|
public function __construct(Composer $composer)
|
||||||
|
{
|
||||||
|
parent::__construct('Composer', Composer::VERSION);
|
||||||
|
|
||||||
|
$this->composer = $composer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the current application.
|
||||||
|
*
|
||||||
|
* @param InputInterface $input An Input instance
|
||||||
|
* @param OutputInterface $output An Output instance
|
||||||
|
*
|
||||||
|
* @return integer 0 if everything went fine, or an error code
|
||||||
|
*/
|
||||||
|
public function doRun(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$this->registerCommands();
|
||||||
|
|
||||||
|
return parent::doRun($input, $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Composer
|
||||||
|
*/
|
||||||
|
public function getComposer()
|
||||||
|
{
|
||||||
|
return $this->composer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks for all *Command files in Composer's Command directory
|
||||||
|
*/
|
||||||
|
protected function registerCommands()
|
||||||
|
{
|
||||||
|
$dir = __DIR__.'/../Command';
|
||||||
|
$finder = new Finder();
|
||||||
|
$finder->files()->name('*Command.php')->in($dir);
|
||||||
|
|
||||||
|
foreach ($finder as $file) {
|
||||||
|
$ns = 'Composer\\Command';
|
||||||
|
if ($relativePath = $file->getRelativePath()) {
|
||||||
|
$ns .= '\\'.strtr($relativePath, '/', '\\');
|
||||||
|
}
|
||||||
|
$r = new \ReflectionClass($ns.'\\'.$file->getBasename('.php'));
|
||||||
|
if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract()) {
|
||||||
|
$this->add($r->newInstance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue