diff --git a/src/Composer/Config.php b/src/Composer/Config.php index b6d942c51..828b98e75 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -44,6 +44,7 @@ class Config 'github-domains' => array('github.com'), 'github-expose-hostname' => true, 'store-auths' => 'prompt', + 'platform' => array(), // valid keys without defaults (auth config stuff): // github-oauth // http-basic diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 7333d0d10..5934dd0df 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -206,7 +206,9 @@ class Installer // create installed repo, this contains all local packages + platform packages (php & extensions) $localRepo = $this->repositoryManager->getLocalRepository(); - $platformRepo = new PlatformRepository(); + $platformOverride = $this->config->get('platform'); + $platformOverride = is_array($platformOverride) ? $platformOverride : array(); + $platformRepo = new PlatformRepository($platformOverride); $repos = array( $localRepo, new InstalledArrayRepository(array($installedRootPackage)), diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index 636cba16b..909eaab7c 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -12,6 +12,7 @@ namespace Composer\Repository; +use Composer\Package\PackageInterface; use Composer\Package\CompletePackage; use Composer\Package\Version\VersionParser; use Composer\Plugin\PluginInterface; @@ -23,17 +24,41 @@ class PlatformRepository extends ArrayRepository { const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit)?|hhvm|(?:ext|lib)-[^/]+)$}i'; + private $overrides; + + public function __construct(array $overrides = array()) + { + parent::__construct(array()); + $this->overrides = $overrides; + } + protected function initialize() { parent::initialize(); $versionParser = new VersionParser(); + // Add each of the override versions as options. + // Later we might even replace the extensions instead. + foreach( $this->overrides as $name => $prettyVersion ) { + // Check that it's a platform package. + if( preg_match(self::PLATFORM_PACKAGE_REGEX, $name) ) { + $version = $versionParser->normalize($prettyVersion); + $package = new CompletePackage($name, $version, $prettyVersion); + $package->setDescription("Overridden virtual platform package $name."); + parent::addPackage($package); + } + else { + throw new \InvalidArgumentException('Invalid platform package '.$name); + } + } + + $prettyVersion = PluginInterface::PLUGIN_API_VERSION; $version = $versionParser->normalize($prettyVersion); $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion); $composerPluginApi->setDescription('The Composer Plugin API'); - parent::addPackage($composerPluginApi); + $this->addPackage($composerPluginApi); try { $prettyVersion = PHP_VERSION; @@ -45,12 +70,12 @@ class PlatformRepository extends ArrayRepository $php = new CompletePackage('php', $version, $prettyVersion); $php->setDescription('The PHP interpreter'); - parent::addPackage($php); + $this->addPackage($php); if (PHP_INT_SIZE === 8) { $php64 = new CompletePackage('php-64bit', $version, $prettyVersion); $php64->setDescription('The PHP interpreter (64bit)'); - parent::addPackage($php64); + $this->addPackage($php64); } $loadedExtensions = get_loaded_extensions(); @@ -73,7 +98,7 @@ class PlatformRepository extends ArrayRepository $packageName = $this->buildPackageName($name); $ext = new CompletePackage($packageName, $version, $prettyVersion); $ext->setDescription('The '.$name.' PHP extension'); - parent::addPackage($ext); + $this->addPackage($ext); } // Another quick loop, just for possible libraries @@ -143,7 +168,7 @@ class PlatformRepository extends ArrayRepository $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion); $lib->setDescription('The '.$name.' PHP library'); - parent::addPackage($lib); + $this->addPackage($lib); } if (defined('HHVM_VERSION')) { @@ -157,8 +182,28 @@ class PlatformRepository extends ArrayRepository $hhvm = new CompletePackage('hhvm', $version, $prettyVersion); $hhvm->setDescription('The HHVM Runtime (64bit)'); - parent::addPackage($hhvm); + $this->addPackage($hhvm); + } + } + + // TODO: Is it a good thing to redefine the public interface + // like this, or is it better to make the "only-add-if-no-in-platform" + // feature in a + // protected function addOverriddenPackage() + // instead? + public function addPackage(PackageInterface $package) + { + /* + If we can find the package in this repository, + in any version, it can only mean that it has been + added by the config key 'platform' and should + the real package (i.e. this one) should not be added. + */ + if( count($this->findPackages($package->getName())) > 0 ) { + // Log a warning that we're ignoring existing package? + return; } + parent::addPackage($package); } private function buildPackageName($name)