1
0
Fork 0

Merge branch 'master' into 2.0

pull/7947/head
Jordi Boggiano 2019-01-28 14:33:10 +01:00
commit 0b928b2a42
16 changed files with 247 additions and 136 deletions

11
.editorconfig Normal file
View File

@ -0,0 +1,11 @@
root = true
[*]
charset = utf-8
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.yml]
indent_size = 2

View File

@ -1,7 +1,5 @@
language: php language: php
sudo: false
dist: trusty dist: trusty
git: git:
@ -16,22 +14,20 @@ addons:
packages: packages:
- parallel - parallel
php:
- 5.4
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
- nightly
matrix: matrix:
include: include:
- php: 5.3 - php: 5.3
dist: precise dist: precise
- php: 5.4
- php: 5.5
- php: 5.6
- php: 7.0
- php: 7.1
- php: 7.2
- php: 7.3
- php: 7.3 - php: 7.3
env: deps=high env: deps=high
- php: nightly
fast_finish: true fast_finish: true
allow_failures: allow_failures:
- php: nightly - php: nightly
@ -42,6 +38,7 @@ before_install:
# disable default memory limit # disable default memory limit
- export INI=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - export INI=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
- echo memory_limit = -1 >> $INI - echo memory_limit = -1 >> $INI
- composer validate
install: install:
# flags to pass to install # flags to pass to install

View File

