1
0
Fork 0

Add Config class and system-wide config management, fixes #513

pull/551/head
Jordi Boggiano 2012-04-09 16:10:25 +02:00
parent 61708a1bb1
commit e638182397
3 changed files with 154 additions and 47 deletions

View File

@ -43,6 +43,16 @@ class Composer
return $this->package;
}
public function setConfig(Config $config)
{
$this->config = $config;
}
public function getConfig()
{
return $this->config;
}
public function setLocker(Locker $locker)
{
$this->locker = $locker;

73
src/Composer/Config.php Normal file
View File

@ -0,0 +1,73 @@
<?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;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class Config
{
private $config;
public function __construct()
{
// load defaults
$this->config = array(
'process-timeout' => 300,
'vendor-dir' => 'vendor',
'bin-dir' => '{$vendor-dir}/bin',
);
}
public function merge(array $config)
{
// override defaults with given config
if (!empty($config['config']) && is_array($config['config'])) {
$this->config = array_merge_recursive($this->config, $config['config']);
}
}
public function get($key)
{
switch ($key) {
case 'vendor-dir':
case 'bin-dir':
case 'process-timeout':
// convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config
$env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
return $this->process(getenv($env) ?: $this->config[$key]);
default:
return $this->process($this->config[$key]);
}
}
public function has($key)
{
return array_key_exists($key, $this->config);
}
/**
* Replaces {$refs} inside a config string
*
* @param string a config string that can contain {$refs-to-other-config}
* @return string
*/
private function process($value)
{
$config = $this;
return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config) {
return $config->get($match[1]);
}, $value);
}
}

View File

