Эх сурвалжийг харах

Merge branch 'master' into 2.0

Jordi Boggiano 6 жил өмнө
parent
commit
0b928b2a42

+ 11 - 0
.editorconfig

@@ -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

+ 28 - 31
.travis.yml

@@ -1,7 +1,5 @@
 language: php
 language: php
 
 
-sudo: false
-
 dist: trusty
 dist: trusty
 
 
 git:
 git:
@@ -16,54 +14,53 @@ 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
 
 
 before_install:
 before_install:
-    # disable xdebug if available
-    - phpenv config-rm xdebug.ini || echo "xdebug not available"
-    # disable default memory limit
-    - export INI=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
-    - echo memory_limit = -1 >> $INI
+  # disable xdebug if available
+  - phpenv config-rm xdebug.ini || echo "xdebug not available"
+  # disable default memory limit
+  - export INI=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
+  - echo memory_limit = -1 >> $INI
+  - composer validate
 
 
 install:
 install:
-    # flags to pass to install
-    - flags="--ansi --prefer-dist --no-interaction --optimize-autoloader --no-suggest --no-progress"
-    # update deps to latest in case of high deps build
-    - if [ "$deps" == "high" ]; then composer config platform.php 7.2.4; composer update $flags; fi
-    # install dependencies using system provided composer binary
-    - composer install $flags
-    # install dependencies using composer from source
-    - bin/composer install $flags
+  # flags to pass to install
+  - flags="--ansi --prefer-dist --no-interaction --optimize-autoloader --no-suggest --no-progress"
+  # update deps to latest in case of high deps build
+  - if [ "$deps" == "high" ]; then composer config platform.php 7.2.4; composer update $flags; fi
+  # install dependencies using system provided composer binary
+  - composer install $flags
+  # install dependencies using composer from source
+  - bin/composer install $flags
 
 
 before_script:
 before_script:
-    # make sure git tests do not complain about user/email not being set
-    - git config --global user.name travis-ci
-    - git config --global user.email travis@example.com
+  # make sure git tests do not complain about user/email not being set
+  - git config --global user.name travis-ci
+  - git config --global user.email travis@example.com
 
 
 script:
 script:
