Finalize platform override feature
- Added tests, docs - Persist to lock file - Add support in config command - Added to json schemapull/3982/head
parent
80b0a35a68
commit
a57c51e8d7
|
@ -82,7 +82,7 @@ resolution.
|
|||
have a proper setup.
|
||||
* **--ignore-platform-reqs:** ignore `php`, `hhvm`, `lib-*` and `ext-*`
|
||||
requirements and force the installation even if the local machine does not
|
||||
fulfill these.
|
||||
fulfill these. See also the `platform` [config option](04-schema.md#config).
|
||||
* **--dry-run:** If you want to run through an installation without actually
|
||||
installing a package, you can use `--dry-run`. This will simulate the
|
||||
installation and show you what would happen.
|
||||
|
@ -127,7 +127,7 @@ php composer.phar update vendor/*
|
|||
* **--prefer-dist:** Install packages from `dist` when available.
|
||||
* **--ignore-platform-reqs:** ignore `php`, `hhvm`, `lib-*` and `ext-*`
|
||||
requirements and force the installation even if the local machine does not
|
||||
fulfill these.
|
||||
fulfill these. See also the `platform` [config option](04-schema.md#config).
|
||||
* **--dry-run:** Simulate the command without actually doing anything.
|
||||
* **--dev:** Install packages listed in `require-dev` (this is the default behavior).
|
||||
* **--no-dev:** Skip installing packages listed in `require-dev`. The autoloader generation skips the `autoload-dev` rules.
|
||||
|
@ -171,7 +171,7 @@ php composer.phar require vendor/package:2.* vendor/package2:dev-master
|
|||
* **--prefer-dist:** Install packages from `dist` when available.
|
||||
* **--ignore-platform-reqs:** ignore `php`, `hhvm`, `lib-*` and `ext-*`
|
||||
requirements and force the installation even if the local machine does not
|
||||
fulfill these.
|
||||
fulfill these. See also the `platform` [config option](04-schema.md#config).
|
||||
* **--dev:** Add packages to `require-dev`.
|
||||
* **--no-update:** Disables the automatic update of the dependencies.
|
||||
* **--no-progress:** Removes the progress display that can mess with some
|
||||
|
@ -195,7 +195,7 @@ uninstalled.
|
|||
### Options
|
||||
* **--ignore-platform-reqs:** ignore `php`, `hhvm`, `lib-*` and `ext-*`
|
||||
requirements and force the installation even if the local machine does not
|
||||
fulfill these.
|
||||
fulfill these. See also the `platform` [config option](04-schema.md#config).
|
||||
* **--dev:** Remove packages from `require-dev`.
|
||||
* **--no-update:** Disables the automatic update of the dependencies.
|
||||
* **--no-progress:** Removes the progress display that can mess with some
|
||||
|
|
|
@ -761,6 +761,9 @@ The following options are supported:
|
|||
against them. For example using
|
||||
`{"example.org": {"username": "alice", "password": "foo"}` as the value of this
|
||||
option will let composer authenticate against example.org.
|
||||
* **platform:** Lets you fake platform packages (PHP and extensions) so that
|
||||
you can emulate a production env or define your target platform in the
|
||||
config. e.g. `{"php": "5.4", "ext-something": "4.0"}`.
|
||||
* **vendor-dir:** Defaults to `vendor`. You can install dependencies into a
|
||||
different directory if you want to. `$HOME` and `~` will be replaced by your
|
||||
home directory's path in vendor-dir and all `*-dir` options below.
|
||||
|
|
|
@ -145,6 +145,11 @@
|
|||
"type": ["string", "boolean"],
|
||||
"description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
|
||||
},
|
||||
"platform": {
|
||||
"type": "object",
|
||||
"description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
|
||||
"additionalProperties": true
|
||||
},
|
||||
"vendor-dir": {
|
||||
"type": "string",
|
||||
"description": "The location where all packages are installed, defaults to \"vendor\"."
|
||||
|
|
|
@ -410,6 +410,15 @@ EOT
|
|||
throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs http://bar.com');
|
||||
}
|
||||
|
||||
// handle platform
|
||||
if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
|
||||
if ($input->getOption('unset')) {
|
||||
return $this->configSource->removeConfigSetting($settingKey);
|
||||
}
|
||||
|
||||
return $this->configSource->addConfigSetting($settingKey, $values[0]);
|
||||
}
|
||||
|
||||
// handle github-oauth
|
||||
if (preg_match('/^(github-oauth|http-basic)\.(.+)/', $settingKey, $matches)) {
|
||||
if ($input->getOption('unset')) {
|
||||
|
|
|
@ -79,7 +79,7 @@ class JsonConfigSource implements ConfigSourceInterface
|
|||
public function addConfigSetting($name, $value)
|
||||
{
|
||||
$this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) {
|
||||
if ($key === 'github-oauth' || $key === 'http-basic') {
|
||||
if (preg_match('{^(github-oauth|http-basic|platform)\.}', $key)) {
|
||||
list($key, $host) = explode('.', $key, 2);
|
||||
if ($this->authConfig) {
|
||||
$config[$key][$host] = $val;
|
||||
|
@ -98,7 +98,7 @@ class JsonConfigSource implements ConfigSourceInterface
|
|||
public function removeConfigSetting($name)
|
||||
{
|
||||
$this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) {
|
||||
if ($key === 'github-oauth' || $key === 'http-basic') {
|
||||
if (preg_match('{^(github-oauth|http-basic|platform)\.}', $key)) {
|
||||
list($key, $host) = explode('.', $key, 2);
|
||||
if ($this->authConfig) {
|
||||
unset($config[$key][$host]);
|
||||
|
|
|
@ -206,9 +206,12 @@ class Installer
|
|||
|
||||
// create installed repo, this contains all local packages + platform packages (php & extensions)
|
||||
$localRepo = $this->repositoryManager->getLocalRepository();
|
||||
$platformOverride = $this->config->get('platform');
|
||||
$platformOverride = is_array($platformOverride) ? $platformOverride : array();
|
||||
$platformRepo = new PlatformRepository($platformOverride);
|
||||
if (!$this->update && $this->locker->isLocked()) {
|
||||
$platformOverrides = $this->locker->getPlatformOverrides();
|
||||
} else {
|
||||
$platformOverrides = $this->config->get('platform') ?: array();
|
||||
}
|
||||
$platformRepo = new PlatformRepository(array(), $platformOverrides);
|
||||
$repos = array(
|
||||
$localRepo,
|
||||
new InstalledArrayRepository(array($installedRootPackage)),
|
||||
|
@ -313,7 +316,8 @@ class Installer
|
|||
$this->package->getMinimumStability(),
|
||||
$this->package->getStabilityFlags(),
|
||||
$this->preferStable || $this->package->getPreferStable(),
|
||||
$this->preferLowest
|
||||
$this->preferLowest,
|
||||
$this->config->get('platform') ?: array()
|
||||
);
|
||||
if ($updatedLock) {
|
||||
$this->io->writeError('<info>Writing lock file</info>');
|
||||
|
|
|
@ -191,6 +191,13 @@ class Locker
|
|||
return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
|
||||
}
|
||||
|
||||
public function getPlatformOverrides()
|
||||
{
|
||||
$lockData = $this->getLockData();
|
||||
|
||||
return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
|
||||
}
|
||||
|
||||
public function getAliases()
|
||||
{
|
||||
$lockData = $this->getLockData();
|
||||
|
@ -223,10 +230,11 @@ class Locker
|
|||
* @param array $stabilityFlags
|
||||
* @param bool $preferStable
|
||||
* @param bool $preferLowest
|
||||
* @param array $platformOverrides
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest)
|
||||
public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest, array $platformOverrides)
|
||||
{
|
||||
$lock = array(
|
||||
'_readme' => array('This file locks the dependencies of your project to a known state',
|
||||
|
@ -260,6 +268,9 @@ class Locker
|
|||
|
||||
$lock['platform'] = $platformReqs;
|
||||
$lock['platform-dev'] = $platformDevReqs;
|
||||
if ($platformOverrides) {
|
||||
$lock['platform-overrides'] = $platformOverrides;
|
||||
}
|
||||
|
||||
if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
|
||||
if ($this->lockFile->exists()) {
|
||||
|
|
|
@ -24,12 +24,22 @@ class PlatformRepository extends ArrayRepository
|
|||
{
|
||||
const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit)?|hhvm|(?:ext|lib)-[^/]+)$}i';
|
||||
|
||||
/**
|
||||
* Defines overrides so that the platform can be mocked
|
||||
*
|
||||
* Should be an array of package name => version number mappings
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $overrides;
|
||||
|
||||
public function __construct(array $overrides = array())
|
||||
public function __construct(array $packages = array(), array $overrides = array())
|
||||
{
|
||||
parent::__construct(array());
|
||||
$this->overrides = $overrides;
|
||||
parent::__construct($packages);
|
||||
$this->overrides = array();
|
||||
foreach ($overrides as $name => $version) {
|
||||
$this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
|
||||
}
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
|
@ -40,19 +50,17 @@ 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 ) {
|
||||
foreach ($this->overrides as $override) {
|
||||
// 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);
|
||||
}
|
||||
if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
|
||||
throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
|
||||
}
|
||||
|
||||
$version = $versionParser->normalize($override['version']);
|
||||
$package = new CompletePackage($override['name'], $version, $override['version']);
|
||||
$package->setDescription('Overridden virtual platform package '.$override['name']);
|
||||
parent::addPackage($package);
|
||||
}
|
||||
|
||||
$prettyVersion = PluginInterface::PLUGIN_API_VERSION;
|
||||
$version = $versionParser->normalize($prettyVersion);
|
||||
|
@ -186,21 +194,13 @@ class PlatformRepository extends ArrayRepository
|
|||
}
|
||||
}
|
||||
|
||||
// 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?
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
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?
|
||||
// Skip if overridden
|
||||
if (isset($this->overrides[strtolower($package->getName())])) {
|
||||
return;
|
||||
}
|
||||
parent::addPackage($package);
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
--TEST--
|
||||
Install overridden platform requirements works
|
||||
--COMPOSER--
|
||||
{
|
||||
"repositories": [
|
||||
{
|
||||
"type": "package",
|
||||
"package": [
|
||||
{ "name": "a/a", "version": "1.0.0", "require": { "ext-dummy2": "1.*" } }
|
||||
]
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"a/a": "*",
|
||||
"ext-dummy": "~1.0",
|
||||
"php": "1.0"
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "1.0.0",
|
||||
"ext-dummy": "1.2.3",
|
||||
"ext-dummy2": "1.2.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
--RUN--
|
||||
install
|
||||
--EXPECT--
|
||||
Installing a/a (1.0.0)
|
|
@ -134,11 +134,12 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
|||
'stability-flags' => array(),
|
||||
'platform' => array(),
|
||||
'platform-dev' => array(),
|
||||
'platform-overrides' => array('foo/bar' => '1.0'),
|
||||
'prefer-stable' => false,
|
||||
'prefer-lowest' => false,
|
||||
));
|
||||
|
||||
$locker->setLockData(array($package1, $package2), array(), array(), array(), array(), 'dev', array(), false, false);
|
||||
$locker->setLockData(array($package1, $package2), array(), array(), array(), array(), 'dev', array(), false, false, array('foo/bar' => '1.0'));
|
||||
}
|
||||
|
||||
public function testLockBadPackages()
|
||||
|
@ -157,7 +158,7 @@ class LockerTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
$this->setExpectedException('LogicException');
|
||||
|
||||
$locker->setLockData(array($package1), array(), array(), array(), array(), 'dev', array(), false, false);
|
||||
$locker->setLockData(array($package1), array(), array(), array(), array(), 'dev', array(), false, false, array());
|
||||
}
|
||||
|
||||
public function testIsFresh()
|
||||
|
|
Loading…
Reference in New Issue