@ -73,8 +73,13 @@
"bin/composer" "bin/composer"
], ],
"scripts": { "scripts": {
"compile": "@php -dphar.readonly=0 bin/compile",
"test": "phpunit" "test": "phpunit"
}, },
"scripts-descriptions": {
"compile": "Compile composer.phar",
"test": "Run all tests"
},
"support": { "support": {
"issues": "https://github.com/composer/composer/issues", "issues": "https://github.com/composer/composer/issues",
"irc": "irc://irc.freenode.org/composer" "irc": "irc://irc.freenode.org/composer"

10
composer.lock generated
View File

@ -8,16 +8,16 @@
"packages": [ "packages": [
{ {
"name": "composer/ca-bundle", "name": "composer/ca-bundle",
"version": "1.1.3", "version": "1.1.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/ca-bundle.git", "url": "https://github.com/composer/ca-bundle.git",
"reference": "8afa52cd417f4ec417b4bfe86b68106538a87660" "reference": "558f321c52faeb4828c03e7dc0cfe39a09e09a2d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/8afa52cd417f4ec417b4bfe86b68106538a87660", "url": "https://api.github.com/repos/composer/ca-bundle/zipball/558f321c52faeb4828c03e7dc0cfe39a09e09a2d",
"reference": "8afa52cd417f4ec417b4bfe86b68106538a87660", "reference": "558f321c52faeb4828c03e7dc0cfe39a09e09a2d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -60,7 +60,7 @@
"ssl", "ssl",
"tls" "tls"
], ],
"time": "2018-10-18T06:09:13+00:00" "time": "2019-01-28T09:30:10+00:00"
}, },
{ {
"name": "composer/semver", "name": "composer/semver",

View File

@ -796,58 +796,40 @@ COMPOSER=composer-other.json php composer.phar install
The generated lock file will use the same name: `composer-other.lock` in this example. The generated lock file will use the same name: `composer-other.lock` in this example.
### COMPOSER_ROOT_VERSION ### COMPOSER_ALLOW_SUPERUSER
By setting this var you can specify the version of the root package, if it can If set to 1, this env disables the warning about running commands as root/super user.
not be guessed from VCS info and is not present in `composer.json`. It also disables automatic clearing of sudo sessions, so you should really only set this
if you use Composer as super user at all times like in docker containers.
### COMPOSER_VENDOR_DIR ### COMPOSER_AUTH
By setting this var you can make Composer install the dependencies into a The `COMPOSER_AUTH` var allows you to set up authentication as an environment variable.
directory other than `vendor`. The contents of the variable should be a JSON formatted object containing http-basic,
github-oauth, bitbucket-oauth, ... objects as needed, and following the
[spec from the config](06-config.md#gitlab-oauth).
### COMPOSER_BIN_DIR ### COMPOSER_BIN_DIR
By setting this option you can change the `bin` ([Vendor Binaries](articles/vendor-binaries.md)) By setting this option you can change the `bin` ([Vendor Binaries](articles/vendor-binaries.md))
directory to something other than `vendor/bin`. directory to something other than `vendor/bin`.
### http_proxy or HTTP_PROXY ### COMPOSER_CACHE_DIR
If you are using Composer from behind an HTTP proxy, you can use the standard The `COMPOSER_CACHE_DIR` var allows you to change the Composer cache directory,
`http_proxy` or `HTTP_PROXY` env vars. Simply set it to the URL of your proxy. which is also configurable via the [`cache-dir`](06-config.md#cache-dir) option.
Many operating systems already set this variable for you.
Using `http_proxy` (lowercased) or even defining both might be preferable since By default it points to `$COMPOSER_HOME/cache` on \*nix and macOS, and
some tools like git or curl will only use the lower-cased `http_proxy` version. `C:\Users\<user>\AppData\Local\Composer` (or `%LOCALAPPDATA%/Composer`) on Windows.
Alternatively you can also define the git proxy using
`git config --global http.proxy <proxy url>`.
If you are using Composer in a non-CLI context (i.e. integration into a CMS or ### COMPOSER_CAFILE
similar use case), and need to support proxies, please provide the `CGI_HTTP_PROXY`
environment variable instead. See [httpoxy.org](https://httpoxy.org/) for further
details.
### no_proxy or NO_PROXY By setting this environmental value, you can set a path to a certificate bundle
file to be used during SSL/TLS peer verification.
If you are behind a proxy and would like to disable it for certain domains, you ### COMPOSER_DISCARD_CHANGES
can use the `no_proxy` or `NO_PROXY` env var. Simply set it to a comma separated list of
domains the proxy should *not* be used for.
The env var accepts domains, IP addresses, and IP address blocks in CIDR This env var controls the [`discard-changes`](06-config.md#discard-changes) config option.
notation. You can restrict the filter to a particular port (e.g. `:80`). You
can also set it to `*` to ignore the proxy for all HTTP requests.
### HTTP_PROXY_REQUEST_FULLURI
If you use a proxy but it does not support the request_fulluri flag, then you
should set this env var to `false` or `0` to prevent Composer from setting the
request_fulluri option.
### HTTPS_PROXY_REQUEST_FULLURI
If you use a proxy but it does not support the request_fulluri flag for HTTPS
requests, then you should set this env var to `false` or `0` to prevent Composer
from setting the request_fulluri option.
### COMPOSER_HOME ### COMPOSER_HOME
@ -873,45 +855,10 @@ This file allows you to set [repositories](05-repositories.md) and
In case global configuration matches _local_ configuration, the _local_ In case global configuration matches _local_ configuration, the _local_
configuration in the project's `composer.json` always wins. configuration in the project's `composer.json` always wins.
### COMPOSER_CACHE_DIR ### COMPOSER_HTACCESS_PROTECT
The `COMPOSER_CACHE_DIR` var allows you to change the Composer cache directory, Defaults to `1`. If set to `0`, Composer will not create `.htaccess` files in the
which is also configurable via the [`cache-dir`](06-config.md#cache-dir) option. composer home, cache, and data directories.
By default it points to `$COMPOSER_HOME/cache` on \*nix and macOS, and
`C:\Users\<user>\AppData\Local\Composer` (or `%LOCALAPPDATA%/Composer`) on Windows.
### COMPOSER_PROCESS_TIMEOUT
This env var controls the time Composer waits for commands (such as git
commands) to finish executing. The default value is 300 seconds (5 minutes).
### COMPOSER_CAFILE
By setting this environmental value, you can set a path to a certificate bundle
file to be used during SSL/TLS peer verification.
### COMPOSER_AUTH
The `COMPOSER_AUTH` var allows you to set up authentication as an environment variable.
The contents of the variable should be a JSON formatted object containing http-basic,
github-oauth, bitbucket-oauth, ... objects as needed, and following the
[spec from the config](06-config.md#gitlab-oauth).
### COMPOSER_DISCARD_CHANGES
This env var controls the [`discard-changes`](06-config.md#discard-changes) config option.
### COMPOSER_NO_INTERACTION
If set to 1, this env var will make Composer behave as if you passed the
`--no-interaction` flag to every command. This can be set on build boxes/CI.
### COMPOSER_ALLOW_SUPERUSER
If set to 1, this env disables the warning about running commands as root/super user.
It also disables automatic clearing of sudo sessions, so you should really only set this
if you use Composer as super user at all times like in docker containers.
### COMPOSER_MEMORY_LIMIT ### COMPOSER_MEMORY_LIMIT
@ -923,10 +870,63 @@ If set to 1, this env changes the default path repository strategy to `mirror` i
of `symlink`. As it is the default strategy being set it can still be overwritten by of `symlink`. As it is the default strategy being set it can still be overwritten by
repository options. repository options.
### COMPOSER_HTACCESS_PROTECT ### COMPOSER_NO_INTERACTION
Defaults to `1`. If set to `0`, Composer will not create `.htaccess` files in the If set to 1, this env var will make Composer behave as if you passed the
composer home, cache, and data directories. `--no-interaction` flag to every command. This can be set on build boxes/CI.
### COMPOSER_PROCESS_TIMEOUT
This env var controls the time Composer waits for commands (such as git
commands) to finish executing. The default value is 300 seconds (5 minutes).
### COMPOSER_ROOT_VERSION
By setting this var you can specify the version of the root package, if it can
not be guessed from VCS info and is not present in `composer.json`.
### COMPOSER_VENDOR_DIR
By setting this var you can make Composer install the dependencies into a
directory other than `vendor`.
### http_proxy or HTTP_PROXY
If you are using Composer from behind an HTTP proxy, you can use the standard
`http_proxy` or `HTTP_PROXY` env vars. Simply set it to the URL of your proxy.
Many operating systems already set this variable for you.
Using `http_proxy` (lowercased) or even defining both might be preferable since
some tools like git or curl will only use the lower-cased `http_proxy` version.
Alternatively you can also define the git proxy using
`git config --global http.proxy <proxy url>`.
If you are using Composer in a non-CLI context (i.e. integration into a CMS or
similar use case), and need to support proxies, please provide the `CGI_HTTP_PROXY`
environment variable instead. See [httpoxy.org](https://httpoxy.org/) for further
details.
### HTTP_PROXY_REQUEST_FULLURI
If you use a proxy but it does not support the request_fulluri flag, then you
should set this env var to `false` or `0` to prevent Composer from setting the
request_fulluri option.
### HTTPS_PROXY_REQUEST_FULLURI
If you use a proxy but it does not support the request_fulluri flag for HTTPS
requests, then you should set this env var to `false` or `0` to prevent Composer
from setting the request_fulluri option.
### no_proxy or NO_PROXY
If you are behind a proxy and would like to disable it for certain domains, you
can use the `no_proxy` or `NO_PROXY` env var. Simply set it to a comma separated list of
domains the proxy should *not* be used for.
The env var accepts domains, IP addresses, and IP address blocks in CIDR
notation. You can restrict the filter to a particular port (e.g. `:80`). You
can also set it to `*` to ignore the proxy for all HTTP requests.
### COMPOSER_DISABLE_NETWORK ### COMPOSER_DISABLE_NETWORK

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false" <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false" backupStaticAttributes="false"
colors="true" colors="true"
convertErrorsToExceptions="true" convertErrorsToExceptions="true"
@ -8,7 +10,6 @@
convertWarningsToExceptions="true" convertWarningsToExceptions="true"
processIsolation="false" processIsolation="false"
stopOnFailure="false" stopOnFailure="false"
syntaxCheck="false"
bootstrap="tests/bootstrap.php" bootstrap="tests/bootstrap.php"
> >
<testsuites> <testsuites>

View File

@ -48,6 +48,7 @@ class RunScriptCommand extends BaseCommand
{ {
$this $this
->setName('run-script') ->setName('run-script')
->setAliases(array('run'))
->setDescription('Runs the scripts defined in composer.json.') ->setDescription('Runs the scripts defined in composer.json.')
->setDefinition(array( ->setDefinition(array(
new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'), new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),

View File

@ -216,7 +216,6 @@ class Config
case 'cache-vcs-dir': case 'cache-vcs-dir':
case 'cafile': case 'cafile':
case 'capath': case 'capath':
case 'htaccess-protect':
// convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config // convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config
$env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_')); $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
@ -230,6 +229,13 @@ class Config
return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val); return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
case 'htaccess-protect':
$value = $this->getComposerEnv('COMPOSER_HTACCESS_PROTECT');
if (false === $value) {
$value = $this->config[$key];
}
return $value !== 'false' && (bool) $value;
case 'cache-ttl': case 'cache-ttl':
return (int) $this->config[$key]; return (int) $this->config[$key];

View File

@ -17,6 +17,8 @@ use Composer\Util\Platform;
use Composer\Util\Silencer; use Composer\Util\Silencer;
use Symfony\Component\Console\Application as BaseApplication; use Symfony\Component\Console\Application as BaseApplication;
use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\Console\Exception\CommandNotFoundException;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
@ -111,7 +113,9 @@ class Application extends BaseApplication
{ {
$this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins'); $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
$io = $this->io = new ConsoleIO($input, $output, $this->getHelperSet()); $io = $this->io = new ConsoleIO($input, $output, new HelperSet(array(
new QuestionHelper(),
)));
ErrorHandler::register($io); ErrorHandler::register($io);
// switch working dir // switch working dir

View File

@ -244,6 +244,12 @@ class EventDispatcher
if (substr($exec, 0, 5) === '@php ') { if (substr($exec, 0, 5) === '@php ') {
$exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5); $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
} else {
$finder = new PhpExecutableFinder();
$phpPath = $finder->find(false);
if ($phpPath) {
putenv('PHP_BINARY=' . $phpPath);
}
} }
if (0 !== ($exitCode = $this->process->execute($exec))) { if (0 !== ($exitCode = $this->process->execute($exec))) {

View File

@ -165,6 +165,16 @@ class Factory
'data-dir' => self::getDataDir($home), 'data-dir' => self::getDataDir($home),
))); )));
// load global config
$file = new JsonFile($config->get('home').'/config.json');
if ($file->exists()) {
if ($io && $io->isDebug()) {
$io->writeError('Loading config file ' . $file->getPath());
}
$config->merge($file->read());
}
$config->setConfigSource(new JsonConfigSource($file));
$htaccessProtect = (bool) $config->get('htaccess-protect'); $htaccessProtect = (bool) $config->get('htaccess-protect');
if ($htaccessProtect) { if ($htaccessProtect) {
// Protect directory against web access. Since HOME could be // Protect directory against web access. Since HOME could be
@ -181,16 +191,6 @@ class Factory
} }
} }
// load global config
$file = new JsonFile($config->get('home').'/config.json');
if ($file->exists()) {
if ($io && $io->isDebug()) {
$io->writeError('Loading config file ' . $file->getPath());
}
$config->merge($file->read());
}
$config->setConfigSource(new JsonConfigSource($file));
// load global auth file // load global auth file
$file = new JsonFile($config->get('home').'/auth.json'); $file = new JsonFile($config->get('home').'/auth.json');
if ($file->exists()) { if ($file->exists()) {

View File

@ -12,8 +12,10 @@
namespace Composer\IO; namespace Composer\IO;
use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Output\StreamOutput;
use Symfony\Component\Console\Formatter\OutputFormatterInterface; use Symfony\Component\Console\Formatter\OutputFormatterInterface;
use Symfony\Component\Console\Input\StreamableInputInterface;
use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Helper\HelperSet;
@ -34,7 +36,9 @@ class BufferIO extends ConsoleIO
$output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter); $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
parent::__construct($input, $output, new HelperSet(array())); parent::__construct($input, $output, new HelperSet(array(
new QuestionHelper(),
)));
} }
public function getOutput() public function getOutput()
@ -56,4 +60,27 @@ class BufferIO extends ConsoleIO
return $output; return $output;
} }
public function setUserInputs(array $inputs)
{
if (!$this->input instanceof StreamableInputInterface) {
throw new \RuntimeException('Setting the user inputs requires at least the version 3.2 of the symfony/console component.');
}
$this->input->setStream($this->createStream($inputs));
$this->input->setInteractive(true);
}
private function createStream(array $inputs)
{
$stream = fopen('php://memory', 'r+', false);
foreach ($inputs as $input) {
fwrite($stream, $input.PHP_EOL);
}
rewind($stream);
return $stream;
}
} }

View File

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

View File

@ -34,6 +34,8 @@ class JsonFile
const JSON_PRETTY_PRINT = 128; const JSON_PRETTY_PRINT = 128;
const JSON_UNESCAPED_UNICODE = 256; const JSON_UNESCAPED_UNICODE = 256;
const COMPOSER_SCHEMA_PATH = '/../../../res/composer-schema.json';
private $path; private $path;
private $httpDownloader; private $httpDownloader;
private $io; private $io;
@ -144,10 +146,11 @@ class JsonFile
* Validates the schema of the current json file according to composer-schema.json rules * Validates the schema of the current json file according to composer-schema.json rules
* *
* @param int $schema a JsonFile::*_SCHEMA constant * @param int $schema a JsonFile::*_SCHEMA constant
* @param string|null $schemaFile a path to the schema file
* @throws JsonValidationException * @throws JsonValidationException
* @return bool true on success * @return bool true on success
*/ */
public function validateSchema($schema = self::STRICT_SCHEMA) public function validateSchema($schema = self::STRICT_SCHEMA, $schemaFile = null)
{ {
$content = file_get_contents($this->path); $content = file_get_contents($this->path);
$data = json_decode($content); $data = json_decode($content);
@ -156,7 +159,9 @@ class JsonFile
self::validateSyntax($content, $this->path); self::validateSyntax($content, $this->path);
} }
$schemaFile = __DIR__ . '/../../../res/composer-schema.json'; if (null === $schemaFile) {
$schemaFile = __DIR__ . self::COMPOSER_SCHEMA_PATH;
}
// Prepend with file:// only when not using a special schema already (e.g. in the phar) // Prepend with file:// only when not using a special schema already (e.g. in the phar)
if (false === strpos($schemaFile, '://')) { if (false === strpos($schemaFile, '://')) {

View File

@ -150,10 +150,15 @@ class ArchiveManager
$sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid(); $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
$filesystem->ensureDirectoryExists($sourcePath); $filesystem->ensureDirectoryExists($sourcePath);
try {
// Download sources // Download sources
$promise = $this->downloadManager->download($package, $sourcePath); $promise = $this->downloadManager->download($package, $sourcePath);
$this->loop->wait(array($promise)); $this->loop->wait(array($promise));
$this->downloadManager->install($package, $sourcePath); $this->downloadManager->install($package, $sourcePath);
} catch (\Exception $e) {
$filesystem->removeDirectory($sourcePath);
throw $e;
}
// Check exclude from downloaded composer.json // Check exclude from downloaded composer.json
if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) { if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {

View File

@ -0,0 +1,43 @@
<?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\IO;
use Composer\IO\BufferIO;
use Composer\Test\TestCase;
use Symfony\Component\Console\Input\StreamableInputInterface;
class BufferIOTest extends TestCase
{
public function testSetUserInputs()
{
$bufferIO = new BufferIO();
$refl = new \ReflectionProperty($bufferIO, 'input');
$refl->setAccessible(true);
$input = $refl->getValue($bufferIO);
if (!$input instanceof StreamableInputInterface) {
$this->setExpectedException('\RuntimeException', 'Setting the user inputs requires at least the version 3.2 of the symfony/console component.');
}
$bufferIO->setUserInputs(array(
'yes',
'no',
'',
));
$this->assertTrue($bufferIO->askConfirmation('Please say yes!', 'no'));
$this->assertFalse($bufferIO->askConfirmation('Now please say no!', 'yes'));
$this->assertSame('default', $bufferIO->ask('Empty string last', 'default'));
}
}