-    # run test suite directories in parallel using GNU parallel
-    - ls -d tests/Composer/Test/* | grep -v TestCase.php | parallel --gnu --keep-order 'echo "Running {} tests"; ./vendor/bin/phpunit -c tests/complete.phpunit.xml --colors=always {} || (echo -e "\e[41mFAILED\e[0m {}" && exit 1);'
+  # run test suite directories in parallel using GNU parallel
+  - ls -d tests/Composer/Test/* | grep -v TestCase.php | parallel --gnu --keep-order 'echo "Running {} tests"; ./vendor/bin/phpunit -c tests/complete.phpunit.xml --colors=always {} || (echo -e "\e[41mFAILED\e[0m {}" && exit 1);'
 
 
 before_deploy:
 before_deploy:
-    - php -d phar.readonly=0 bin/compile
+  - php -d phar.readonly=0 bin/compile
 
 
 deploy:
 deploy:
   provider: releases
   provider: releases

+ 5 - 0
composer.json

@@ -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"

+ 5 - 5
composer.lock

@@ -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",
-                "reference": "8afa52cd417f4ec417b4bfe86b68106538a87660",
+                "url": "https://api.github.com/repos/composer/ca-bundle/zipball/558f321c52faeb4828c03e7dc0cfe39a09e09a2d",
+                "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",

+ 69 - 69
doc/03-cli.md

@@ -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
-not be guessed from VCS info and is not present in `composer.json`.
+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_VENDOR_DIR
+### COMPOSER_AUTH
 
 
-By setting this var you can make Composer install the dependencies into a
-directory other than `vendor`.
+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_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
-
-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.
-
-### no_proxy or NO_PROXY
+### COMPOSER_CACHE_DIR
 
 
-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 `COMPOSER_CACHE_DIR` var allows you to change the Composer cache directory,
+which is also configurable via the [`cache-dir`](06-config.md#cache-dir) option.
 
 
-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.
+By default it points to `$COMPOSER_HOME/cache` on \*nix and macOS, and
+`C:\Users\<user>\AppData\Local\Composer` (or `%LOCALAPPDATA%/Composer`) on Windows.
 
 
-### HTTP_PROXY_REQUEST_FULLURI
+### COMPOSER_CAFILE
 
 
-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.
+By setting this environmental value, you can set a path to a certificate bundle
+file to be used during SSL/TLS peer verification.
 
 
-### HTTPS_PROXY_REQUEST_FULLURI
+### COMPOSER_DISCARD_CHANGES
 
 
-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.
+This env var controls the [`discard-changes`](06-config.md#discard-changes) config option.
 
 
 ### COMPOSER_HOME
 ### COMPOSER_HOME
 
 
@@ -873,60 +855,78 @@ 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,
-which is also configurable via the [`cache-dir`](06-config.md#cache-dir) option.
+Defaults to `1`. If set to `0`, Composer will not create `.htaccess` files in the
+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_MEMORY_LIMIT
+
+If set, the value is used as php's memory_limit.
+
+### COMPOSER_MIRROR_PATH_REPOS
+
+If set to 1, this env changes the default path repository strategy to `mirror` instead
+of `symlink`. As it is the default strategy being set it can still be overwritten by
+repository options.
+
+### 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_PROCESS_TIMEOUT
 ### COMPOSER_PROCESS_TIMEOUT
 
 
 This env var controls the time Composer waits for commands (such as git
 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).
 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_ROOT_VERSION
 
 
-### COMPOSER_AUTH
+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`.
 
 
-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_VENDOR_DIR
 
 
-### COMPOSER_DISCARD_CHANGES
+By setting this var you can make Composer install the dependencies into a
+directory other than `vendor`.
 
 
-This env var controls the [`discard-changes`](06-config.md#discard-changes) config option.
+### http_proxy or HTTP_PROXY
 
 
-### COMPOSER_NO_INTERACTION
+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.
 
 
-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.
+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>`.
 
 
-### COMPOSER_ALLOW_SUPERUSER
+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.
 
 
-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.
+### HTTP_PROXY_REQUEST_FULLURI
 
 
-### COMPOSER_MEMORY_LIMIT
+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.
 
 
-If set, the value is used as php's memory_limit.
+### HTTPS_PROXY_REQUEST_FULLURI
 
 
-### COMPOSER_MIRROR_PATH_REPOS
+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.
 
 
-If set to 1, this env changes the default path repository strategy to `mirror` instead
-of `symlink`. As it is the default strategy being set it can still be overwritten by
-repository options.
+### no_proxy or NO_PROXY
 
 
-### COMPOSER_HTACCESS_PROTECT
+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.
 
 
-Defaults to `1`. If set to `0`, Composer will not create `.htaccess` files in the
-composer home, cache, and data directories.
+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
 
 

+ 3 - 2
phpunit.xml.dist

@@ -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>

+ 1 - 0
src/Composer/Command/RunScriptCommand.php

@@ -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.'),

+ 7 - 1
src/Composer/Config.php

@@ -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];
 
 

+ 5 - 1
src/Composer/Console/Application.php

@@ -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

+ 6 - 0
src/Composer/EventDispatcher/EventDispatcher.php

@@ -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))) {

+ 10 - 10
src/Composer/Factory.php

@@ -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()) {

+ 28 - 1
src/Composer/IO/BufferIO.php

@@ -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;
+    }
 }
 }

+ 1 - 1
src/Composer/Installer/BinaryInstaller.php

@@ -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
 
 

+ 7 - 2
src/Composer/Json/JsonFile.php

@@ -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, '://')) {

+ 9 - 4
src/Composer/Package/Archiver/ArchiveManager.php

@@ -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);
 
 
-            // Download sources
-            $promise = $this->downloadManager->download($package, $sourcePath);
-            $this->loop->wait(array($promise));
-            $this->downloadManager->install($package, $sourcePath);
+            try {
+                // Download sources
+                $promise = $this->downloadManager->download($package, $sourcePath);
+                $this->loop->wait(array($promise));
+                $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')) {

+ 43 - 0
tests/Composer/Test/IO/BufferIOTest.php

@@ -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'));
+    }
+}