second batch of refactoring
parent
d2150a3c2e
commit
9deb10361f
|
@ -35,6 +35,22 @@ abstract class Command extends BaseCommand
|
||||||
return $this->getApplication()->getComposer();
|
return $this->getApplication()->getComposer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Composer\Package\PackageInterface
|
||||||
|
*/
|
||||||
|
protected function getPackage()
|
||||||
|
{
|
||||||
|
return $this->getApplication()->getPackage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Composer\Package\PackageLock
|
||||||
|
*/
|
||||||
|
protected function getLock()
|
||||||
|
{
|
||||||
|
return $this->getApplication()->getLock();
|
||||||
|
}
|
||||||
|
|
||||||
protected function solveDependencies(Request $request, Solver $solver)
|
protected function solveDependencies(Request $request, Solver $solver)
|
||||||
{
|
{
|
||||||
$operations = array();
|
$operations = array();
|
||||||
|
|
|
@ -1,174 +0,0 @@
|
||||||
<?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;
|
|
||||||
|
|
||||||
use Composer\Repository\RepositoryFactory;
|
|
||||||
use Composer\Package;
|
|
||||||
use Composer\Installer\LibraryInstaller;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Konstantin Kudryashiv <ever.zet@gmail.com>
|
|
||||||
*/
|
|
||||||
class ConfigurableComposer extends Composer
|
|
||||||
{
|
|
||||||
private $configFile;
|
|
||||||
private $lockFile;
|
|
||||||
private $isLocked = false;
|
|
||||||
private $lockedPackages = array();
|
|
||||||
private $repositoryFactory;
|
|
||||||
|
|
||||||
public function __construct($configFile = 'composer.json', $lockFile = 'composer.lock',
|
|
||||||
RepositoryFactory $repositoryFactory)
|
|
||||||
{
|
|
||||||
$this->configFile = $configFile;
|
|
||||||
$this->lockFile = $lockFile;
|
|
||||||
$this->repositoryFactory = $repositoryFactory;
|
|
||||||
|
|
||||||
$this->setRepository('Platform', $repositoryFactory->create('platform'));
|
|
||||||
|
|
||||||
if (!file_exists($configFile)) {
|
|
||||||
throw new \UnexpectedValueException('Can not find composer config file');
|
|
||||||
}
|
|
||||||
|
|
||||||
$config = $this->loadJsonConfig($configFile);
|
|
||||||
|
|
||||||
if (isset($config['path'])) {
|
|
||||||
$this->setInstaller('library', new LibraryInstaller($config['path']));
|
|
||||||
} else {
|
|
||||||
$this->setInstaller('library', new LibraryInstaller());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($config['repositories'])) {
|
|
||||||
$repositories = $this->loadRepositoriesFromConfig($config['repositories'])
|
|
||||||
foreach ($repositories as $name => $repository) {
|
|
||||||
$this->setRepository($name, $repository);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($config['require'])) {
|
|
||||||
$requirements = $this->loadRequirementsFromConfig($config['require']);
|
|
||||||
foreach ($requirements as $name => $constraint) {
|
|
||||||
$this->setRequirement($name, $constraint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file_exists($lockFile)) {
|
|
||||||
$lock = $this->loadJsonConfig($lockFile);
|
|
||||||
$platform = $this->getRepository('Platform');
|
|
||||||
$packages = $this->loadPackagesFromLock($lock);
|
|
||||||
foreach ($packages as $package) {
|
|
||||||
if ($this->hasRequirement($package->getName())) {
|
|
||||||
$platform->addPackage($package);
|
|
||||||
$this->lockedPackages[] = $package;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->isLocked = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isLocked()
|
|
||||||
{
|
|
||||||
return $this->isLocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLockedPackages()
|
|
||||||
{
|
|
||||||
return $this->lockedPackages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function lock(array $packages)
|
|
||||||
{
|
|
||||||
// TODO: write installed packages info into $this->lockFile
|
|
||||||
}
|
|
||||||
|
|
||||||
private function loadPackagesFromLock(array $lockList)
|
|
||||||
{
|
|
||||||
$packages = array();
|
|
||||||
foreach ($lockList as $info) {
|
|
||||||
$packages[] = new Package\MemoryPackage($info['package'], $info['version']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $packages;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function loadRepositoriesFromConfig(array $repositoriesList)
|
|
||||||
{
|
|
||||||
$repositories = array();
|
|
||||||
foreach ($repositoriesList as $name => $spec) {
|
|
||||||
if (is_array($spec) && count($spec) === 1) {
|
|
||||||
$repositories[$name] = $this->repositoryFactory->create(
|
|
||||||
key($spec), $name, current($spec)
|
|
||||||
);
|
|
||||||
} elseif (null === $spec) {
|
|
||||||
$repositories[$name] = null;
|
|
||||||
} else {
|
|
||||||
throw new \UnexpectedValueException(
|
|
||||||
'Invalid repositories specification '.
|
|
||||||
json_encode($spec).', should be: {"type": "url"}'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $repositories;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function loadRequirementsFromConfig(array $requirementsList)
|
|
||||||
{
|
|
||||||
$requirements = array();
|
|
||||||
foreach ($requirementsList as $name => $version) {
|
|
||||||
$name = strtolower($name);
|
|
||||||
if ('latest' === $version) {
|
|
||||||
$requirements[$name] = null;
|
|
||||||
} else {
|
|
||||||
preg_match('#^([>=<~]*)([\d.]+.*)$#', $version, $match);
|
|
||||||
if (!$match[1]) {
|
|
||||||
$match[1] = '=';
|
|
||||||
}
|
|
||||||
$constraint = new Package\LinkConstraint\VersionConstraint($match[1], $match[2]);
|
|
||||||
$requirements[$name] = $constraint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $requirements;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function loadJsonConfig($configFile)
|
|
||||||
{
|
|
||||||
$config = json_decode(file_get_contents($configFile), 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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,11 +13,13 @@
|
||||||
namespace Composer\Console;
|
namespace Composer\Console;
|
||||||
|
|
||||||
use Symfony\Component\Console\Application as BaseApplication;
|
use Symfony\Component\Console\Application as BaseApplication;
|
||||||
use Composer\Composer;
|
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
use Composer\Command\InstallCommand;
|
use Composer\Command\InstallCommand;
|
||||||
|
use Composer\Composer;
|
||||||
|
use Composer\Package\PackageInterface;
|
||||||
|
use Composer\Package\PackageLock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console application that handles the commands
|
* The console application that handles the commands
|
||||||
|
@ -27,12 +29,16 @@ use Composer\Command\InstallCommand;
|
||||||
class Application extends BaseApplication
|
class Application extends BaseApplication
|
||||||
{
|
{
|
||||||
private $composer;
|
private $composer;
|
||||||
|
private $package;
|
||||||
|
private $lock;
|
||||||
|
|
||||||
public function __construct(Composer $composer)
|
public function __construct(Composer $composer, PackageInterface $package, PackageLock $lock)
|
||||||
{
|
{
|
||||||
parent::__construct('Composer', Composer::VERSION);
|
parent::__construct('Composer', Composer::VERSION);
|
||||||
|
|
||||||
$this->composer = $composer;
|
$this->composer = $composer;
|
||||||
|
$this->package = $package;
|
||||||
|
$this->lock = $lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,7 +65,23 @@ class Application extends BaseApplication
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes all the composer commands
|
* @return PackageInterface
|
||||||
|
*/
|
||||||
|
public function getPackage()
|
||||||
|
{
|
||||||
|
return $this->package;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return PackageLock
|
||||||
|
*/
|
||||||
|
public function getLock()
|
||||||
|
{
|
||||||
|
return $this->lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks for all *Command files in Composer's Command directory
|
||||||
*/
|
*/
|
||||||
protected function registerCommands()
|
protected function registerCommands()
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,17 +13,15 @@
|
||||||
namespace Composer\Installer;
|
namespace Composer\Installer;
|
||||||
|
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
use Composer\Composer;
|
use Composer\Downloader\DownloaderInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||||
*/
|
*/
|
||||||
class InstallerInterface
|
interface InstallerInterface
|
||||||
{
|
{
|
||||||
function setComposer(Composer $composer);
|
function isInstalled(PackageInterface $package, DownloaderInterface $sourceDownloader = null,
|
||||||
|
DownloaderInterface $distDownloader = null);
|
||||||
function isInstalled(PackageInterface $package);
|
function install(PackageInterface $package, DownloaderInterface $sourceDownloader = null,
|
||||||
function install(PackageInterface $package);
|
DownloaderInterface $distDownloader = null);
|
||||||
function update(PackageInterface $package);
|
|
||||||
function remove(PackageInterface $package);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace Composer\Installer;
|
||||||
|
|
||||||
use Composer\Downloader\DownloaderInterface;
|
use Composer\Downloader\DownloaderInterface;
|
||||||
use Composer\Package\PackageInterface;
|
use Composer\Package\PackageInterface;
|
||||||
use Composer\Composer;
|
use Composer\Downloader\DownloaderInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
@ -23,33 +23,52 @@ use Composer\Composer;
|
||||||
class LibraryInstaller implements InstallerInterface
|
class LibraryInstaller implements InstallerInterface
|
||||||
{
|
{
|
||||||
private $dir;
|
private $dir;
|
||||||
private $composer;
|
|
||||||
private $preferSource;
|
private $preferSource;
|
||||||
|
private $downloaders = array();
|
||||||
|
|
||||||
public function __construct($dir = 'vendor', $preferSource = false)
|
public function __construct($dir = 'vendor', $preferSource = false)
|
||||||
{
|
{
|
||||||
$this->dir = $dir;
|
$this->dir = $dir;
|
||||||
$this->preferSource = $preferSource;
|
$this->preferSource = $preferSource;
|
||||||
|
|
||||||
|
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.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setComposer(Composer $composer)
|
public function setDownloader($type, DownloaderInterface $downloader = null)
|
||||||
{
|
{
|
||||||
$this->composer = $composer;
|
if (null === $downloader) {
|
||||||
|
unset($this->downloaders[$type]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->downloaders[$type] = $downloader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDownloader($type)
|
||||||
|
{
|
||||||
|
if (!isset($this->downloaders[$type])) {
|
||||||
|
throw new \UnexpectedValueException('Unknown source type: '.$type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->downloaders[$type];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function install(PackageInterface $package)
|
public function install(PackageInterface $package)
|
||||||
{
|
{
|
||||||
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->path.' does not exist and could not be created.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!($this->preferSource && $package->getSourceType()) && $package->getDistType()) {
|
if (!($this->preferSource && $package->getSourceType()) && $package->getDistType()) {
|
||||||
$downloader = $this->composer->getDownloader($package->getDistType());
|
$downloader = $this->getDownloader($package->getDistType());
|
||||||
|
|
||||||
return $downloader->download(
|
return $downloader->download(
|
||||||
$package, $this->dir, $package->getDistUrl(), $package->getDistSha1Checksum()
|
$package, $this->dir, $package->getDistUrl(), $package->getDistSha1Checksum()
|
||||||
|
@ -57,7 +76,7 @@ class LibraryInstaller implements InstallerInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($package->getSourceType()) {
|
if ($package->getSourceType()) {
|
||||||
$downloader = $this->composer->getDownloader($package->getSourceType());
|
$downloader = $this->getDownloader($package->getSourceType());
|
||||||
|
|
||||||
return $downloader->download(
|
return $downloader->download(
|
||||||
$package, $this->dir, $package->getSourceUrl()
|
$package, $this->dir, $package->getSourceUrl()
|
||||||
|
@ -70,7 +89,7 @@ class LibraryInstaller implements InstallerInterface
|
||||||
public function isInstalled(PackageInterface $package)
|
public function isInstalled(PackageInterface $package)
|
||||||
{
|
{
|
||||||
if ($package->getSourceType()) {
|
if ($package->getSourceType()) {
|
||||||
$downloader = $this->composer->getDownloader($package->getSourceType());
|
$downloader = $this->getDownloader($package->getSourceType());
|
||||||
|
|
||||||
if ($downloader->isDownloaded($package, $this->dir)) {
|
if ($downloader->isDownloaded($package, $this->dir)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -78,7 +97,7 @@ class LibraryInstaller implements InstallerInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($package->getDistType()) {
|
if ($package->getDistType()) {
|
||||||
$downloader = $this->composer->getDownloader($package->getDistType());
|
$downloader = $this->getDownloader($package->getDistType());
|
||||||
|
|
||||||
if ($downloader->isDownloaded($package, $this->dir)) {
|
if ($downloader->isDownloaded($package, $this->dir)) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -143,25 +143,4 @@ abstract class BasePackage implements PackageInterface
|
||||||
{
|
{
|
||||||
return $this->getName().'-'.$this->getVersion().'-'.$this->getReleaseType();
|
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]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
<?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($config['type']);
|
||||||
|
|
||||||
|
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 $requirements;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validateConfig(array $config)
|
||||||
|
{
|
||||||
|
if (!isset($config['name'])) {
|
||||||
|
throw new \UnexpectedValueException('name is required for package');
|
||||||
|
}
|
||||||
|
if (!isset($config['type'])) {
|
||||||
|
throw new \UnexpectedValueException('type 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,16 +23,6 @@ class ArrayRepository implements RepositoryInterface
|
||||||
{
|
{
|
||||||
protected $packages;
|
protected $packages;
|
||||||
|
|
||||||
static public function supports($type, $name = '', $url = '')
|
|
||||||
{
|
|
||||||
return 'array' === strtolower($type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function create($type, $name = '', $url = '')
|
|
||||||
{
|
|
||||||
return new static();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new package to the repository
|
* Adds a new package to the repository
|
||||||
*
|
*
|
||||||
|
|
|
@ -12,9 +12,7 @@
|
||||||
|
|
||||||
namespace Composer\Repository;
|
namespace Composer\Repository;
|
||||||
|
|
||||||
use Composer\Package\MemoryPackage;
|
use Composer\Package\Loader\ArrayLoader;
|
||||||
use Composer\Package\BasePackage;
|
|
||||||
use Composer\Package\Link;
|
|
||||||
use Composer\Package\LinkConstraint\VersionConstraint;
|
use Composer\Package\LinkConstraint\VersionConstraint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,20 +20,16 @@ use Composer\Package\LinkConstraint\VersionConstraint;
|
||||||
*/
|
*/
|
||||||
class ComposerRepository extends ArrayRepository
|
class ComposerRepository extends ArrayRepository
|
||||||
{
|
{
|
||||||
|
protected $url;
|
||||||
protected $packages;
|
protected $packages;
|
||||||
|
|
||||||
static public function supports($type, $name = '', $url = '')
|
|
||||||
{
|
|
||||||
return 'composer' === strtolower($type) && '' !== $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function create($type, $name = '', $url = '')
|
|
||||||
{
|
|
||||||
return new static($url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __construct($url)
|
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;
|
$this->url = $url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,60 +46,11 @@ class ComposerRepository extends ArrayRepository
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createPackages($data)
|
private function createPackages($data)
|
||||||
{
|
{
|
||||||
foreach ($data['versions'] as $rev) {
|
foreach ($data['versions'] as $rev) {
|
||||||
$version = BasePackage::parseVersion($rev['version']);
|
$loader = new ArrayLoader();
|
||||||
|
$this->addPackage($loader->load($rev));
|
||||||
$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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,21 +24,13 @@ use Composer\Package\LinkConstraint\VersionConstraint;
|
||||||
*/
|
*/
|
||||||
class GitRepository extends ArrayRepository
|
class GitRepository extends ArrayRepository
|
||||||
{
|
{
|
||||||
protected $packages;
|
protected $url;
|
||||||
|
protected $cacheDir;
|
||||||
|
|
||||||
static public function supports($type, $name = '', $url = '')
|
public function __construct($url, $cacheDir)
|
||||||
{
|
|
||||||
return 'git' === strtolower($type) && '' !== $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function create($type, $name = '', $url = '')
|
|
||||||
{
|
|
||||||
return new static($url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __construct($url)
|
|
||||||
{
|
{
|
||||||
$this->url = $url;
|
$this->url = $url;
|
||||||
|
$this->cacheDir = $cacheDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function initialize()
|
protected function initialize()
|
||||||
|
|
|
@ -23,26 +23,17 @@ use Composer\Package\LinkConstraint\VersionConstraint;
|
||||||
*/
|
*/
|
||||||
class PearRepository extends ArrayRepository
|
class PearRepository extends ArrayRepository
|
||||||
{
|
{
|
||||||
private $name;
|
protected $url;
|
||||||
private $url;
|
protected $cacheDir;
|
||||||
|
|
||||||
static public function supports($type, $name = '', $url = '')
|
public function __construct($url, $cacheDir)
|
||||||
{
|
|
||||||
return 'pear' === strtolower($type) && '' !== $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
static public function create($type, $name = '', $url = '')
|
|
||||||
{
|
|
||||||
return new static($url, $name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __construct($url, $name = '')
|
|
||||||
{
|
{
|
||||||
if (!filter_var($url, FILTER_VALIDATE_URL)) {
|
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->url = $url;
|
||||||
|
$this->cacheDir = $cacheDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function initialize()
|
protected function initialize()
|
||||||
|
|
|
@ -20,13 +20,6 @@ use Composer\Package\BasePackage;
|
||||||
*/
|
*/
|
||||||
class PlatformRepository extends ArrayRepository
|
class PlatformRepository extends ArrayRepository
|
||||||
{
|
{
|
||||||
protected $packages;
|
|
||||||
|
|
||||||
static public function supports($type, $name = '', $url = '')
|
|
||||||
{
|
|
||||||
return 'platform' === strtolower($type);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function initialize()
|
protected function initialize()
|
||||||
{
|
{
|
||||||
parent::initialize();
|
parent::initialize();
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
<?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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Konstantin Kudryashiv <ever.zet@gmail.com>
|
|
||||||
*/
|
|
||||||
class RepositoryFactory
|
|
||||||
{
|
|
||||||
private $classes = array();
|
|
||||||
|
|
||||||
public function __construct(array $classes)
|
|
||||||
{
|
|
||||||
foreach ($classes as $class) {
|
|
||||||
$this->registerRepositoryClass($class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function registerRepositoryClass($class)
|
|
||||||
{
|
|
||||||
$reflection = new \ReflectionClass($class);
|
|
||||||
|
|
||||||
if (!$reflection->implementsInterface('Composer\Repository\RepositoryInterface')) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
'Repository class should implement "RepositoryInterface", but "'.$class.'"'.
|
|
||||||
'given'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->classes[] = $class;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function classWhichSupports($type, $name = '', $url = '')
|
|
||||||
{
|
|
||||||
foreach ($this->classes as $class) {
|
|
||||||
if ($class::supports($type, $name, $url)) {
|
|
||||||
return $class;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new \UnexpectedValueException(sprintf(
|
|
||||||
"Can not find repository class, which supports:\n%s",
|
|
||||||
json_encode(array($name => array($type => $url)))
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function create($type, $name = '', $url = '')
|
|
||||||
{
|
|
||||||
$class = $this->classWhichSupports($type, $name, $url);
|
|
||||||
|
|
||||||
return $class::create($type, $name, $url);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue