Merge remote-tracking branch 'francoispluchino/master'
Conflicts: src/Composer/Repository/Vcs/GitDriver.php src/Composer/Repository/Vcs/HgDriver.php src/Composer/Repository/Vcs/SvnDriver.phppull/219/merge
commit
6492118f29
|
@ -111,7 +111,7 @@ EOT
|
||||||
$request->install($package->getName(), $constraint);
|
$request->install($package->getName(), $constraint);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$output->writeln('<info>Installing dependencies.</info>');
|
$output->writeln('<info>Installing dependencies</info>');
|
||||||
|
|
||||||
$links = $this->collectLinks($input, $composer->getPackage());
|
$links = $this->collectLinks($input, $composer->getPackage());
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ EOT
|
||||||
// prepare solver
|
// prepare solver
|
||||||
$installationManager = $composer->getInstallationManager();
|
$installationManager = $composer->getInstallationManager();
|
||||||
$policy = new DependencyResolver\DefaultPolicy();
|
$policy = new DependencyResolver\DefaultPolicy();
|
||||||
$solver = new DependencyResolver\Solver($policy, $pool, $installedRepo);
|
$solver = new DependencyResolver\Solver($policy, $pool, $installedRepo, $this->getApplication()->getIO());
|
||||||
|
|
||||||
// solve dependencies
|
// solve dependencies
|
||||||
$operations = $solver->solve($request);
|
$operations = $solver->solve($request);
|
||||||
|
|
|
@ -22,16 +22,20 @@ use Symfony\Component\Finder\Finder;
|
||||||
use Composer\Command;
|
use Composer\Command;
|
||||||
use Composer\Composer;
|
use Composer\Composer;
|
||||||
use Composer\Factory;
|
use Composer\Factory;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
use Composer\IO\ConsoleIO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console application that handles the commands
|
* The console application that handles the commands
|
||||||
*
|
*
|
||||||
* @author Ryan Weaver <ryan@knplabs.com>
|
* @author Ryan Weaver <ryan@knplabs.com>
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @author François Pluchino <francois.pluchino@opendisplay.com>
|
||||||
*/
|
*/
|
||||||
class Application extends BaseApplication
|
class Application extends BaseApplication
|
||||||
{
|
{
|
||||||
protected $composer;
|
protected $composer;
|
||||||
|
protected $io;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
|
@ -59,6 +63,7 @@ class Application extends BaseApplication
|
||||||
public function doRun(InputInterface $input, OutputInterface $output)
|
public function doRun(InputInterface $input, OutputInterface $output)
|
||||||
{
|
{
|
||||||
$this->registerCommands();
|
$this->registerCommands();
|
||||||
|
$this->io = new ConsoleIO($input, $output, $this->getHelperSet());
|
||||||
|
|
||||||
return parent::doRun($input, $output);
|
return parent::doRun($input, $output);
|
||||||
}
|
}
|
||||||
|
@ -70,9 +75,9 @@ class Application extends BaseApplication
|
||||||
{
|
{
|
||||||
if (null === $this->composer) {
|
if (null === $this->composer) {
|
||||||
try {
|
try {
|
||||||
$this->composer = Factory::create();
|
$this->composer = Factory::create($this->io);
|
||||||
} catch (\InvalidArgumentException $e) {
|
} catch (\InvalidArgumentException $e) {
|
||||||
echo $e->getMessage().PHP_EOL;
|
$this->io->writeln($e->getMessage());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,6 +85,14 @@ class Application extends BaseApplication
|
||||||
return $this->composer;
|
return $this->composer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return IOInterface
|
||||||
|
*/
|
||||||
|
public function getIO()
|
||||||
|
{
|
||||||
|
return $this->io;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes all the composer commands
|
* Initializes all the composer commands
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
namespace Composer\DependencyResolver;
|
namespace Composer\DependencyResolver;
|
||||||
|
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Repository\RepositoryInterface;
|
use Composer\Repository\RepositoryInterface;
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
use Composer\DependencyResolver\Operation;
|
use Composer\DependencyResolver\Operation;
|
||||||
|
@ -55,12 +56,15 @@ class Solver
|
||||||
protected $packageToUpdateRule = array();
|
protected $packageToUpdateRule = array();
|
||||||
protected $packageToFeatureRule = array();
|
protected $packageToFeatureRule = array();
|
||||||
|
|
||||||
public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed)
|
protected $io;
|
||||||
|
|
||||||
|
public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
|
||||||
{
|
{
|
||||||
$this->policy = $policy;
|
$this->policy = $policy;
|
||||||
$this->pool = $pool;
|
$this->pool = $pool;
|
||||||
$this->installed = $installed;
|
$this->installed = $installed;
|
||||||
$this->rules = new RuleSet;
|
$this->rules = new RuleSet;
|
||||||
|
$this->io = $io;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2046,26 +2050,26 @@ class Solver
|
||||||
|
|
||||||
public function printDecisionMap()
|
public function printDecisionMap()
|
||||||
{
|
{
|
||||||
echo "\nDecisionMap: \n";
|
$this->io->writeln("\nDecisionMap: ");
|
||||||
foreach ($this->decisionMap as $packageId => $level) {
|
foreach ($this->decisionMap as $packageId => $level) {
|
||||||
if ($packageId === 0) {
|
if ($packageId === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ($level > 0) {
|
if ($level > 0) {
|
||||||
echo ' +' . $this->pool->packageById($packageId) . "\n";
|
$this->io->writeln(' +' . $this->pool->packageById($packageId));
|
||||||
} else {
|
} else {
|
||||||
echo ' -' . $this->pool->packageById($packageId) . "\n";
|
$this->io->writeln(' -' . $this->pool->packageById($packageId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
echo "\n";
|
$this->io->writeln('');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function printDecisionQueue()
|
public function printDecisionQueue()
|
||||||
{
|
{
|
||||||
echo "DecisionQueue: \n";
|
$this->io->writeln("DecisionQueue: ");
|
||||||
foreach ($this->decisionQueue as $i => $literal) {
|
foreach ($this->decisionQueue as $i => $literal) {
|
||||||
echo ' ' . $literal . ' ' . $this->decisionQueueWhy[$i] . "\n";
|
$this->io->writeln(' ' . $literal . ' ' . $this->decisionQueueWhy[$i]);
|
||||||
}
|
}
|
||||||
echo "\n";
|
$this->io->writeln('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
namespace Composer\Downloader;
|
namespace Composer\Downloader;
|
||||||
|
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,9 +19,23 @@ use Composer\Package\PackageInterface;
|
||||||
*
|
*
|
||||||
* @author Kirill chEbba Chebunin <iam@chebba.org>
|
* @author Kirill chEbba Chebunin <iam@chebba.org>
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @author François Pluchino <francois.pluchino@opendisplay.com>
|
||||||
*/
|
*/
|
||||||
abstract class FileDownloader implements DownloaderInterface
|
abstract class FileDownloader implements DownloaderInterface
|
||||||
{
|
{
|
||||||
|
protected $io;
|
||||||
|
protected $bytesMax;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param IOInterface $io The IO instance
|
||||||
|
*/
|
||||||
|
public function __construct(IOInterface $io)
|
||||||
|
{
|
||||||
|
$this->io = $io;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
@ -34,6 +49,9 @@ abstract class FileDownloader implements DownloaderInterface
|
||||||
*/
|
*/
|
||||||
public function download(PackageInterface $package, $path)
|
public function download(PackageInterface $package, $path)
|
||||||
{
|
{
|
||||||
|
// init the progress bar
|
||||||
|
$this->bytesMax = 0;
|
||||||
|
|
||||||
$url = $package->getDistUrl();
|
$url = $package->getDistUrl();
|
||||||
$checksum = $package->getDistSha1Checksum();
|
$checksum = $package->getDistSha1Checksum();
|
||||||
|
|
||||||
|
@ -48,7 +66,7 @@ abstract class FileDownloader implements DownloaderInterface
|
||||||
|
|
||||||
$fileName = rtrim($path.'/'.md5(time().rand()).'.'.pathinfo($url, PATHINFO_EXTENSION), '.');
|
$fileName = rtrim($path.'/'.md5(time().rand()).'.'.pathinfo($url, PATHINFO_EXTENSION), '.');
|
||||||
|
|
||||||
echo 'Downloading '.$url.' to '.$fileName.PHP_EOL;
|
$this->io->writeln(" - Package <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
|
||||||
|
|
||||||
if (!extension_loaded('openssl') && (0 === strpos($url, 'https:') || 0 === strpos($url, 'http://github.com'))) {
|
if (!extension_loaded('openssl') && (0 === strpos($url, 'https:') || 0 === strpos($url, 'http://github.com'))) {
|
||||||
// bypass https for github if openssl is disabled
|
// bypass https for github if openssl is disabled
|
||||||
|
@ -60,6 +78,8 @@ abstract class FileDownloader implements DownloaderInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle system proxy
|
// Handle system proxy
|
||||||
|
$params = array('http' => array());
|
||||||
|
|
||||||
if (isset($_SERVER['HTTP_PROXY'])) {
|
if (isset($_SERVER['HTTP_PROXY'])) {
|
||||||
// http(s):// is not supported in proxy
|
// http(s):// is not supported in proxy
|
||||||
$proxy = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $_SERVER['HTTP_PROXY']);
|
$proxy = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $_SERVER['HTTP_PROXY']);
|
||||||
|
@ -68,18 +88,25 @@ abstract class FileDownloader implements DownloaderInterface
|
||||||
throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
|
throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
|
||||||
}
|
}
|
||||||
|
|
||||||
$ctx = stream_context_create(array(
|
$params['http'] = array(
|
||||||
'http' => array(
|
|
||||||
'proxy' => $proxy,
|
'proxy' => $proxy,
|
||||||
'request_fulluri' => true,
|
'request_fulluri' => true,
|
||||||
),
|
);
|
||||||
));
|
|
||||||
|
|
||||||
copy($url, $fileName, $ctx);
|
|
||||||
} else {
|
|
||||||
copy($url, $fileName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->io->hasAuthorization($package->getSourceUrl())) {
|
||||||
|
$auth = $this->io->getAuthorization($package->getSourceUrl());
|
||||||
|
$authStr = base64_encode($auth['username'] . ':' . $auth['password']);
|
||||||
|
$params['http'] = array_merge($params['http'], array('header' => "Authorization: Basic $authStr\r\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
$ctx = stream_context_create($params);
|
||||||
|
stream_context_set_params($ctx, array("notification" => array($this, 'callbackGet')));
|
||||||
|
|
||||||
|
$this->io->overwrite(" Downloading: <comment>connection...</comment>", 80);
|
||||||
|
copy($url, $fileName, $ctx);
|
||||||
|
$this->io->overwriteln(" Downloading", 80);
|
||||||
|
|
||||||
if (!file_exists($fileName)) {
|
if (!file_exists($fileName)) {
|
||||||
throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
|
throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
|
||||||
.' directory is writable and you have internet connectivity');
|
.' directory is writable and you have internet connectivity');
|
||||||
|
@ -89,11 +116,11 @@ abstract class FileDownloader implements DownloaderInterface
|
||||||
throw new \UnexpectedValueException('The checksum verification of the archive failed (downloaded from '.$url.')');
|
throw new \UnexpectedValueException('The checksum verification of the archive failed (downloaded from '.$url.')');
|
||||||
}
|
}
|
||||||
|
|
||||||
echo 'Unpacking archive'.PHP_EOL;
|
$this->io->writeln(' Unpacking archive');
|
||||||
$this->extract($fileName, $path);
|
$this->extract($fileName, $path);
|
||||||
|
|
||||||
|
|
||||||
echo 'Cleaning up'.PHP_EOL;
|
$this->io->writeln(' Cleaning up');
|
||||||
unlink($fileName);
|
unlink($fileName);
|
||||||
|
|
||||||
// If we have only a one dir inside it suppose to be a package itself
|
// If we have only a one dir inside it suppose to be a package itself
|
||||||
|
@ -107,6 +134,8 @@ abstract class FileDownloader implements DownloaderInterface
|
||||||
}
|
}
|
||||||
rmdir($contentDir);
|
rmdir($contentDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->io->writeln('');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -128,6 +157,52 @@ abstract class FileDownloader implements DownloaderInterface
|
||||||
$fs->removeDirectory($path);
|
$fs->removeDirectory($path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get notification action.
|
||||||
|
*
|
||||||
|
* @param integer $notificationCode The notification code
|
||||||
|
* @param integer $severity The severity level
|
||||||
|
* @param string $message The message
|
||||||
|
* @param integer $messageCode The message code
|
||||||
|
* @param integer $bytesTransferred The loaded size
|
||||||
|
* @param integer $bytesMax The total size
|
||||||
|
*/
|
||||||
|
protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
|
||||||
|
{
|
||||||
|
switch ($notificationCode) {
|
||||||
|
case STREAM_NOTIFY_AUTH_REQUIRED:
|
||||||
|
throw new \LogicException("Authorization is required");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STREAM_NOTIFY_FAILURE:
|
||||||
|
throw new \LogicException("File not found");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STREAM_NOTIFY_FILE_SIZE_IS:
|
||||||
|
if ($this->bytesMax < $bytesMax) {
|
||||||
|
$this->bytesMax = $bytesMax;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STREAM_NOTIFY_PROGRESS:
|
||||||
|
if ($this->bytesMax > 0) {
|
||||||
|
$progression = 0;
|
||||||
|
|
||||||
|
if ($this->bytesMax > 0) {
|
||||||
|
$progression = round($bytesTransferred / $this->bytesMax * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 === $progression % 5) {
|
||||||
|
$this->io->overwrite(" Downloading: <comment>$progression%</comment>", 80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract file to directory
|
* Extract file to directory
|
||||||
*
|
*
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
namespace Composer;
|
namespace Composer;
|
||||||
|
|
||||||
use Composer\Json\JsonFile;
|
use Composer\Json\JsonFile;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an configured instance of composer.
|
* Creates an configured instance of composer.
|
||||||
|
@ -28,7 +29,7 @@ class Factory
|
||||||
*
|
*
|
||||||
* @return Composer
|
* @return Composer
|
||||||
*/
|
*/
|
||||||
public function createComposer($composerFile = null)
|
public function createComposer(IOInterface $io, $composerFile = null)
|
||||||
{
|
{
|
||||||
// load Composer configuration
|
// load Composer configuration
|
||||||
if (null === $composerFile) {
|
if (null === $composerFile) {
|
||||||
|
@ -66,13 +67,13 @@ class Factory
|
||||||
$binDir = getenv('COMPOSER_BIN_DIR') ?: $packageConfig['config']['bin-dir'];
|
$binDir = getenv('COMPOSER_BIN_DIR') ?: $packageConfig['config']['bin-dir'];
|
||||||
|
|
||||||
// initialize repository manager
|
// initialize repository manager
|
||||||
$rm = $this->createRepositoryManager($vendorDir);
|
$rm = $this->createRepositoryManager($io, $vendorDir);
|
||||||
|
|
||||||
// initialize download manager
|
// initialize download manager
|
||||||
$dm = $this->createDownloadManager();
|
$dm = $this->createDownloadManager($io);
|
||||||
|
|
||||||
// initialize installation manager
|
// initialize installation manager
|
||||||
$im = $this->createInstallationManager($rm, $dm, $vendorDir, $binDir);
|
$im = $this->createInstallationManager($rm, $dm, $vendorDir, $binDir, $io);
|
||||||
|
|
||||||
// load package
|
// load package
|
||||||
$loader = new Package\Loader\RootPackageLoader($rm);
|
$loader = new Package\Loader\RootPackageLoader($rm);
|
||||||
|
@ -98,9 +99,9 @@ class Factory
|
||||||
return $composer;
|
return $composer;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createRepositoryManager($vendorDir)
|
protected function createRepositoryManager(IOInterface $io, $vendorDir)
|
||||||
{
|
{
|
||||||
$rm = new Repository\RepositoryManager();
|
$rm = new Repository\RepositoryManager($io);
|
||||||
$rm->setLocalRepository(new Repository\FilesystemRepository(new JsonFile($vendorDir.'/.composer/installed.json')));
|
$rm->setLocalRepository(new Repository\FilesystemRepository(new JsonFile($vendorDir.'/.composer/installed.json')));
|
||||||
$rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
|
$rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
|
||||||
$rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
|
$rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
|
||||||
|
@ -110,31 +111,31 @@ class Factory
|
||||||
return $rm;
|
return $rm;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createDownloadManager()
|
protected function createDownloadManager(IOInterface $io)
|
||||||
{
|
{
|
||||||
$dm = new Downloader\DownloadManager();
|
$dm = new Downloader\DownloadManager();
|
||||||
$dm->setDownloader('git', new Downloader\GitDownloader());
|
$dm->setDownloader('git', new Downloader\GitDownloader());
|
||||||
$dm->setDownloader('svn', new Downloader\SvnDownloader());
|
$dm->setDownloader('svn', new Downloader\SvnDownloader());
|
||||||
$dm->setDownloader('hg', new Downloader\HgDownloader());
|
$dm->setDownloader('hg', new Downloader\HgDownloader());
|
||||||
$dm->setDownloader('pear', new Downloader\PearDownloader());
|
$dm->setDownloader('pear', new Downloader\PearDownloader($io));
|
||||||
$dm->setDownloader('zip', new Downloader\ZipDownloader());
|
$dm->setDownloader('zip', new Downloader\ZipDownloader($io));
|
||||||
|
|
||||||
return $dm;
|
return $dm;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createInstallationManager(Repository\RepositoryManager $rm, Downloader\DownloadManager $dm, $vendorDir, $binDir)
|
protected function createInstallationManager(Repository\RepositoryManager $rm, Downloader\DownloadManager $dm, $vendorDir, $binDir, IOInterface $io)
|
||||||
{
|
{
|
||||||
$im = new Installer\InstallationManager($vendorDir);
|
$im = new Installer\InstallationManager($vendorDir);
|
||||||
$im->addInstaller(new Installer\LibraryInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), null));
|
$im->addInstaller(new Installer\LibraryInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), $io, null));
|
||||||
$im->addInstaller(new Installer\InstallerInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), $im));
|
$im->addInstaller(new Installer\InstallerInstaller($vendorDir, $binDir, $dm, $rm->getLocalRepository(), $io, $im));
|
||||||
|
|
||||||
return $im;
|
return $im;
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function create($composerFile = null)
|
static public function create(IOInterface $io, $composerFile = null)
|
||||||
{
|
{
|
||||||
$factory = new static();
|
$factory = new static();
|
||||||
|
|
||||||
return $factory->createComposer($composerFile);
|
return $factory->createComposer($io, $composerFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,280 @@
|
||||||
|
<?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\IO;
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputDefinition;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
|
||||||
|
use Symfony\Component\Console\Helper\HelperSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Input/Output helper.
|
||||||
|
*
|
||||||
|
* @author François Pluchino <francois.pluchino@opendisplay.com>
|
||||||
|
*/
|
||||||
|
class ConsoleIO implements IOInterface
|
||||||
|
{
|
||||||
|
protected $input;
|
||||||
|
protected $output;
|
||||||
|
protected $helperSet;
|
||||||
|
protected $authorizations = array();
|
||||||
|
protected $lastUsername;
|
||||||
|
protected $lastPassword;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param InputInterface $input The input instance
|
||||||
|
* @param OutputInterface $output The output instance
|
||||||
|
* @param HelperSet $helperSet The helperSet instance
|
||||||
|
*/
|
||||||
|
public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
|
||||||
|
{
|
||||||
|
$this->input = $input;
|
||||||
|
$this->output = $output;
|
||||||
|
$this->helperSet = $helperSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function isInteractive()
|
||||||
|
{
|
||||||
|
return $this->input->isInteractive();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function write($messages, $newline = false, $type = 0)
|
||||||
|
{
|
||||||
|
$this->output->write($messages, $newline, $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function writeln($messages, $type = 0)
|
||||||
|
{
|
||||||
|
$this->output->writeln($messages, $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function overwrite($messages, $size = 80, $newline = false, $type = 0)
|
||||||
|
{
|
||||||
|
for ($place = $size; $place > 0; $place--) {
|
||||||
|
$this->write("\x08");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->write($messages, false, $type);
|
||||||
|
|
||||||
|
for ($place = ($size - strlen($messages)); $place > 0; $place--) {
|
||||||
|
$this->write(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
// clean up the end line
|
||||||
|
for ($place = ($size - strlen($messages)); $place > 0; $place--) {
|
||||||
|
$this->write("\x08");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($newline) {
|
||||||
|
$this->writeln('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function overwriteln($messages, $size = 80, $type = 0)
|
||||||
|
{
|
||||||
|
$this->overwrite($messages, $size, true, $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setVerbosity($level)
|
||||||
|
{
|
||||||
|
$this->output->setVerbosity($level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getVerbosity()
|
||||||
|
{
|
||||||
|
return $this->output->getVerbosity();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setDecorated($decorated)
|
||||||
|
{
|
||||||
|
$this->output->setDecorated($decorated);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function isDecorated()
|
||||||
|
{
|
||||||
|
return $this->output->isDecorated();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setFormatter(OutputFormatterInterface $formatter)
|
||||||
|
{
|
||||||
|
$this->output->setFormatter($formatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getFormatter()
|
||||||
|
{
|
||||||
|
return $this->output->getFormatter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function ask($question, $default = null)
|
||||||
|
{
|
||||||
|
return $this->helperSet->get('dialog')->ask($this->output, $question, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function askConfirmation($question, $default = true)
|
||||||
|
{
|
||||||
|
return $this->helperSet->get('dialog')->askConfirmation($this->output, $question, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function askAndValidate($question, $validator, $attempts = false, $default = null)
|
||||||
|
{
|
||||||
|
return $this->helperSet->get('dialog')->askAndValidate($this->output, $question, $validator, $attempts, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function askAndHideAnswer($question)
|
||||||
|
{
|
||||||
|
// for windows OS (does not hide the answer in the popup, but it never appears in the STDIN history)
|
||||||
|
if (preg_match('/^win/i', PHP_OS)) {
|
||||||
|
$vbscript = sys_get_temp_dir() . '/prompt_password.vbs';
|
||||||
|
file_put_contents($vbscript,
|
||||||
|
'wscript.echo(Inputbox("' . addslashes($question) . '","'
|
||||||
|
. addslashes($question) . '", ""))');
|
||||||
|
$command = "cscript //nologo " . escapeshellarg($vbscript);
|
||||||
|
|
||||||
|
$this->write($question);
|
||||||
|
|
||||||
|
$value = rtrim(shell_exec($command));
|
||||||
|
unlink($vbscript);
|
||||||
|
|
||||||
|
for ($i = 0; $i < strlen($value); ++$i) {
|
||||||
|
$this->write('*');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->writeln('');
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for other OS with shell_exec (hide the answer)
|
||||||
|
if (rtrim(shell_exec($command)) === 'OK') {
|
||||||
|
$command = "/usr/bin/env bash -c 'echo OK'";
|
||||||
|
|
||||||
|
$this->write($question);
|
||||||
|
|
||||||
|
$command = "/usr/bin/env bash -c 'read -s mypassword && echo \$mypassword'";
|
||||||
|
$value = rtrim(shell_exec($command));
|
||||||
|
|
||||||
|
for ($i = 0; $i < strlen($value); ++$i) {
|
||||||
|
$this->write('*');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->writeln('');
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for other OS without shell_exec (does not hide the answer)
|
||||||
|
$this->writeln('');
|
||||||
|
|
||||||
|
return $this->ask($question);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getLastUsername()
|
||||||
|
{
|
||||||
|
return $this->lastUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getLastPassword()
|
||||||
|
{
|
||||||
|
return $this->lastPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getAuthorizations()
|
||||||
|
{
|
||||||
|
return $this->authorizations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function hasAuthorization($repositoryName)
|
||||||
|
{
|
||||||
|
$auths = $this->getAuthorizations();
|
||||||
|
return isset($auths[$repositoryName]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getAuthorization($repositoryName)
|
||||||
|
{
|
||||||
|
$auths = $this->getAuthorizations();
|
||||||
|
return isset($auths[$repositoryName]) ? $auths[$repositoryName] : array('username' => null, 'password' => null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function setAuthorization($repositoryName, $username, $password = null)
|
||||||
|
{
|
||||||
|
$auths = $this->getAuthorizations();
|
||||||
|
$auths[$repositoryName] = array('username' => $username, 'password' => $password);
|
||||||
|
|
||||||
|
$this->authorizations = $auths;
|
||||||
|
$this->lastUsername = $username;
|
||||||
|
$this->lastPassword = $password;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
<?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\IO;
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Helper\HelperSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Input/Output helper interface.
|
||||||
|
*
|
||||||
|
* @author François Pluchino <francois.pluchino@opendisplay.com>
|
||||||
|
*/
|
||||||
|
interface IOInterface extends OutputInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Is this input means interactive?
|
||||||
|
*
|
||||||
|
* @return Boolean
|
||||||
|
*/
|
||||||
|
function isInteractive();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwrites a previous message to the output.
|
||||||
|
*
|
||||||
|
* @param string|array $messages The message as an array of lines of a single string
|
||||||
|
* @param integer $size The size of line
|
||||||
|
* @param Boolean $newline Whether to add a newline or not
|
||||||
|
* @param integer $type The type of output
|
||||||
|
*/
|
||||||
|
function overwrite($messages, $size = 80, $newline = false, $type = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwrites a previous message to the output and adds a newline at the end.
|
||||||
|
*
|
||||||
|
* @param string|array $messages The message as an array of lines of a single string
|
||||||
|
* @param integer $size The size of line
|
||||||
|
* @param integer $type The type of output
|
||||||
|
*/
|
||||||
|
function overwriteln($messages, $size = 80, $type = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks a question to the user.
|
||||||
|
*
|
||||||
|
* @param string|array $question The question to ask
|
||||||
|
* @param string $default The default answer if none is given by the user
|
||||||
|
*
|
||||||
|
* @return string The user answer
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException If there is no data to read in the input stream
|
||||||
|
*/
|
||||||
|
function ask($question, $default = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks a confirmation to the user.
|
||||||
|
*
|
||||||
|
* The question will be asked until the user answers by nothing, yes, or no.
|
||||||
|
*
|
||||||
|
* @param string|array $question The question to ask
|
||||||
|
* @param Boolean $default The default answer if the user enters nothing
|
||||||
|
*
|
||||||
|
* @return Boolean true if the user has confirmed, false otherwise
|
||||||
|
*/
|
||||||
|
function askConfirmation($question, $default = true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks for a value and validates the response.
|
||||||
|
*
|
||||||
|
* The validator receives the data to validate. It must return the
|
||||||
|
* validated data when the data is valid and throw an exception
|
||||||
|
* otherwise.
|
||||||
|
*
|
||||||
|
* @param string|array $question The question to ask
|
||||||
|
* @param callback $validator A PHP callback
|
||||||
|
* @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite)
|
||||||
|
* @param string $default The default answer if none is given by the user
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*
|
||||||
|
* @throws \Exception When any of the validators return an error
|
||||||
|
*/
|
||||||
|
function askAndValidate($question, $validator, $attempts = false, $default = null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks a question to the user and hide the answer.
|
||||||
|
*
|
||||||
|
* @param string $question The question to ask
|
||||||
|
*
|
||||||
|
* @return string The answer
|
||||||
|
*/
|
||||||
|
function askAndHideAnswer($question);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last username entered.
|
||||||
|
*
|
||||||
|
* @return string The username
|
||||||
|
*/
|
||||||
|
function getLastUsername();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last password entered.
|
||||||
|
*
|
||||||
|
* @return string The password
|
||||||
|
*/
|
||||||
|
function getLastPassword();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all authorization informations entered.
|
||||||
|
*
|
||||||
|
* @return array The map of authorization
|
||||||
|
*/
|
||||||
|
function getAuthorizations();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify if the repository has a authorization informations.
|
||||||
|
*
|
||||||
|
* @param string $repositoryName The unique name of repository
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
function hasAuthorization($repositoryName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the username and password of repository.
|
||||||
|
*
|
||||||
|
* @param string $repositoryName The unique name of repository
|
||||||
|
*
|
||||||
|
* @return array The 'username' and 'password'
|
||||||
|
*/
|
||||||
|
function getAuthorization($repositoryName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the authorization informations for the repository.
|
||||||
|
*
|
||||||
|
* @param string $repositoryName The unique name of repository
|
||||||
|
* @param string $username The username
|
||||||
|
* @param string $password The password
|
||||||
|
*/
|
||||||
|
function setAuthorization($repositoryName, $username, $password = null);
|
||||||
|
}
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
namespace Composer\Installer;
|
namespace Composer\Installer;
|
||||||
|
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Autoload\AutoloadGenerator;
|
use Composer\Autoload\AutoloadGenerator;
|
||||||
use Composer\Downloader\DownloadManager;
|
use Composer\Downloader\DownloadManager;
|
||||||
use Composer\Repository\WritableRepositoryInterface;
|
use Composer\Repository\WritableRepositoryInterface;
|
||||||
|
@ -33,10 +34,11 @@ class InstallerInstaller extends LibraryInstaller
|
||||||
* @param string $binDir relative path for binaries
|
* @param string $binDir relative path for binaries
|
||||||
* @param DownloadManager $dm download manager
|
* @param DownloadManager $dm download manager
|
||||||
* @param WritableRepositoryInterface $repository repository controller
|
* @param WritableRepositoryInterface $repository repository controller
|
||||||
|
* @param IOInterface $io io instance
|
||||||
*/
|
*/
|
||||||
public function __construct($vendorDir, $binDir, DownloadManager $dm, WritableRepositoryInterface $repository, InstallationManager $im)
|
public function __construct($vendorDir, $binDir, DownloadManager $dm, WritableRepositoryInterface $repository, IOInterface $io, InstallationManager $im)
|
||||||
{
|
{
|
||||||
parent::__construct($vendorDir, $binDir, $dm, $repository, 'composer-installer');
|
parent::__construct($vendorDir, $binDir, $dm, $repository, $io, 'composer-installer');
|
||||||
$this->installationManager = $im;
|
$this->installationManager = $im;
|
||||||
|
|
||||||
foreach ($repository->getPackages() as $package) {
|
foreach ($repository->getPackages() as $package) {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
namespace Composer\Installer;
|
namespace Composer\Installer;
|
||||||
|
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
use Composer\Downloader\DownloadManager;
|
use Composer\Downloader\DownloadManager;
|
||||||
use Composer\Repository\WritableRepositoryInterface;
|
use Composer\Repository\WritableRepositoryInterface;
|
||||||
use Composer\DependencyResolver\Operation\OperationInterface;
|
use Composer\DependencyResolver\Operation\OperationInterface;
|
||||||
|
@ -30,6 +31,7 @@ class LibraryInstaller implements InstallerInterface
|
||||||
protected $binDir;
|
protected $binDir;
|
||||||
protected $downloadManager;
|
protected $downloadManager;
|
||||||
protected $repository;
|
protected $repository;
|
||||||
|
protected $io;
|
||||||
private $type;
|
private $type;
|
||||||
private $filesystem;
|
private $filesystem;
|
||||||
|
|
||||||
|
@ -40,12 +42,14 @@ class LibraryInstaller implements InstallerInterface
|
||||||
* @param string $binDir relative path for binaries
|
* @param string $binDir relative path for binaries
|
||||||
* @param DownloadManager $dm download manager
|
* @param DownloadManager $dm download manager
|
||||||
* @param WritableRepositoryInterface $repository repository controller
|
* @param WritableRepositoryInterface $repository repository controller
|
||||||
|
* @param IOInterface $io io instance
|
||||||
* @param string $type package type that this installer handles
|
* @param string $type package type that this installer handles
|
||||||
*/
|
*/
|
||||||
public function __construct($vendorDir, $binDir, DownloadManager $dm, WritableRepositoryInterface $repository, $type = 'library')
|
public function __construct($vendorDir, $binDir, DownloadManager $dm, WritableRepositoryInterface $repository, IOInterface $io, $type = 'library')
|
||||||
{
|
{
|
||||||
$this->downloadManager = $dm;
|
$this->downloadManager = $dm;
|
||||||
$this->repository = $repository;
|
$this->repository = $repository;
|
||||||
|
$this->io = $io;
|
||||||
$this->type = $type;
|
$this->type = $type;
|
||||||
|
|
||||||
$this->filesystem = new Filesystem();
|
$this->filesystem = new Filesystem();
|
||||||
|
@ -136,7 +140,7 @@ class LibraryInstaller implements InstallerInterface
|
||||||
foreach ($package->getBinaries() as $bin) {
|
foreach ($package->getBinaries() as $bin) {
|
||||||
$link = $this->binDir.'/'.basename($bin);
|
$link = $this->binDir.'/'.basename($bin);
|
||||||
if (file_exists($link)) {
|
if (file_exists($link)) {
|
||||||
echo 'Skipped installation of '.$bin.' for package '.$package->getName().', name conflicts with an existing file'.PHP_EOL;
|
$this->io->writeln('Skipped installation of '.$bin.' for package '.$package->getName().', name conflicts with an existing file');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$bin = $this->getInstallPath($package).'/'.$bin;
|
$bin = $this->getInstallPath($package).'/'.$bin;
|
||||||
|
|
|
@ -12,17 +12,26 @@
|
||||||
|
|
||||||
namespace Composer\Repository;
|
namespace Composer\Repository;
|
||||||
|
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repositories manager.
|
* Repositories manager.
|
||||||
*
|
*
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||||
|
* @author François Pluchino <francois.pluchino@opendisplay.com>
|
||||||
*/
|
*/
|
||||||
class RepositoryManager
|
class RepositoryManager
|
||||||
{
|
{
|
||||||
private $localRepository;
|
private $localRepository;
|
||||||
private $repositories = array();
|
private $repositories = array();
|
||||||
private $repositoryClasses = array();
|
private $repositoryClasses = array();
|
||||||
|
private $io;
|
||||||
|
|
||||||
|
public function __construct(IOInterface $io)
|
||||||
|
{
|
||||||
|
$this->io = $io;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for a package by it's name and version in managed repositories.
|
* Searches for a package by it's name and version in managed repositories.
|
||||||
|
@ -66,7 +75,7 @@ class RepositoryManager
|
||||||
}
|
}
|
||||||
|
|
||||||
$class = $this->repositoryClasses[$type];
|
$class = $this->repositoryClasses[$type];
|
||||||
return new $class($config);
|
return new $class($config, $this->io);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
namespace Composer\Repository\Vcs;
|
namespace Composer\Repository\Vcs;
|
||||||
|
|
||||||
use Composer\Json\JsonFile;
|
use Composer\Json\JsonFile;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Per Bernhardt <plb@webfactory.de>
|
* @author Per Bernhardt <plb@webfactory.de>
|
||||||
*/
|
*/
|
||||||
class GitBitbucketDriver implements VcsDriverInterface
|
class GitBitbucketDriver extends VcsDriver implements VcsDriverInterface
|
||||||
{
|
{
|
||||||
protected $url;
|
|
||||||
protected $owner;
|
protected $owner;
|
||||||
protected $repository;
|
protected $repository;
|
||||||
protected $tags;
|
protected $tags;
|
||||||
|
@ -27,12 +27,13 @@ class GitBitbucketDriver implements VcsDriverInterface
|
||||||
protected $rootIdentifier;
|
protected $rootIdentifier;
|
||||||
protected $infoCache = array();
|
protected $infoCache = array();
|
||||||
|
|
||||||
public function __construct($url)
|
public function __construct($url, IOInterface $io)
|
||||||
{
|
{
|
||||||
$this->url = $url;
|
|
||||||
preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url, $match);
|
preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url, $match);
|
||||||
$this->owner = $match[1];
|
$this->owner = $match[1];
|
||||||
$this->repository = $match[2];
|
$this->repository = $match[2];
|
||||||
|
|
||||||
|
parent::__construct($url, $io);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +49,7 @@ class GitBitbucketDriver implements VcsDriverInterface
|
||||||
public function getRootIdentifier()
|
public function getRootIdentifier()
|
||||||
{
|
{
|
||||||
if (null === $this->rootIdentifier) {
|
if (null === $this->rootIdentifier) {
|
||||||
$repoData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository), true);
|
$repoData = json_decode($this->getContents($this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository), true);
|
||||||
$this->rootIdentifier = !empty($repoData['main_branch']) ? $repoData['main_branch'] : 'master';
|
$this->rootIdentifier = !empty($repoData['main_branch']) ? $repoData['main_branch'] : 'master';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ class GitBitbucketDriver implements VcsDriverInterface
|
||||||
public function getDist($identifier)
|
public function getDist($identifier)
|
||||||
{
|
{
|
||||||
$label = array_search($identifier, $this->getTags()) ?: $identifier;
|
$label = array_search($identifier, $this->getTags()) ?: $identifier;
|
||||||
$url = 'https://bitbucket.org/'.$this->owner.'/'.$this->repository.'/get/'.$label.'.zip';
|
$url = $this->getScheme() . '://bitbucket.org/'.$this->owner.'/'.$this->repository.'/get/'.$label.'.zip';
|
||||||
|
|
||||||
return array('type' => 'zip', 'url' => $url, 'reference' => $label, 'shasum' => '');
|
return array('type' => 'zip', 'url' => $url, 'reference' => $label, 'shasum' => '');
|
||||||
}
|
}
|
||||||
|
@ -90,7 +91,7 @@ class GitBitbucketDriver implements VcsDriverInterface
|
||||||
public function getComposerInformation($identifier)
|
public function getComposerInformation($identifier)
|
||||||
{
|
{
|
||||||
if (!isset($this->infoCache[$identifier])) {
|
if (!isset($this->infoCache[$identifier])) {
|
||||||
$composer = @file_get_contents('https://bitbucket.org/'.$this->owner.'/'.$this->repository.'/raw/'.$identifier.'/composer.json');
|
$composer = $this->getContents($this->getScheme() . '://bitbucket.org/'.$this->owner.'/'.$this->repository.'/raw/'.$identifier.'/composer.json');
|
||||||
if (!$composer) {
|
if (!$composer) {
|
||||||
throw new \UnexpectedValueException('Failed to retrieve composer information for identifier '.$identifier.' in '.$this->getUrl());
|
throw new \UnexpectedValueException('Failed to retrieve composer information for identifier '.$identifier.' in '.$this->getUrl());
|
||||||
}
|
}
|
||||||
|
@ -98,7 +99,7 @@ class GitBitbucketDriver implements VcsDriverInterface
|
||||||
$composer = JsonFile::parseJson($composer);
|
$composer = JsonFile::parseJson($composer);
|
||||||
|
|
||||||
if (!isset($composer['time'])) {
|
if (!isset($composer['time'])) {
|
||||||
$changeset = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier), true);
|
$changeset = json_decode($this->getContents($this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier), true);
|
||||||
$composer['time'] = $changeset['timestamp'];
|
$composer['time'] = $changeset['timestamp'];
|
||||||
}
|
}
|
||||||
$this->infoCache[$identifier] = $composer;
|
$this->infoCache[$identifier] = $composer;
|
||||||
|
@ -113,7 +114,7 @@ class GitBitbucketDriver implements VcsDriverInterface
|
||||||
public function getTags()
|
public function getTags()
|
||||||
{
|
{
|
||||||
if (null === $this->tags) {
|
if (null === $this->tags) {
|
||||||
$tagsData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'), true);
|
$tagsData = json_decode($this->getContents($this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'), true);
|
||||||
$this->tags = array();
|
$this->tags = array();
|
||||||
foreach ($tagsData as $tag => $data) {
|
foreach ($tagsData as $tag => $data) {
|
||||||
$this->tags[$tag] = $data['raw_node'];
|
$this->tags[$tag] = $data['raw_node'];
|
||||||
|
@ -129,7 +130,7 @@ class GitBitbucketDriver implements VcsDriverInterface
|
||||||
public function getBranches()
|
public function getBranches()
|
||||||
{
|
{
|
||||||
if (null === $this->branches) {
|
if (null === $this->branches) {
|
||||||
$branchData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches'), true);
|
$branchData = json_decode($this->getContents($this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches'), true);
|
||||||
$this->branches = array();
|
$this->branches = array();
|
||||||
foreach ($branchData as $branch => $data) {
|
foreach ($branchData as $branch => $data) {
|
||||||
$this->branches[$branch] = $data['raw_node'];
|
$this->branches[$branch] = $data['raw_node'];
|
||||||
|
|
|
@ -4,22 +4,23 @@ namespace Composer\Repository\Vcs;
|
||||||
|
|
||||||
use Composer\Json\JsonFile;
|
use Composer\Json\JsonFile;
|
||||||
use Composer\Util\Process;
|
use Composer\Util\Process;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class GitDriver implements VcsDriverInterface
|
class GitDriver extends VcsDriver implements VcsDriverInterface
|
||||||
{
|
{
|
||||||
protected $url;
|
|
||||||
protected $tags;
|
protected $tags;
|
||||||
protected $branches;
|
protected $branches;
|
||||||
protected $rootIdentifier;
|
protected $rootIdentifier;
|
||||||
protected $infoCache = array();
|
protected $infoCache = array();
|
||||||
|
|
||||||
public function __construct($url)
|
public function __construct($url, IOInterface $io)
|
||||||
{
|
{
|
||||||
$this->url = $url;
|
|
||||||
$this->tmpDir = sys_get_temp_dir() . '/composer-' . preg_replace('{[^a-z0-9]}i', '-', $url) . '/';
|
$this->tmpDir = sys_get_temp_dir() . '/composer-' . preg_replace('{[^a-z0-9]}i', '-', $url) . '/';
|
||||||
|
|
||||||
|
parent::__construct($url, $io);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
namespace Composer\Repository\Vcs;
|
namespace Composer\Repository\Vcs;
|
||||||
|
|
||||||
use Composer\Json\JsonFile;
|
use Composer\Json\JsonFile;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class GitHubDriver implements VcsDriverInterface
|
class GitHubDriver extends VcsDriver implements VcsDriverInterface
|
||||||
{
|
{
|
||||||
protected $owner;
|
protected $owner;
|
||||||
protected $repository;
|
protected $repository;
|
||||||
|
@ -16,11 +17,13 @@ class GitHubDriver implements VcsDriverInterface
|
||||||
protected $rootIdentifier;
|
protected $rootIdentifier;
|
||||||
protected $infoCache = array();
|
protected $infoCache = array();
|
||||||
|
|
||||||
public function __construct($url)
|
public function __construct($url, IOInterface $io)
|
||||||
{
|
{
|
||||||
preg_match('#^(?:https?|git)://github\.com/([^/]+)/(.+?)(?:\.git)?$#', $url, $match);
|
preg_match('#^(?:https?|git)://github\.com/([^/]+)/(.+?)(?:\.git)?$#', $url, $match);
|
||||||
$this->owner = $match[1];
|
$this->owner = $match[1];
|
||||||
$this->repository = $match[2];
|
$this->repository = $match[2];
|
||||||
|
|
||||||
|
parent::__construct($url, $io);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,7 +39,7 @@ class GitHubDriver implements VcsDriverInterface
|
||||||
public function getRootIdentifier()
|
public function getRootIdentifier()
|
||||||
{
|
{
|
||||||
if (null === $this->rootIdentifier) {
|
if (null === $this->rootIdentifier) {
|
||||||
$repoData = json_decode(file_get_contents('https://api.github.com/repos/'.$this->owner.'/'.$this->repository), true);
|
$repoData = json_decode($this->getContents($this->getScheme() . '://api.github.com/repos/'.$this->owner.'/'.$this->repository), true);
|
||||||
$this->rootIdentifier = $repoData['master_branch'] ?: 'master';
|
$this->rootIdentifier = $repoData['master_branch'] ?: 'master';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +51,7 @@ class GitHubDriver implements VcsDriverInterface
|
||||||
*/
|
*/
|
||||||
public function getUrl()
|
public function getUrl()
|
||||||
{
|
{
|
||||||
return 'http://github.com/'.$this->owner.'/'.$this->repository.'.git';
|
return $this->url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,7 +70,7 @@ class GitHubDriver implements VcsDriverInterface
|
||||||
public function getDist($identifier)
|
public function getDist($identifier)
|
||||||
{
|
{
|
||||||
$label = array_search($identifier, $this->getTags()) ?: $identifier;
|
$label = array_search($identifier, $this->getTags()) ?: $identifier;
|
||||||
$url = 'http://github.com/'.$this->owner.'/'.$this->repository.'/zipball/'.$label;
|
$url = $this->getScheme() . '://github.com/'.$this->owner.'/'.$this->repository.'/zipball/'.$label;
|
||||||
|
|
||||||
return array('type' => 'zip', 'url' => $url, 'reference' => $label, 'shasum' => '');
|
return array('type' => 'zip', 'url' => $url, 'reference' => $label, 'shasum' => '');
|
||||||
}
|
}
|
||||||
|
@ -78,7 +81,7 @@ class GitHubDriver implements VcsDriverInterface
|
||||||
public function getComposerInformation($identifier)
|
public function getComposerInformation($identifier)
|
||||||
{
|
{
|
||||||
if (!isset($this->infoCache[$identifier])) {
|
if (!isset($this->infoCache[$identifier])) {
|
||||||
$composer = @file_get_contents('https://raw.github.com/'.$this->owner.'/'.$this->repository.'/'.$identifier.'/composer.json');
|
$composer = $this->getContents($this->getScheme() . '://raw.github.com/'.$this->owner.'/'.$this->repository.'/'.$identifier.'/composer.json');
|
||||||
if (!$composer) {
|
if (!$composer) {
|
||||||
throw new \UnexpectedValueException('Failed to retrieve composer information for identifier '.$identifier.' in '.$this->getUrl());
|
throw new \UnexpectedValueException('Failed to retrieve composer information for identifier '.$identifier.' in '.$this->getUrl());
|
||||||
}
|
}
|
||||||
|
@ -86,7 +89,7 @@ class GitHubDriver implements VcsDriverInterface
|
||||||
$composer = JsonFile::parseJson($composer);
|
$composer = JsonFile::parseJson($composer);
|
||||||
|
|
||||||
if (!isset($composer['time'])) {
|
if (!isset($composer['time'])) {
|
||||||
$commit = json_decode(file_get_contents('https://api.github.com/repos/'.$this->owner.'/'.$this->repository.'/commits/'.$identifier), true);
|
$commit = json_decode($this->getContents($this->getScheme() . '://api.github.com/repos/'.$this->owner.'/'.$this->repository.'/commits/'.$identifier), true);
|
||||||
$composer['time'] = $commit['commit']['committer']['date'];
|
$composer['time'] = $commit['commit']['committer']['date'];
|
||||||
}
|
}
|
||||||
$this->infoCache[$identifier] = $composer;
|
$this->infoCache[$identifier] = $composer;
|
||||||
|
@ -101,7 +104,7 @@ class GitHubDriver implements VcsDriverInterface
|
||||||
public function getTags()
|
public function getTags()
|
||||||
{
|
{
|
||||||
if (null === $this->tags) {
|
if (null === $this->tags) {
|
||||||
$tagsData = json_decode(file_get_contents('https://api.github.com/repos/'.$this->owner.'/'.$this->repository.'/tags'), true);
|
$tagsData = json_decode($this->getContents($this->getScheme() . '://api.github.com/repos/'.$this->owner.'/'.$this->repository.'/tags'), true);
|
||||||
$this->tags = array();
|
$this->tags = array();
|
||||||
foreach ($tagsData as $tag) {
|
foreach ($tagsData as $tag) {
|
||||||
$this->tags[$tag['name']] = $tag['commit']['sha'];
|
$this->tags[$tag['name']] = $tag['commit']['sha'];
|
||||||
|
@ -117,7 +120,7 @@ class GitHubDriver implements VcsDriverInterface
|
||||||
public function getBranches()
|
public function getBranches()
|
||||||
{
|
{
|
||||||
if (null === $this->branches) {
|
if (null === $this->branches) {
|
||||||
$branchData = json_decode(file_get_contents('https://api.github.com/repos/'.$this->owner.'/'.$this->repository.'/branches'), true);
|
$branchData = json_decode($this->getContents($this->getScheme() . '://api.github.com/repos/'.$this->owner.'/'.$this->repository.'/branches'), true);
|
||||||
$this->branches = array();
|
$this->branches = array();
|
||||||
foreach ($branchData as $branch) {
|
foreach ($branchData as $branch) {
|
||||||
$this->branches[$branch['name']] = $branch['commit']['sha'];
|
$this->branches[$branch['name']] = $branch['commit']['sha'];
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
namespace Composer\Repository\Vcs;
|
namespace Composer\Repository\Vcs;
|
||||||
|
|
||||||
use Composer\Json\JsonFile;
|
use Composer\Json\JsonFile;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Per Bernhardt <plb@webfactory.de>
|
* @author Per Bernhardt <plb@webfactory.de>
|
||||||
*/
|
*/
|
||||||
class HgBitbucketDriver implements VcsDriverInterface
|
class HgBitbucketDriver extends VcsDriver implements VcsDriverInterface
|
||||||
{
|
{
|
||||||
protected $url;
|
|
||||||
protected $owner;
|
protected $owner;
|
||||||
protected $repository;
|
protected $repository;
|
||||||
protected $tags;
|
protected $tags;
|
||||||
|
@ -27,12 +27,13 @@ class HgBitbucketDriver implements VcsDriverInterface
|
||||||
protected $rootIdentifier;
|
protected $rootIdentifier;
|
||||||
protected $infoCache = array();
|
protected $infoCache = array();
|
||||||
|
|
||||||
public function __construct($url)
|
public function __construct($url, IOInterface $io)
|
||||||
{
|
{
|
||||||
$this->url = $url;
|
|
||||||
preg_match('#^https://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url, $match);
|
preg_match('#^https://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url, $match);
|
||||||
$this->owner = $match[1];
|
$this->owner = $match[1];
|
||||||
$this->repository = $match[2];
|
$this->repository = $match[2];
|
||||||
|
|
||||||
|
parent::__construct($url, $io);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +49,7 @@ class HgBitbucketDriver implements VcsDriverInterface
|
||||||
public function getRootIdentifier()
|
public function getRootIdentifier()
|
||||||
{
|
{
|
||||||
if (null === $this->rootIdentifier) {
|
if (null === $this->rootIdentifier) {
|
||||||
$repoData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'), true);
|
$repoData = json_decode($this->getContents($this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'), true);
|
||||||
$this->rootIdentifier = $repoData['tip']['raw_node'];
|
$this->rootIdentifier = $repoData['tip']['raw_node'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ class HgBitbucketDriver implements VcsDriverInterface
|
||||||
public function getDist($identifier)
|
public function getDist($identifier)
|
||||||
{
|
{
|
||||||
$label = array_search($identifier, $this->getTags()) ?: $identifier;
|
$label = array_search($identifier, $this->getTags()) ?: $identifier;
|
||||||
$url = 'https://bitbucket.org/'.$this->owner.'/'.$this->repository.'/get/'.$label.'.zip';
|
$url = $this->getScheme() . '://bitbucket.org/'.$this->owner.'/'.$this->repository.'/get/'.$label.'.zip';
|
||||||
|
|
||||||
return array('type' => 'zip', 'url' => $url, 'reference' => $label, 'shasum' => '');
|
return array('type' => 'zip', 'url' => $url, 'reference' => $label, 'shasum' => '');
|
||||||
}
|
}
|
||||||
|
@ -90,7 +91,7 @@ class HgBitbucketDriver implements VcsDriverInterface
|
||||||
public function getComposerInformation($identifier)
|
public function getComposerInformation($identifier)
|
||||||
{
|
{
|
||||||
if (!isset($this->infoCache[$identifier])) {
|
if (!isset($this->infoCache[$identifier])) {
|
||||||
$composer = @file_get_contents('https://bitbucket.org/'.$this->owner.'/'.$this->repository.'/raw/'.$identifier.'/composer.json');
|
$composer = $this->getContents($this->getScheme() . '://bitbucket.org/'.$this->owner.'/'.$this->repository.'/raw/'.$identifier.'/composer.json');
|
||||||
if (!$composer) {
|
if (!$composer) {
|
||||||
throw new \UnexpectedValueException('Failed to retrieve composer information for identifier '.$identifier.' in '.$this->getUrl());
|
throw new \UnexpectedValueException('Failed to retrieve composer information for identifier '.$identifier.' in '.$this->getUrl());
|
||||||
}
|
}
|
||||||
|
@ -98,7 +99,7 @@ class HgBitbucketDriver implements VcsDriverInterface
|
||||||
$composer = JsonFile::parseJson($composer);
|
$composer = JsonFile::parseJson($composer);
|
||||||
|
|
||||||
if (!isset($composer['time'])) {
|
if (!isset($composer['time'])) {
|
||||||
$changeset = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier), true);
|
$changeset = json_decode($this->getContents($this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/changesets/'.$identifier), true);
|
||||||
$composer['time'] = $changeset['timestamp'];
|
$composer['time'] = $changeset['timestamp'];
|
||||||
}
|
}
|
||||||
$this->infoCache[$identifier] = $composer;
|
$this->infoCache[$identifier] = $composer;
|
||||||
|
@ -113,7 +114,7 @@ class HgBitbucketDriver implements VcsDriverInterface
|
||||||
public function getTags()
|
public function getTags()
|
||||||
{
|
{
|
||||||
if (null === $this->tags) {
|
if (null === $this->tags) {
|
||||||
$tagsData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'), true);
|
$tagsData = json_decode($this->getContents($this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/tags'), true);
|
||||||
$this->tags = array();
|
$this->tags = array();
|
||||||
foreach ($tagsData as $tag => $data) {
|
foreach ($tagsData as $tag => $data) {
|
||||||
$this->tags[$tag] = $data['raw_node'];
|
$this->tags[$tag] = $data['raw_node'];
|
||||||
|
@ -129,7 +130,7 @@ class HgBitbucketDriver implements VcsDriverInterface
|
||||||
public function getBranches()
|
public function getBranches()
|
||||||
{
|
{
|
||||||
if (null === $this->branches) {
|
if (null === $this->branches) {
|
||||||
$branchData = json_decode(file_get_contents('https://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches'), true);
|
$branchData = json_decode($this->getContents($this->getScheme() . '://api.bitbucket.org/1.0/repositories/'.$this->owner.'/'.$this->repository.'/branches'), true);
|
||||||
$this->branches = array();
|
$this->branches = array();
|
||||||
foreach ($branchData as $branch => $data) {
|
foreach ($branchData as $branch => $data) {
|
||||||
$this->branches[$branch] = $data['raw_node'];
|
$this->branches[$branch] = $data['raw_node'];
|
||||||
|
|
|
@ -14,22 +14,23 @@ namespace Composer\Repository\Vcs;
|
||||||
|
|
||||||
use Composer\Json\JsonFile;
|
use Composer\Json\JsonFile;
|
||||||
use Composer\Util\Process;
|
use Composer\Util\Process;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Per Bernhardt <plb@webfactory.de>
|
* @author Per Bernhardt <plb@webfactory.de>
|
||||||
*/
|
*/
|
||||||
class HgDriver implements VcsDriverInterface
|
class HgDriver extends VcsDriver implements VcsDriverInterface
|
||||||
{
|
{
|
||||||
protected $url;
|
|
||||||
protected $tags;
|
protected $tags;
|
||||||
protected $branches;
|
protected $branches;
|
||||||
protected $rootIdentifier;
|
protected $rootIdentifier;
|
||||||
protected $infoCache = array();
|
protected $infoCache = array();
|
||||||
|
|
||||||
public function __construct($url)
|
public function __construct($url, IOInterface $io)
|
||||||
{
|
{
|
||||||
$this->url = $url;
|
|
||||||
$this->tmpDir = sys_get_temp_dir() . '/composer-' . preg_replace('{[^a-z0-9]}i', '-', $url) . '/';
|
$this->tmpDir = sys_get_temp_dir() . '/composer-' . preg_replace('{[^a-z0-9]}i', '-', $url) . '/';
|
||||||
|
|
||||||
|
parent::__construct($url, $io);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,21 +4,22 @@ namespace Composer\Repository\Vcs;
|
||||||
|
|
||||||
use Composer\Json\JsonFile;
|
use Composer\Json\JsonFile;
|
||||||
use Composer\Util\Process;
|
use Composer\Util\Process;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class SvnDriver implements VcsDriverInterface
|
class SvnDriver extends VcsDriver implements VcsDriverInterface
|
||||||
{
|
{
|
||||||
protected $url;
|
|
||||||
protected $baseUrl;
|
protected $baseUrl;
|
||||||
protected $tags;
|
protected $tags;
|
||||||
protected $branches;
|
protected $branches;
|
||||||
protected $infoCache = array();
|
protected $infoCache = array();
|
||||||
|
|
||||||
public function __construct($url)
|
public function __construct($url, IOInterface $io)
|
||||||
{
|
{
|
||||||
$this->url = $this->baseUrl = rtrim($url, '/');
|
parent::__construct($this->baseUrl = rtrim($url, '/'), $io);
|
||||||
|
|
||||||
if (false !== ($pos = strrpos($url, '/trunk'))) {
|
if (false !== ($pos = strrpos($url, '/trunk'))) {
|
||||||
$this->baseUrl = substr($url, 0, $pos);
|
$this->baseUrl = substr($url, 0, $pos);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
<?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\Vcs;
|
||||||
|
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A driver implementation for driver with authorization interaction.
|
||||||
|
*
|
||||||
|
* @author François Pluchino <francois.pluchino@opendisplay.com>
|
||||||
|
*/
|
||||||
|
abstract class VcsDriver
|
||||||
|
{
|
||||||
|
protected $url;
|
||||||
|
protected $io;
|
||||||
|
private $firstCall;
|
||||||
|
private $contentUrl;
|
||||||
|
private $content;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param string $url The URL
|
||||||
|
* @param IOInterface $io The IO instance
|
||||||
|
*/
|
||||||
|
public function __construct($url, IOInterface $io)
|
||||||
|
{
|
||||||
|
$this->url = $url;
|
||||||
|
$this->io = $io;
|
||||||
|
$this->firstCall = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the https or http protocol.
|
||||||
|
*
|
||||||
|
* @return string The correct type of protocol
|
||||||
|
*/
|
||||||
|
protected function getScheme()
|
||||||
|
{
|
||||||
|
if (extension_loaded('openssl')) {
|
||||||
|
return 'https';
|
||||||
|
}
|
||||||
|
return 'http';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the remote content.
|
||||||
|
*
|
||||||
|
* @param string $url The URL of content
|
||||||
|
*
|
||||||
|
* @return mixed The result
|
||||||
|
*/
|
||||||
|
protected function getContents($url)
|
||||||
|
{
|
||||||
|
$this->contentUrl = $url;
|
||||||
|
$auth = $this->io->getAuthorization($this->url);
|
||||||
|
$params = array();
|
||||||
|
|
||||||
|
// add authorization to curl options
|
||||||
|
if ($this->io->hasAuthorization($this->url)) {
|
||||||
|
$authStr = base64_encode($auth['username'] . ':' . $auth['password']);
|
||||||
|
$params['http'] = array('header' => "Authorization: Basic $authStr\r\n");
|
||||||
|
|
||||||
|
} else if (null !== $this->io->getLastUsername()) {
|
||||||
|
$authStr = base64_encode($this->io->getLastUsername() . ':' . $this->io->getLastPassword());
|
||||||
|
$params['http'] = array('header' => "Authorization: Basic $authStr\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
$ctx = stream_context_create($params);
|
||||||
|
stream_context_set_params($ctx, array("notification" => array($this, 'callbackGet')));
|
||||||
|
|
||||||
|
$content = @file_get_contents($url, false, $ctx);
|
||||||
|
|
||||||
|
// content get after authorization
|
||||||
|
if (false === $content) {
|
||||||
|
$content = $this->content;
|
||||||
|
$this->content = null;
|
||||||
|
$this->contentUrl = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get notification action.
|
||||||
|
*
|
||||||
|
* @param integer $notificationCode The notification code
|
||||||
|
* @param integer $severity The severity level
|
||||||
|
* @param string $message The message
|
||||||
|
* @param integer $messageCode The message code
|
||||||
|
* @param integer $bytesTransferred The loaded size
|
||||||
|
* @param integer $bytesMax The total size
|
||||||
|
*/
|
||||||
|
protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
|
||||||
|
{
|
||||||
|
switch ($notificationCode) {
|
||||||
|
case STREAM_NOTIFY_AUTH_REQUIRED:
|
||||||
|
case STREAM_NOTIFY_FAILURE:
|
||||||
|
// for private repository returning 404 error when the authorization is incorrect
|
||||||
|
$auth = $this->io->getAuthorization($this->url);
|
||||||
|
$ps = $this->firstCall && 404 === $messageCode
|
||||||
|
&& null === $this->io->getLastUsername()
|
||||||
|
&& null === $auth['username'];
|
||||||
|
|
||||||
|
if (404 === $messageCode && !$this->firstCall) {
|
||||||
|
throw new \RuntimeException("The '" . $this->contentUrl . "' URL not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->firstCall) {
|
||||||
|
$this->firstCall = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get authorization informations
|
||||||
|
if (401 === $messageCode || $ps) {
|
||||||
|
if (!$this->io->isInteractive()) {
|
||||||
|
$mess = "The '" . $this->contentUrl . "' URL not found";
|
||||||
|
|
||||||
|
if (401 === $code || $ps) {
|
||||||
|
$mess = "The '" . $this->contentUrl . "' URL required the authorization.\nYou must be used the interactive console";
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \RuntimeException($mess);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->io->writeln("Authorization for <info>" . $this->contentUrl . "</info>:");
|
||||||
|
$username = $this->io->ask(' Username: ');
|
||||||
|
$password = $this->io->askAndHideAnswer(' Password: ');
|
||||||
|
$this->io->setAuthorization($this->url, $username, $password);
|
||||||
|
|
||||||
|
$this->content = $this->getContents($this->contentUrl);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ namespace Composer\Repository;
|
||||||
use Composer\Repository\Vcs\VcsDriverInterface;
|
use Composer\Repository\Vcs\VcsDriverInterface;
|
||||||
use Composer\Package\Version\VersionParser;
|
use Composer\Package\Version\VersionParser;
|
||||||
use Composer\Package\Loader\ArrayLoader;
|
use Composer\Package\Loader\ArrayLoader;
|
||||||
|
use Composer\IO\IOInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
@ -14,8 +15,9 @@ class VcsRepository extends ArrayRepository
|
||||||
protected $url;
|
protected $url;
|
||||||
protected $packageName;
|
protected $packageName;
|
||||||
protected $debug;
|
protected $debug;
|
||||||
|
protected $io;
|
||||||
|
|
||||||
public function __construct(array $config, array $drivers = null)
|
public function __construct(array $config, IOInterface $io, array $drivers = null)
|
||||||
{
|
{
|
||||||
if (!filter_var($config['url'], FILTER_VALIDATE_URL)) {
|
if (!filter_var($config['url'], FILTER_VALIDATE_URL)) {
|
||||||
throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$config['url']);
|
throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$config['url']);
|
||||||
|
@ -31,6 +33,7 @@ class VcsRepository extends ArrayRepository
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->url = $config['url'];
|
$this->url = $config['url'];
|
||||||
|
$this->io = $io;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setDebug($debug)
|
public function setDebug($debug)
|
||||||
|
@ -42,7 +45,7 @@ class VcsRepository extends ArrayRepository
|
||||||
{
|
{
|
||||||
foreach ($this->drivers as $driver) {
|
foreach ($this->drivers as $driver) {
|
||||||
if ($driver::supports($this->url)) {
|
if ($driver::supports($this->url)) {
|
||||||
$driver = new $driver($this->url);
|
$driver = new $driver($this->url, $this->io);
|
||||||
$driver->initialize();
|
$driver->initialize();
|
||||||
return $driver;
|
return $driver;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +53,7 @@ class VcsRepository extends ArrayRepository
|
||||||
|
|
||||||
foreach ($this->drivers as $driver) {
|
foreach ($this->drivers as $driver) {
|
||||||
if ($driver::supports($this->url, true)) {
|
if ($driver::supports($this->url, true)) {
|
||||||
$driver = new $driver($this->url);
|
$driver = new $driver($this->url, $this->io);
|
||||||
$driver->initialize();
|
$driver->initialize();
|
||||||
return $driver;
|
return $driver;
|
||||||
}
|
}
|
||||||
|
@ -77,6 +80,7 @@ class VcsRepository extends ArrayRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($driver->getTags() as $tag => $identifier) {
|
foreach ($driver->getTags() as $tag => $identifier) {
|
||||||
|
$this->io->overwrite('Get composer of <info>' . $this->packageName . '</info> (<comment>' . $tag . '</comment>)');
|
||||||
$parsedTag = $this->validateTag($versionParser, $tag);
|
$parsedTag = $this->validateTag($versionParser, $tag);
|
||||||
if ($parsedTag && $driver->hasComposerFile($identifier)) {
|
if ($parsedTag && $driver->hasComposerFile($identifier)) {
|
||||||
try {
|
try {
|
||||||
|
@ -84,7 +88,7 @@ class VcsRepository extends ArrayRepository
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
if (strpos($e->getMessage(), 'JSON Parse Error') !== false) {
|
if (strpos($e->getMessage(), 'JSON Parse Error') !== false) {
|
||||||
if ($debug) {
|
if ($debug) {
|
||||||
echo 'Skipped tag '.$tag.', '.$e->getMessage().PHP_EOL;
|
$this->io->writeln('Skipped tag '.$tag.', '.$e->getMessage());
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
@ -108,22 +112,25 @@ class VcsRepository extends ArrayRepository
|
||||||
// broken package, version doesn't match tag
|
// broken package, version doesn't match tag
|
||||||
if ($data['version_normalized'] !== $parsedTag) {
|
if ($data['version_normalized'] !== $parsedTag) {
|
||||||
if ($debug) {
|
if ($debug) {
|
||||||
echo 'Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json'.PHP_EOL;
|
$this->io->writeln('Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json');
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($debug) {
|
if ($debug) {
|
||||||
echo 'Importing tag '.$tag.' ('.$data['version_normalized'].')'.PHP_EOL;
|
$this->io->writeln('Importing tag '.$tag.' ('.$data['version_normalized'].')');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->addPackage($loader->load($this->preProcess($driver, $data, $identifier)));
|
$this->addPackage($loader->load($this->preProcess($driver, $data, $identifier)));
|
||||||
} elseif ($debug) {
|
} elseif ($debug) {
|
||||||
echo 'Skipped tag '.$tag.', '.($parsedTag ? 'no composer file was found' : 'invalid name').PHP_EOL;
|
$this->io->writeln('Skipped tag '.$tag.', '.($parsedTag ? 'no composer file was found' : 'invalid name'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->io->overwrite('');
|
||||||
|
|
||||||
foreach ($driver->getBranches() as $branch => $identifier) {
|
foreach ($driver->getBranches() as $branch => $identifier) {
|
||||||
|
$this->io->overwrite('Get composer of <info>' . $this->packageName . '</info> (<comment>' . $branch . '</comment>)');
|
||||||
$parsedBranch = $this->validateBranch($versionParser, $branch);
|
$parsedBranch = $this->validateBranch($versionParser, $branch);
|
||||||
if ($driver->hasComposerFile($identifier)) {
|
if ($driver->hasComposerFile($identifier)) {
|
||||||
$data = $driver->getComposerInformation($identifier);
|
$data = $driver->getComposerInformation($identifier);
|
||||||
|
@ -137,7 +144,7 @@ class VcsRepository extends ArrayRepository
|
||||||
$data['version_normalized'] = $parsedBranch;
|
$data['version_normalized'] = $parsedBranch;
|
||||||
} else {
|
} else {
|
||||||
if ($debug) {
|
if ($debug) {
|
||||||
echo 'Skipped branch '.$branch.', invalid name and no composer file was found'.PHP_EOL;
|
$this->io->writeln('Skipped branch '.$branch.', invalid name and no composer file was found');
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +158,7 @@ class VcsRepository extends ArrayRepository
|
||||||
foreach ($this->getPackages() as $package) {
|
foreach ($this->getPackages() as $package) {
|
||||||
if ($normalizedStableVersion === $package->getVersion()) {
|
if ($normalizedStableVersion === $package->getVersion()) {
|
||||||
if ($debug) {
|
if ($debug) {
|
||||||
echo 'Skipped branch '.$branch.', already tagged'.PHP_EOL;
|
$this->io->writeln('Skipped branch '.$branch.', already tagged');
|
||||||
}
|
}
|
||||||
|
|
||||||
continue 2;
|
continue 2;
|
||||||
|
@ -159,14 +166,16 @@ class VcsRepository extends ArrayRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($debug) {
|
if ($debug) {
|
||||||
echo 'Importing branch '.$branch.' ('.$data['version_normalized'].')'.PHP_EOL;
|
$this->io->writeln('Importing branch '.$branch.' ('.$data['version_normalized'].')');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->addPackage($loader->load($this->preProcess($driver, $data, $identifier)));
|
$this->addPackage($loader->load($this->preProcess($driver, $data, $identifier)));
|
||||||
} elseif ($debug) {
|
} elseif ($debug) {
|
||||||
echo 'Skipped branch '.$branch.', no composer file was found'.PHP_EOL;
|
$this->io->writeln('Skipped branch '.$branch.', no composer file was found');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->io->overwrite('');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function preProcess(VcsDriverInterface $driver, array $data, $identifier)
|
private function preProcess(VcsDriverInterface $driver, array $data, $identifier)
|
||||||
|
|
Loading…
Reference in New Issue