@ -27,66 +27,81 @@ use Composer\Util\RemoteFilesystem;
*/
class Factory
{
public static function createConfig()
{
// load main Composer configuration
if (!$home = getenv('COMPOSER_HOME')) {
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
$home = getenv('APPDATA') . '/Composer/';
} else {
$home = getenv('HOME') . '/.composer/';
}
}
$config = new Config();
$file = new JsonFile($home.'config.json');
if ($file->exists()) {
$config->merge($file->read());
}
return $config;
}
/**
* Creates a Composer instance
*
* @param IOInterface $io IO instance
* @param mixed $localConfig either a configuration array or a filename to read from, if null it will read from the default filename
* @return Composer
*/
public function createComposer(IOInterface $io, $composerFile = null)
public function createComposer(IOInterface $io, $localConfig = null)
{
// load Composer configuration
if (null === $composerFile) {
$composerFile = getenv('COMPOSER') ?: 'composer.json';
if (null === $localConfig) {
$localConfig = getenv('COMPOSER') ?: 'composer.json';
}
$file = new JsonFile($composerFile, new RemoteFilesystem($io));
if (is_string($localConfig)) {
$composerFile = $localConfig;
$file = new JsonFile($localConfig, new RemoteFilesystem($io));
if (!$file->exists()) {
if ($composerFile === 'composer.json') {
if ($localConfig === 'composer.json') {
$message = 'Composer could not find a composer.json file in '.getcwd();
} else {
$message = 'Composer could not find the config file: '.$composerFile;
$message = 'Composer could not find the config file: '.$localConfig;
}
$instructions = 'To initialize a project, please create a composer.json file as described in the http://getcomposer.org/ "Getting Started" section';
throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
}
// Configuration defaults
$composerConfig = array(
'vendor-dir' => 'vendor',
'process-timeout' => 300,
);
$packageConfig = $file->read();
$file->validateSchema(JsonFile::LAX_SCHEMA);
if (isset($packageConfig['config']) && is_array($packageConfig['config'])) {
$packageConfig['config'] = array_merge($composerConfig, $packageConfig['config']);
} else {
$packageConfig['config'] = $composerConfig;
$localConfig = $file->read();
}
$vendorDir = getenv('COMPOSER_VENDOR_DIR') ?: $packageConfig['config']['vendor-dir'];
if (!isset($packageConfig['config']['bin-dir'])) {
$packageConfig['config']['bin-dir'] = $vendorDir.'/bin';
}
$binDir = getenv('COMPOSER_BIN_DIR') ?: $packageConfig['config']['bin-dir'];
// Configuration defaults
$config = $this->createConfig();
$config->merge($localConfig);
$vendorDir = $config->get('vendor-dir');
$binDir = $config->get('bin-dir');
// setup process timeout
$processTimeout = getenv('COMPOSER_PROCESS_TIMEOUT') ?: $packageConfig['config']['process-timeout'];
ProcessExecutor::setTimeout((int) $processTimeout);
ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
// initialize repository manager
$rm = $this->createRepositoryManager($io);
// load default repository unless it's explicitly disabled
$packageConfig = $this->addPackagistRepository($packageConfig);
$localConfig = $this->addPackagistRepository($localConfig);
// load local repository
$this->addLocalRepository($rm, $vendorDir);
// load package
$loader = new Package\Loader\RootPackageLoader($rm);
$package = $loader->load($packageConfig);
$package = $loader->load($localConfig);
// initialize download manager
$dm = $this->createDownloadManager($io);
@ -97,18 +112,21 @@ class Factory
// purge packages if they have been deleted on the filesystem
$this->purgePackages($rm, $im);
// init locker
$lockFile = substr($composerFile, -5) === '.json' ? substr($composerFile, 0, -4).'lock' : $composerFile . '.lock';
$locker = new Package\Locker(new JsonFile($lockFile, new RemoteFilesystem($io)), $rm, md5_file($composerFile));
// initialize composer
$composer = new Composer();
$composer->setConfig($config);
$composer->setPackage($package);
$composer->setLocker($locker);
$composer->setRepositoryManager($rm);
$composer->setDownloadManager($dm);
$composer->setInstallationManager($im);
// init locker if possible
if (isset($composerFile)) {
$lockFile = substr($composerFile, -5) === '.json' ? substr($composerFile, 0, -4).'lock' : $composerFile . '.lock';
$locker = new Package\Locker(new JsonFile($lockFile, new RemoteFilesystem($io)), $rm, md5_file($composerFile));
$composer->setLocker($locker);
}
return $composer;
}
@ -131,18 +149,19 @@ class Factory
$rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/.composer/installed.json')));
}
protected function addPackagistRepository(array $packageConfig)
protected function addPackagistRepository(array $localConfig)
{
$loadPackagist = true;
$packagistConfig = array(
'type' => 'composer',
'url' => 'http://packagist.org'
);
if (isset($packageConfig['repositories'])) {
foreach ($packageConfig['repositories'] as $key => $repo) {
if (isset($localConfig['repositories'])) {
foreach ($localConfig['repositories'] as $key => $repo) {
if (isset($repo['packagist'])) {
if (true === $repo['packagist']) {
$packageConfig['repositories'][$key] = $packagistConfig;
$localConfig['repositories'][$key] = $packagistConfig;
}
$loadPackagist = false;
@ -150,14 +169,14 @@ class Factory
}
}
} else {
$packageConfig['repositories'] = array();
$localConfig['repositories'] = array();
}
if ($loadPackagist) {
$packageConfig['repositories'][] = $packagistConfig;
$localConfig['repositories'][] = $packagistConfig;
}
return $packageConfig;
return $localConfig;
}
public function createDownloadManager(IOInterface $io)
@ -194,10 +213,15 @@ class Factory
}
}
static public function create(IOInterface $io, $composerFile = null)
/**
* @param IOInterface $io IO instance
* @param mixed $config either a configuration array or a filename to read from, if null it will read from the default filename
* @return Composer
*/
static public function create(IOInterface $io, $config = null)
{
$factory = new static();
return $factory->createComposer($io, $composerFile);
return $factory->createComposer($io, $config);
}
}