Browse Source

Merge branch '1.7'

Jordi Boggiano 6 years ago
parent
commit
2528654c53

+ 5 - 5
composer.lock

@@ -8,16 +8,16 @@
     "packages": [
         {
             "name": "composer/ca-bundle",
-            "version": "1.1.2",
+            "version": "1.1.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/composer/ca-bundle.git",
-                "reference": "46afded9720f40b9dc63542af4e3e43a1177acb0"
+                "reference": "8afa52cd417f4ec417b4bfe86b68106538a87660"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/composer/ca-bundle/zipball/46afded9720f40b9dc63542af4e3e43a1177acb0",
-                "reference": "46afded9720f40b9dc63542af4e3e43a1177acb0",
+                "url": "https://api.github.com/repos/composer/ca-bundle/zipball/8afa52cd417f4ec417b4bfe86b68106538a87660",
+                "reference": "8afa52cd417f4ec417b4bfe86b68106538a87660",
                 "shasum": ""
             },
             "require": {
@@ -60,7 +60,7 @@
                 "ssl",
                 "tls"
             ],
-            "time": "2018-08-08T08:57:40+00:00"
+            "time": "2018-10-18T06:09:13+00:00"
         },
         {
             "name": "composer/semver",

+ 2 - 2
doc/03-cli.md

@@ -856,9 +856,9 @@ is a hidden, global (per-user on the machine) directory that is shared between
 all projects.
 
 By default it points to `C:\Users\<user>\AppData\Roaming\Composer` on Windows
-and `/Users/<user>/.composer` on macOS. On *nix systems that follow the [XDG Base
+and `/Users/<user>/.composer` on macOS. On \*nix systems that follow the [XDG Base
 Directory Specifications](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html),
-it points to `$XDG_CONFIG_HOME/composer`. On other *nix systems, it points to
+it points to `$XDG_CONFIG_HOME/composer`. On other \*nix systems, it points to
 `/home/<user>/.composer`.
 
 #### COMPOSER_HOME/config.json

+ 1 - 1
src/Composer/Autoload/ClassLoader.php

@@ -279,7 +279,7 @@ class ClassLoader
      */
     public function setApcuPrefix($apcuPrefix)
     {
-        $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
+        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
     }
 
     /**

+ 3 - 3
src/Composer/Command/DiagnoseCommand.php

@@ -522,7 +522,7 @@ EOT
             $errors['iconv_mbstring'] = true;
         }
 
-        if (!ini_get('allow_url_fopen')) {
+        if (!filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN)) {
             $errors['allow_url_fopen'] = true;
         }
 
@@ -546,7 +546,7 @@ EOT
             $warnings['openssl_version'] = true;
         }
 
-        if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) {
+        if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN)) {
             $warnings['apc_cli'] = true;
         }
 
@@ -569,7 +569,7 @@ EOT
             }
         }
 
-        if (ini_get('xdebug.profiler_enabled')) {
+        if (filter_var(ini_get('xdebug.profiler_enabled'), FILTER_VALIDATE_BOOLEAN)) {
             $warnings['xdebug_profile'] = true;
         } elseif (extension_loaded('xdebug')) {
             $warnings['xdebug_loaded'] = true;

+ 1 - 1
src/Composer/Command/SelfUpdateCommand.php

@@ -220,7 +220,7 @@ TAGSPUBKEY
 
             $pubkeyid = openssl_pkey_get_public($sigFile);
             $algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384';
-            if (!in_array('SHA384', openssl_get_md_methods())) {
+            if (!in_array('sha384', array_map('strtolower', openssl_get_md_methods()))) {
                 throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
             }
             $signature = json_decode($signature, true);

+ 9 - 0
src/Composer/Command/ShowCommand.php

@@ -222,6 +222,12 @@ EOT
                 if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
                     $exitCode = 1;
                 }
+                if ($input->getOption('path')) {
+                    $io->write($package->getName(), false);
+                    $io->write(' ' . strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n"));
+
+                    return $exitCode;
+                }
                 $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
                 $this->printLinks($package, 'requires');
                 $this->printLinks($package, 'devRequires', 'requires (dev)');
@@ -585,6 +591,9 @@ EOT
         $this->printLicenses($package);
         $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
         $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
+        if ($installedRepo->hasPackage($package)) {
+            $io->write('<info>path</info>     : ' . sprintf('%s', realpath($this->getComposer()->getInstallationManager()->getInstallPath($package))));
+        }
         $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
 
         if ($latestPackage->isAbandoned()) {

+ 1 - 1
src/Composer/Compiler.php

@@ -255,7 +255,7 @@ class Compiler
  */
 
 // Avoid APC causing random fatal errors per https://github.com/composer/composer/issues/264
-if (extension_loaded('apc') && ini_get('apc.enable_cli') && ini_get('apc.cache_by_default')) {
+if (extension_loaded('apc') && filter_var(ini_get('apc.enable_cli'), FILTER_VALIDATE_BOOLEAN) && filter_var(ini_get('apc.cache_by_default'), FILTER_VALIDATE_BOOLEAN)) {
     if (version_compare(phpversion('apc'), '3.0.12', '>=')) {
         ini_set('apc.cache_by_default', 0);
     } else {

+ 2 - 1
src/Composer/Downloader/ZipDownloader.php

@@ -69,7 +69,8 @@ class ZipDownloader extends ArchiveDownloader
 
             if (!self::$isWindows && !self::$hasSystemUnzip) {
                 $this->io->writeError("<warning>As there is no 'unzip' command installed zip files are being unpacked using the PHP zip extension.</warning>");
-                $this->io->writeError("<warning>This may cause invalid reports of corrupted archives. Installing 'unzip' may remediate them.</warning>");
+                $this->io->writeError("<warning>This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.</warning>");
+                $this->io->writeError("<warning>Installing 'unzip' may remediate them.</warning>");
             }
         }
 

+ 3 - 1
src/Composer/Repository/ArtifactRepository.php

@@ -126,7 +126,9 @@ class ArtifactRepository extends ArrayRepository implements ConfigurableReposito
     private function getComposerInformation(\SplFileInfo $file)
     {
         $zip = new \ZipArchive();
-        $zip->open($file->getPathname());
+        if ($zip->open($file->getPathname()) !== true) {
+            return false;
+        }
 
         if (0 == $zip->numFiles) {
             $zip->close();

+ 12 - 2
src/Composer/Repository/PlatformRepository.php

@@ -236,7 +236,12 @@ class PlatformRepository extends ArrayRepository
         // Skip if overridden
         if (isset($this->overrides[$package->getName()])) {
             $overrider = $this->findPackage($package->getName(), '*');
-            $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
+            if ($package->getVersion() === $overrider->getVersion()) {
+                $actualText = 'same as actual';
+            } else {
+                $actualText = 'actual: '.$package->getPrettyVersion();
+            }
+            $overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
 
             return;
         }
@@ -244,7 +249,12 @@ class PlatformRepository extends ArrayRepository
         // Skip if PHP is overridden and we are adding a php-* package
         if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
             $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
-            $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
+            if ($package->getVersion() === $overrider->getVersion()) {
+                $actualText = 'same as actual';
+            } else {
+                $actualText = 'actual: '.$package->getPrettyVersion();
+            }
+            $overrider->setDescription($overrider->getDescription().' ('.$actualText.')');
 
             return;
         }

+ 8 - 3
src/Composer/Repository/Vcs/BitbucketDriver.php

@@ -197,7 +197,7 @@ abstract class BitbucketDriver extends VcsDriver
         }
 
         $resource = sprintf(
-            'https://api.bitbucket.org/1.0/repositories/%s/%s/raw/%s/%s',
+            'https://api.bitbucket.org/2.0/repositories/%s/%s/src/%s/%s',
             $this->owner,
             $this->repository,
             $identifier,
@@ -428,11 +428,16 @@ abstract class BitbucketDriver extends VcsDriver
     protected function getMainBranchData()
     {
         $resource = sprintf(
-            'https://api.bitbucket.org/1.0/repositories/%s/%s/main-branch',
+            'https://api.bitbucket.org/2.0/repositories/%s/%s?fields=mainbranch',
             $this->owner,
             $this->repository
         );
 
-        return JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
+        $data = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
+        if (isset($data['mainbranch'])) {
+            return $data['mainbranch'];
+        }
+
+        return null;
     }
 }

+ 61 - 12
src/Composer/Repository/VcsRepository.php

@@ -41,8 +41,10 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
     private $drivers;
     /** @var VcsDriverInterface */
     private $driver;
+    /** @var VersionCacheInterface */
+    private $versionCache;
 
-    public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null)
+    public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null, VersionCacheInterface $versionCache = null)
     {
         parent::__construct();
         $this->drivers = $drivers ?: array(
@@ -64,6 +66,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
         $this->verbose = $io->isVeryVerbose();
         $this->config = $config;
         $this->repoConfig = $repoConfig;
+        $this->versionCache = $versionCache;
     }
 
     public function getRepoConfig()
@@ -152,6 +155,13 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
             // strip the release- prefix from tags if present
             $tag = str_replace('release-', '', $tag);
 
+            $cachedPackage = $this->getCachedPackageVersion($tag, $identifier, $verbose);
+            if ($cachedPackage) {
+                $this->addPackage($cachedPackage);
+
+                continue;
+            }
+
             if (!$parsedTag = $this->validateTag($tag)) {
                 if ($verbose) {
                     $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
@@ -188,7 +198,8 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
                     continue;
                 }
 
-                if ($existingPackage = $this->findPackage($data['name'], $data['version_normalized'])) {
+                $tagPackageName = isset($data['name']) ? $data['name'] : $this->packageName;
+                if ($existingPackage = $this->findPackage($tagPackageName, $data['version_normalized'])) {
                     if ($verbose) {
                         $this->io->writeError('<warning>Skipped tag '.$tag.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$data['version_normalized'].' internally</warning>');
                     }
@@ -235,6 +246,21 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
                 continue;
             }
 
+            // make sure branch packages have a dev flag
+            if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
+                $version = 'dev-' . $branch;
+            } else {
+                $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
+                $version = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
+            }
+
+            $cachedPackage = $this->getCachedPackageVersion($version, $identifier, $verbose);
+            if ($cachedPackage) {
+                $this->addPackage($cachedPackage);
+
+                continue;
+            }
+
             try {
                 if (!$data = $driver->getComposerInformation($identifier)) {
                     if ($verbose) {
@@ -244,17 +270,9 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
                 }
 
                 // branches are always auto-versioned, read value from branch name
-                $data['version'] = $branch;
+                $data['version'] = $version;
                 $data['version_normalized'] = $parsedBranch;
 
-                // make sure branch packages have a dev flag
-                if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
-                    $data['version'] = 'dev-' . $data['version'];
-                } else {
-                    $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
-                    $data['version'] = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
-                }
-
                 if ($verbose) {
                     $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
                 }
@@ -294,7 +312,8 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
     protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
     {
         // keep the name of the main identifier for all packages
-        $data['name'] = $this->packageName ?: $data['name'];
+        $dataPackageName = isset($data['name']) ? $data['name'] : null;
+        $data['name'] = $this->packageName ?: $dataPackageName;
 
         if (!isset($data['dist'])) {
             $data['dist'] = $driver->getDist($identifier);
@@ -325,4 +344,34 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt
 
         return false;
     }
+
+    private function getCachedPackageVersion($version, $identifier, $verbose)
+    {
+        if (!$this->versionCache) {
+            return;
+        }
+
+        $cachedPackage = $this->versionCache->getVersionPackage($version, $identifier);
+        if ($cachedPackage) {
+            $msg = 'Found cached composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $version . '</comment>)';
+            if ($verbose) {
+                $this->io->writeError($msg);
+            } else {
+                $this->io->overwriteError($msg, false);
+            }
+
+            if ($existingPackage = $this->findPackage($cachedPackage['name'], $cachedPackage['version_normalized'])) {
+                if ($verbose) {
+                    $this->io->writeError('<warning>Skipped cached version '.$version.', it conflicts with an another tag ('.$existingPackage->getPrettyVersion().') as both resolve to '.$cachedPackage['version_normalized'].' internally</warning>');
+                }
+                $cachedPackage = null;
+            }
+        }
+
+        if ($cachedPackage) {
+            return $this->loader->load($cachedPackage);
+        }
+
+        return null;
+    }
 }

+ 23 - 0
src/Composer/Repository/VersionCacheInterface.php

@@ -0,0 +1,23 @@
+<?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\Repository;
+
+interface VersionCacheInterface
+{
+    /**
+     * @param string $version
+     * @param string $identifier
+     * @return array Package version data
+     */
+    public function getVersionPackage($version, $identifier);
+}

+ 1 - 1
src/Composer/Util/ErrorHandler.php

@@ -41,7 +41,7 @@ class ErrorHandler
             return;
         }
 
-        if (ini_get('xdebug.scream')) {
+        if (filter_var(ini_get('xdebug.scream'), FILTER_VALIDATE_BOOLEAN)) {
             $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
             "\na legitimately suppressed error that you were not supposed to see.";
         }

+ 1 - 5
src/Composer/Util/ProcessExecutor.php

@@ -131,15 +131,11 @@ class ProcessExecutor
      */
     public static function escape($argument)
     {
-        if (method_exists('Symfony\Component\Process\ProcessUtils', 'escapeArgument')) {
-            return ProcessUtils::escapeArgument($argument);
-        }
-
         return self::escapeArgument($argument);
     }
 
     /**
-     * Copy of ProcessUtils::escapeArgument() that is removed in Symfony 4.
+     * Copy of ProcessUtils::escapeArgument() that is deprecated in Symfony 3.3 and removed in Symfony 4.
      *
      * @param string $argument
      *

+ 4 - 1
src/Composer/Util/RemoteFilesystem.php

@@ -369,7 +369,7 @@ class RemoteFilesystem
             }
             $result = false;
         }
-        if ($errorMessage && !ini_get('allow_url_fopen')) {
+        if ($errorMessage && !filter_var(ini_get('allow_url_fopen'), FILTER_VALIDATE_BOOLEAN)) {
             $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
         }
         restore_error_handler();
@@ -390,15 +390,18 @@ class RemoteFilesystem
 
         $statusCode = null;
         $contentType = null;
+        $locationHeader = null;
         if (!empty($http_response_header[0])) {
             $statusCode = $this->findStatusCode($http_response_header);
             $contentType = $this->findHeaderValue($http_response_header, 'content-type');
+            $locationHeader = $this->findHeaderValue($http_response_header, 'location');
         }
 
         // check for bitbucket login page asking to authenticate
         if ($originUrl === 'bitbucket.org'
             && !$this->isPublicBitBucketDownload($fileUrl)
             && substr($fileUrl, -4) === '.zip'
+            && (!$locationHeader || substr($locationHeader, -4) !== '.zip')
             && $contentType && preg_match('{^text/html\b}i', $contentType)
         ) {
             $result = false;

BIN
tests/Composer/Test/Repository/Fixtures/artifacts/not-a-zip-with-zip-extension.zip


+ 3 - 3
tests/Composer/Test/Repository/Vcs/GitBitbucketDriverTest.php

@@ -113,7 +113,7 @@ class GitBitbucketDriverTest extends TestCase
                 ),
                 array(
                     $this->originUrl,
-                    'https://api.bitbucket.org/1.0/repositories/user/repo/main-branch',
+                    'https://api.bitbucket.org/2.0/repositories/user/repo?fields=mainbranch',
                     false,
                 ),
                 array(
@@ -128,7 +128,7 @@ class GitBitbucketDriverTest extends TestCase
                 ),
                 array(
                     $this->originUrl,
-                    'https://api.bitbucket.org/1.0/repositories/user/repo/raw/master/composer.json',
+                    'https://api.bitbucket.org/2.0/repositories/user/repo/src/master/composer.json',
                     false,
                 ),
                 array(
@@ -139,7 +139,7 @@ class GitBitbucketDriverTest extends TestCase
             )
             ->willReturnOnConsecutiveCalls(
                 '{"scm":"git","website":"","has_wiki":false,"name":"repo","links":{"branches":{"href":"https:\/\/api.bitbucket.org\/2.0\/repositories\/user\/repo\/refs\/branches"},"tags":{"href":"https:\/\/api.bitbucket.org\/2.0\/repositories\/user\/repo\/refs\/tags"},"clone":[{"href":"https:\/\/user@bitbucket.org\/user\/repo.git","name":"https"},{"href":"ssh:\/\/git@bitbucket.org\/user\/repo.git","name":"ssh"}],"html":{"href":"https:\/\/bitbucket.org\/user\/repo"}},"language":"php","created_on":"2015-02-18T16:22:24.688+00:00","updated_on":"2016-05-17T13:20:21.993+00:00","is_private":true,"has_issues":false}',
-                '{"name": "master"}',
+                '{"mainbranch": {"name": "master"}}',
                 '{"values":[{"name":"1.0.1","target":{"hash":"9b78a3932143497c519e49b8241083838c8ff8a1"}},{"name":"1.0.0","target":{"hash":"d3393d514318a9267d2f8ebbf463a9aaa389f8eb"}}]}',
                 '{"values":[{"name":"master","target":{"hash":"937992d19d72b5116c3e8c4a04f960e5fa270b22"}}]}',
                 '{"name": "user/repo","description": "test repo","license": "GPL","authors": [{"name": "Name","email": "local@domain.tld"}],"require": {"creator/package": "^1.0"},"require-dev": {"phpunit/phpunit": "~4.8"}}',