From f76685ce4f8558b4261d599d372c6cd424af4cbd Mon Sep 17 00:00:00 2001 From: Joakim Israelsson Date: Wed, 14 May 2014 20:29:22 +0200 Subject: [PATCH 1/5] PlatformRepository now takes an array of packages to override. These overrides are on the form array($packageName => $version) These "virtual" packages are added instead of the real ones, with the version specified. Note that it is a version and not a constraint so you cannot pass array('ext-mongo' => '*'). Also there is currently no limit what packages can be overriden. --- .../Repository/PlatformRepository.php | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index 0c6a5d9ce..1ba264ec1 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,35 @@ 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 ) { + $version = $versionParser->normalize($prettyVersion); + $package = new CompletePackage($name, $version, $prettyVersion); + $package->setDescription("Overridden virtual platform package $name."); + parent::addPackage($package); + } + + $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 +64,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 +92,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 +162,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,10 +176,29 @@ 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) { From 571363dee267f7ccdc8a8c3331fca8d5ddb0821f Mon Sep 17 00:00:00 2001 From: Joakim Israelsson Date: Wed, 14 May 2014 20:31:42 +0200 Subject: [PATCH 2/5] The config setting 'platform' is used to override platform packages. Like suggested in #1522. These overridden packages appear only during install/update and not when running init, show and search commands. I don't know if they should or not. --- src/Composer/Config.php | 1 + src/Composer/Installer.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Config.php b/src/Composer/Config.php index 89f535725..53314611f 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -39,6 +39,7 @@ class Config 'optimize-autoloader' => false, 'prepend-autoloader' => true, 'github-domains' => array('github.com'), + 'platform' => array(), ); public static $defaultRepositories = array( diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 03e6beb92..079a5a6e5 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -196,7 +196,7 @@ class Installer // create installed repo, this contains all local packages + platform packages (php & extensions) $localRepo = $this->repositoryManager->getLocalRepository(); - $platformRepo = new PlatformRepository(); + $platformRepo = new PlatformRepository($this->config->get('platform')); $repos = array( $localRepo, new InstalledArrayRepository(array($installedRootPackage)), From ac89a5bb3b6bb99a3d1a35e338f85d43da64733a Mon Sep 17 00:00:00 2001 From: Joakim Israelsson Date: Wed, 14 May 2014 20:37:24 +0200 Subject: [PATCH 3/5] Only allow platform packages to be overridden. As defined by the PlatformRepository::PLATFORM_PACKAGE_REGEX pattern. --- src/Composer/Repository/PlatformRepository.php | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index 1ba264ec1..8d4e639c3 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -41,10 +41,16 @@ class PlatformRepository extends ArrayRepository // Add each of the override versions as options. // Later we might even replace the extensions instead. foreach( $this->overrides as $name => $prettyVersion ) { - $version = $versionParser->normalize($prettyVersion); - $package = new CompletePackage($name, $version, $prettyVersion); - $package->setDescription("Overridden virtual platform package $name."); - parent::addPackage($package); + // 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 \UnexpectedValueException('Invalid platform package "'.$name); + } } From 19b39550223945bcde8e4ced84c97b691f9fc3a2 Mon Sep 17 00:00:00 2001 From: Joakim Israelsson Date: Thu, 15 May 2014 11:23:19 +0200 Subject: [PATCH 4/5] Throw InvalidArgumentException on invalid platform packages in config. It's a user provided configuration value that's wrong so it makes more sense. --- src/Composer/Repository/PlatformRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index 8d4e639c3..909eaab7c 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -49,7 +49,7 @@ class PlatformRepository extends ArrayRepository parent::addPackage($package); } else { - throw new \UnexpectedValueException('Invalid platform package "'.$name); + throw new \InvalidArgumentException('Invalid platform package '.$name); } } From bb375b1e751682aea1341ebbb696c017546aba7e Mon Sep 17 00:00:00 2001 From: Joakim Israelsson Date: Thu, 15 May 2014 13:36:40 +0200 Subject: [PATCH 5/5] Only use "platform" config if it is an array. Another option could have been to adjust the test that failed so a platform array is returned from the mock config object but this feels more robust. If "platform" config is set to a non-array value it is silently ignored now. --- src/Composer/Installer.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php index 079a5a6e5..57680600c 100644 --- a/src/Composer/Installer.php +++ b/src/Composer/Installer.php @@ -196,7 +196,9 @@ class Installer // create installed repo, this contains all local packages + platform packages (php & extensions) $localRepo = $this->repositoryManager->getLocalRepository(); - $platformRepo = new PlatformRepository($this->config->get('platform')); + $platformOverride = $this->config->get('platform'); + $platformOverride = is_array($platformOverride) ? $platformOverride : array(); + $platformRepo = new PlatformRepository($platformOverride); $repos = array( $localRepo, new InstalledArrayRepository(array($installedRootPackage)),