1
0
Fork 0

Merge branch 'master' into 2.0

* master:
  Follow up to #7946 test: add solver flag to assert path execution
  Fix tests
  Make sure config command output is also output on --quiet so that warnings can be hidden, fixes #7963
  Recognize composer-plugin-api as a platform package, fixes #7951
  Quote wildcards to avoid issues in some shells, fixes #7960
  Avoid dumping null values for dist reference/shasum and source reference, fixes #7955
  Soften hard exit after revert of composer file
  Make unixy proxy code POSIX compatible
  Update aliases.md
  Same but for Problem.php
  Better error message for present but incompatible versions
  Fix inconsistent casing
  Don't do (new Foo())->bar() - not 5.3-compatible
  Support identifying the HHVM version when not running with HHVM
pull/7883/head
Nils Adermann 2019-02-10 20:28:24 +01:00
commit 287419f6a0
16 changed files with 169 additions and 42 deletions

View File

@ -9,13 +9,13 @@ a logging library. If you have not yet installed Composer, refer to the
> **Note:** for the sake of simplicity, this introduction will assume you
> have performed a [local](00-intro.md#locally) install of Composer.
## `composer.json`: Project Setup
## `composer.json`: Project setup
To start using Composer in your project, all you need is a `composer.json`
file. This file describes the dependencies of your project and may contain
other metadata as well.
### The `require` Key
### The `require` key
The first (and often only) thing you specify in `composer.json` is the
[`require`](04-schema.md#require) key. You are simply telling Composer which
@ -41,7 +41,7 @@ assumed that the `monolog/monolog` package is registered on Packagist. (See more
about Packagist [below](#packagist), or read more about repositories
[here](05-repositories.md)).
### Package Names
### Package names
The package name consists of a vendor name and the project's name. Often these
will be identical - the vendor name only exists to prevent naming clashes. For
@ -53,7 +53,7 @@ Read more about publishing packages and package naming [here](02-libraries.md).
you to require certain versions of server software. See
[platform packages](#platform-packages) below.)
### Package Version Constraints
### Package version constraints
In our example, we are requesting the Monolog package with the version constraint
[`1.0.*`](https://semver.mwl.be/#?package=monolog%2Fmonolog&version=1.0.*).
@ -84,7 +84,7 @@ versions, how versions relate to each other, and on version constraints.
> versions of a package. Read more about stability flags and the `minimum-stability`
> key on the [schema page](04-schema.md).
## Installing Dependencies
## Installing dependencies
To install the defined dependencies for your project, run the
[`install`](03-cli.md#install) command.
@ -95,7 +95,7 @@ php composer.phar install
When you run this command, one of two things may happen:
### Installing Without `composer.lock`
### Installing without `composer.lock`
If you have never run the command before and there is also no `composer.lock` file present,
Composer simply resolves all dependencies listed in your `composer.json` file and downloads
@ -114,7 +114,7 @@ of them that it downloaded to the `composer.lock` file, locking the project to t
versions. You should commit the `composer.lock` file to your project repo so that all people
working on the project are locked to the same versions of dependencies (more below).
### Installing With `composer.lock`
### Installing with `composer.lock`
This brings us to the second scenario. If there is already a `composer.lock` file as well as a
`composer.json` file when you run `composer install`, it means either you ran the
@ -130,7 +130,7 @@ working on your project. As a result you will have all dependencies requested by
the file was created). This is by design, it ensures that your project does not break because of
unexpected changes in dependencies.
### Commit Your `composer.lock` File to Version Control
### Commit your `composer.lock` file to version control
Committing this file to VC is important because it will cause anyone who sets
up the project to use the exact same
@ -142,7 +142,7 @@ reinstalling the project you can feel confident the dependencies installed are
still working even if your dependencies released many new versions since then.
(See note below about using the `update` command.)
## Updating Dependencies to their Latest Versions
## Updating dependencies to their latest versions
As mentioned above, the `composer.lock` file prevents you from automatically getting
the latest versions of your dependencies. To update to the latest versions, use the

View File

@ -140,7 +140,7 @@ php composer.phar update vendor/package vendor/package2
You can also use wildcards to update a bunch of packages at once:
```sh
php composer.phar update vendor/*
php composer.phar update "vendor/*"
```
### Options

View File

@ -89,6 +89,12 @@ Add this to your project's root `composer.json`:
}
```
Or let composer add it for you with:
```
php composer.phar require monolog/monolog:"dev-bugfix as 1.0.x-dev"
```
That will fetch the `dev-bugfix` version of `monolog/monolog` from your GitHub
and alias it to `1.0.x-dev`.

View File

@ -21,6 +21,7 @@ use Symfony\Component\Console\Output\OutputInterface;
use Composer\Config;
use Composer\Config\JsonConfigSource;
use Composer\Factory;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Semver\VersionParser;
use Composer\Package\BasePackage;
@ -284,7 +285,7 @@ EOT
$value = json_encode($value);
}
$this->getIO()->write($value);
$this->getIO()->write($value, true, IOInterface::QUIET);
return 0;
}
@ -710,9 +711,9 @@ EOT
}
if (is_string($rawVal) && $rawVal != $value) {
$io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>');
$io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>', true, IOInterface::QUIET);
} else {
$io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>');
$io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>', true, IOInterface::QUIET);
}
}
}

View File

@ -194,7 +194,7 @@ EOT
$status = $install->run();
if ($status !== 0) {
$this->revertComposerFile();
$this->revertComposerFile(false);
}
return $status;
@ -225,7 +225,7 @@ EOT
return;
}
public function revertComposerFile()
public function revertComposerFile($hardExit = true)
{
$io = $this->getIO();
@ -237,6 +237,8 @@ EOT
file_put_contents($this->json->getPath(), $this->composerBackup);
}
exit(1);
if ($hardExit) {
exit(1);
}
}
}

View File

@ -106,7 +106,7 @@ class Problem
$msg = "\n - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but ';
if (defined('HHVM_VERSION')) {
if (defined('HHVM_VERSION') || count($available)) {
return $msg . 'your HHVM version does not satisfy that requirement.';
}

View File

@ -175,13 +175,18 @@ abstract class Rule
return $text . ' -> your HHVM version does not satisfy that requirement.';
}
if ($targetName === 'hhvm') {
return $text . ' -> you are running this with PHP and not HHVM.';
}
$packages = $pool->whatProvides($targetName);
$package = count($packages) ? current($packages) : phpversion();
if ($targetName === 'hhvm') {
if ($package instanceof CompletePackage) {
return $text . ' -> your HHVM version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
} else {
return $text . ' -> you are running this with PHP and not HHVM.';
}
}
if (!($package instanceof CompletePackage)) {
return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
}

View File

@ -58,6 +58,9 @@ class Solver
/** @var array */
protected $learnedWhy = array();
/** @var bool */
public $testFlagLearnedPositiveLiteral = false;
/** @var IOInterface */
protected $io;
@ -478,6 +481,9 @@ class Solver
unset($seen[abs($literal)]);
if ($num && 0 === --$num) {
if ($literal < 0) {
$this->testFlagLearnedPositiveLiteral = true;
}
$learnedLiterals[0] = -$literal;
if (!$l1num) {

View File

@ -196,9 +196,13 @@ class BinaryInstaller
dir=\$(cd "\${0%[/\\\\]*}" > /dev/null; cd $binDir && pwd)
if [ -d /proc/cygdrive ] && [[ \$(which php) == \$(readlink -n /proc/cygdrive)/* ]]; then
# We are in Cygwin using Windows php, so the path must be translated
dir=\$(cygpath -m "\$dir");
if [ -d /proc/cygdrive ]; then
case \$(which php) in
\$(readlink -n /proc/cygdrive)/*)
# We are in Cygwin using Windows php, so the path must be translated
dir=\$(cygpath -m "\$dir");
;;
esac
fi
"\${dir}/$binFile" "\$@"

View File

@ -48,7 +48,9 @@ class ArrayDumper
if ($package->getSourceType()) {
$data['source']['type'] = $package->getSourceType();
$data['source']['url'] = $package->getSourceUrl();
$data['source']['reference'] = $package->getSourceReference();
if (null !== ($value = $package->getSourceReference())) {
$data['source']['reference'] = $value;
}
if ($mirrors = $package->getSourceMirrors()) {
$data['source']['mirrors'] = $mirrors;
}
@ -57,8 +59,12 @@ class ArrayDumper
if ($package->getDistType()) {
$data['dist']['type'] = $package->getDistType();
$data['dist']['url'] = $package->getDistUrl();
$data['dist']['reference'] = $package->getDistReference();
$data['dist']['shasum'] = $package->getDistSha1Checksum();
if (null !== ($value = $package->getDistReference())) {
$data['dist']['reference'] = $value;
}
if (null !== ($value = $package->getDistSha1Checksum())) {
$data['dist']['shasum'] = $value;
}
if ($mirrors = $package->getDistMirrors()) {
$data['dist']['mirrors'] = $mirrors;
}

View File

@ -152,7 +152,7 @@ class ArrayLoader implements LoaderInterface
}
$package->setSourceType($config['source']['type']);
$package->setSourceUrl($config['source']['url']);
$package->setSourceReference($config['source']['reference']);
$package->setSourceReference(isset($config['source']['reference']) ? $config['source']['reference'] : null);
if (isset($config['source']['mirrors'])) {
$package->setSourceMirrors($config['source']['mirrors']);
}

View File

@ -16,15 +16,18 @@ use Composer\Package\CompletePackage;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;
use Composer\Plugin\PluginInterface;
use Composer\Util\ProcessExecutor;
use Composer\Util\Silencer;
use Composer\Util\Platform;
use Composer\XdebugHandler\XdebugHandler;
use Symfony\Component\Process\ExecutableFinder;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class PlatformRepository extends ArrayRepository
{
const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*)$}iD';
const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*|composer-plugin-api)$}iD';
private $versionParser;
@ -37,8 +40,11 @@ class PlatformRepository extends ArrayRepository
*/
private $overrides = array();
public function __construct(array $packages = array(), array $overrides = array())
private $process;
public function __construct(array $packages = array(), array $overrides = array(), ProcessExecutor $process = null)
{
$this->process = $process === null ? (new ProcessExecutor()) : $process;
foreach ($overrides as $name => $version) {
$this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
}
@ -220,12 +226,27 @@ class PlatformRepository extends ArrayRepository
$this->addPackage($lib);
}
if (defined('HHVM_VERSION')) {
$hhvmVersion = defined('HHVM_VERSION') ? HHVM_VERSION : null;
if ($hhvmVersion === null && !Platform::isWindows()) {
$finder = new ExecutableFinder();
$hhvm = $finder->find('hhvm');
if ($hhvm !== null) {
$exitCode = $this->process->execute(
ProcessExecutor::escape($hhvm).
' --php -d hhvm.jit=0 -r "echo HHVM_VERSION;" 2>/dev/null',
$hhvmVersion
);
if ($exitCode !== 0) {
$hhvmVersion = null;
}
}
}
if ($hhvmVersion) {
try {
$prettyVersion = HHVM_VERSION;
$prettyVersion = $hhvmVersion;
$version = $this->versionParser->normalize($prettyVersion);
} catch (\UnexpectedValueException $e) {
$prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION);
$prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', $hhvmVersion);
$version = $this->versionParser->normalize($prettyVersion);
}

View File

@ -899,6 +899,9 @@ class SolverTest extends TestCase
$this->request->install('A');
// check correct setup for assertion later
$this->assertFalse($this->solver->testFlagLearnedPositiveLiteral);
$this->checkSolverResult(array(
array('job' => 'install', 'package' => $packageF1),
array('job' => 'install', 'package' => $packageD),
@ -908,6 +911,10 @@ class SolverTest extends TestCase
array('job' => 'install', 'package' => $packageB),
array('job' => 'install', 'package' => $packageA),
));
// verify that the code path leading to a negative literal resulting in a positive learned literal is actually
// executed
$this->assertTrue($this->solver->testFlagLearnedPositiveLiteral);
}
protected function reposComplete()

View File

@ -35,8 +35,7 @@ install --prefer-dist
"dist": {
"type": "zip",
"url": "http://www.example.com/dist.zip",
"reference": "459720ff3b74ee0c0d159277c6f2f5df89d8a4f6",
"shasum": null
"reference": "459720ff3b74ee0c0d159277c6f2f5df89d8a4f6"
},
"type": "library"
}

View File

@ -101,43 +101,43 @@ g/g is dev and installed in a different ref than the #ref, so it gets updated an
{
"name": "a/a", "version": "dev-master",
"source": { "reference": "2222222222222222222222222222222222222222", "url": "https://github.com/a/newa", "type": "git" },
"dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/a/newa/zipball/2222222222222222222222222222222222222222", "type": "zip", "shasum": null },
"dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/a/newa/zipball/2222222222222222222222222222222222222222", "type": "zip" },
"type": "library"
},
{
"name": "b/b", "version": "2.0.3",
"source": { "reference": "2222222222222222222222222222222222222222", "url": "https://github.com/b/newb", "type": "git" },
"dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/b/newb/zipball/2222222222222222222222222222222222222222", "type": "zip", "shasum": null },
"dist": { "reference": "2222222222222222222222222222222222222222", "url": "https://api.github.com/repos/b/newb/zipball/2222222222222222222222222222222222222222", "type": "zip" },
"type": "library"
},
{
"name": "c/c", "version": "1.0.0",
"source": { "reference": "1111111111111111111111111111111111111111", "url": "https://github.com/c/newc", "type": "git" },
"dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/c/newc/zipball/1111111111111111111111111111111111111111", "type": "zip", "shasum": null },
"dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/c/newc/zipball/1111111111111111111111111111111111111111", "type": "zip" },
"type": "library"
},
{
"name": "d/d", "version": "dev-master",
"source": { "reference": "1111111111111111111111111111111111111111", "url": "https://github.com/d/newd", "type": "git" },
"dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/d/newd/zipball/1111111111111111111111111111111111111111", "type": "zip", "shasum": null },
"dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/d/newd/zipball/1111111111111111111111111111111111111111", "type": "zip" },
"type": "library"
},
{
"name": "e/e", "version": "dev-master",
"source": { "reference": "1111111111111111111111111111111111111111", "url": "https://github.com/e/newe", "type": "git" },
"dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/e/newe/zipball/1111111111111111111111111111111111111111", "type": "zip", "shasum": null },
"dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/e/newe/zipball/1111111111111111111111111111111111111111", "type": "zip" },
"type": "library"
},
{
"name": "f/f", "version": "dev-master",
"source": { "reference": "1111111111111111111111111111111111111111", "url": "https://github.com/f/newf", "type": "git" },
"dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/f/newf/zipball/1111111111111111111111111111111111111111", "type": "zip", "shasum": null },
"dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/f/newf/zipball/1111111111111111111111111111111111111111", "type": "zip" },
"type": "library"
},
{
"name": "g/g", "version": "dev-master",
"source": { "reference": "1111111111111111111111111111111111111111", "url": "https://github.com/g/newg", "type": "git" },
"dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/g/newg/zipball/1111111111111111111111111111111111111111", "type": "zip", "shasum": null },
"dist": { "reference": "1111111111111111111111111111111111111111", "url": "https://api.github.com/repos/g/newg/zipball/1111111111111111111111111111111111111111", "type": "zip" },
"type": "library"
}
],

View File

@ -0,0 +1,70 @@
<?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\Test\Repository;
use Composer\Repository\PlatformRepository;
use Composer\Test\TestCase;
use Composer\Util\Platform;
use Symfony\Component\Process\ExecutableFinder;
class PlatformRepositoryTest extends TestCase {
public function testHHVMVersionWhenExecutingInHHVM() {
if (!defined('HHVM_VERSION_ID')) {
$this->markTestSkipped('Not running with HHVM');
return;
}
$repository = new PlatformRepository();
$package = $repository->findPackage('hhvm', '*');
$this->assertNotNull($package, 'failed to find HHVM package');
$this->assertSame(
sprintf('%d.%d.%d',
HHVM_VERSION_ID / 10000,
(HHVM_VERSION_ID / 100) % 100,
HHVM_VERSION_ID % 100
),
$package->getPrettyVersion()
);
}
public function testHHVMVersionWhenExecutingInPHP() {
if (defined('HHVM_VERSION_ID')) {
$this->markTestSkipped('Running with HHVM');
return;
}
if (PHP_VERSION_ID < 50400) {
$this->markTestSkipped('Test only works on PHP 5.4+');
return;
}
if (Platform::isWindows()) {
$this->markTestSkipped('Test does not run on Windows');
return;
}
$finder = new ExecutableFinder();
$hhvm = $finder->find('hhvm');
if ($hhvm === null) {
$this->markTestSkipped('HHVM is not installed');
}
$process = $this->getMockBuilder('Composer\Util\ProcessExecutor')->getMock();
$process->expects($this->once())->method('execute')->will($this->returnCallback(
function($command, &$out) {
$this->assertContains('HHVM_VERSION', $command);
$out = '4.0.1-dev';
return 0;
}
));
$repository = new PlatformRepository(array(), array(), $process);
$package = $repository->findPackage('hhvm', '*');
$this->assertNotNull($package, 'failed to find HHVM package');
$this->assertSame('4.0.1.0-dev', $package->getVersion());
}
}