1
0
Fork 0

Read first from $_SERVER and $_ENV before using getenv (#10218)

pull/10248/head
Jordi Boggiano 2021-11-09 16:31:27 +01:00 committed by GitHub
parent 1900f0e6e0
commit bd4d624cc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 90 additions and 63 deletions

View File

@ -14,6 +14,7 @@ namespace Composer;
use Composer\IO\IOInterface; use Composer\IO\IOInterface;
use Composer\Util\Filesystem; use Composer\Util\Filesystem;
use Composer\Util\Platform;
use Composer\Util\Silencer; use Composer\Util\Silencer;
use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\Finder;
@ -242,7 +243,7 @@ class Cache
} }
self::$cacheCollected = true; self::$cacheCollected = true;
if (getenv('COMPOSER_TEST_SUITE')) { if (Platform::getEnv('COMPOSER_TEST_SUITE')) {
return false; return false;
} }

View File

@ -213,7 +213,7 @@ EOT
{ {
// Open file in editor // Open file in editor
if ($input->getOption('editor')) { if ($input->getOption('editor')) {
$editor = escapeshellcmd(getenv('EDITOR')); $editor = escapeshellcmd(Platform::getEnv('EDITOR'));
if (!$editor) { if (!$editor) {
if (Platform::isWindows()) { if (Platform::isWindows()) {
$editor = 'notepad'; $editor = 'notepad';

View File

@ -88,7 +88,7 @@ EOT
} }
// The COMPOSER env var should not apply to the global execution scope // The COMPOSER env var should not apply to the global execution scope
if (getenv('COMPOSER')) { if (Platform::getEnv('COMPOSER')) {
Platform::clearEnv('COMPOSER'); Platform::clearEnv('COMPOSER');
} }

View File

@ -330,7 +330,7 @@ class Config
return (int) $this->config['cache-ttl']; return (int) $this->config['cache-ttl'];
case 'home': case 'home':
$val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $this->config[$key]); $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(Platform::getEnv('HOME') ?: Platform::getEnv('USERPROFILE'), '/\\') . '/', $this->config[$key]);
return rtrim($this->process($val, $flags), '/\\'); return rtrim($this->process($val, $flags), '/\\');
@ -462,7 +462,7 @@ class Config
return $path; return $path;
} }
return $this->baseDir . '/' . $path; return $this->baseDir ? $this->baseDir . '/' . $path : $path;
} }
/** /**
@ -477,7 +477,7 @@ class Config
private function getComposerEnv($var) private function getComposerEnv($var)
{ {
if ($this->useEnvironment) { if ($this->useEnvironment) {
return getenv($var); return Platform::getEnv($var);
} }
return false; return false;

View File

@ -135,7 +135,7 @@ class Application extends BaseApplication
{ {
$this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins'); $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
if (getenv('COMPOSER_NO_INTERACTION') || !Platform::isTty(defined('STDIN') ? STDIN : fopen('php://stdin', 'r'))) { if (Platform::getEnv('COMPOSER_NO_INTERACTION') || !Platform::isTty(defined('STDIN') ? STDIN : fopen('php://stdin', 'r'))) {
$input->setInteractive(false); $input->setInteractive(false);
} }
@ -174,7 +174,7 @@ class Application extends BaseApplication
// prompt user for dir change if no composer.json is present in current dir // prompt user for dir change if no composer.json is present in current dir
if ($io->isInteractive() && !$newWorkDir && !in_array($commandName, array('', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project', 'outdated'), true) && !file_exists(Factory::getComposerFile())) { if ($io->isInteractive() && !$newWorkDir && !in_array($commandName, array('', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project', 'outdated'), true) && !file_exists(Factory::getComposerFile())) {
$dir = dirname(getcwd()); $dir = dirname(getcwd());
$home = realpath(getenv('HOME') ?: getenv('USERPROFILE') ?: '/'); $home = realpath(Platform::getEnv('HOME') ?: Platform::getEnv('USERPROFILE') ?: '/');
// abort when we reach the home dir or top of the filesystem // abort when we reach the home dir or top of the filesystem
while (dirname($dir) !== $dir && $dir !== $home) { while (dirname($dir) !== $dir && $dir !== $home) {
@ -253,7 +253,7 @@ class Application extends BaseApplication
$io->writeError('<warning>Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.', upgrading is strongly recommended.</warning>'); $io->writeError('<warning>Composer only officially supports PHP 5.3.2 and above, you will most likely encounter problems with your PHP '.PHP_VERSION.', upgrading is strongly recommended.</warning>');
} }
if (XdebugHandler::isXdebugActive() && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) { if (XdebugHandler::isXdebugActive() && !Platform::getEnv('COMPOSER_DISABLE_XDEBUG_WARN')) {
$io->writeError('<warning>Composer is operating slower than normal because you have Xdebug enabled. See https://getcomposer.org/xdebug</warning>'); $io->writeError('<warning>Composer is operating slower than normal because you have Xdebug enabled. See https://getcomposer.org/xdebug</warning>');
} }
@ -264,7 +264,7 @@ class Application extends BaseApplication
if ( if (
!Platform::isWindows() !Platform::isWindows()
&& function_exists('exec') && function_exists('exec')
&& !getenv('COMPOSER_ALLOW_SUPERUSER') && !Platform::getEnv('COMPOSER_ALLOW_SUPERUSER')
&& (ini_get('open_basedir') || !file_exists('/.dockerenv')) && (ini_get('open_basedir') || !file_exists('/.dockerenv'))
) { ) {
if (function_exists('posix_getuid') && posix_getuid() === 0) { if (function_exists('posix_getuid') && posix_getuid() === 0) {
@ -277,7 +277,7 @@ class Application extends BaseApplication
} }
} }
} }
if ($uid = (int) getenv('SUDO_UID')) { if ($uid = (int) Platform::getEnv('SUDO_UID')) {
// Silently clobber any sudo credentials on the invoking user to avoid privilege escalations later on // Silently clobber any sudo credentials on the invoking user to avoid privilege escalations later on
// ref. https://github.com/composer/composer/issues/5119 // ref. https://github.com/composer/composer/issues/5119
Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1"); Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");

View File

@ -13,6 +13,7 @@
namespace Composer\Console; namespace Composer\Console;
use Composer\IO\IOInterface; use Composer\IO\IOInterface;
use Composer\Util\Platform;
final class GithubActionError final class GithubActionError
{ {
@ -35,7 +36,7 @@ final class GithubActionError
*/ */
public function emit($message, $file = null, $line = null) public function emit($message, $file = null, $line = null)
{ {
if (getenv('GITHUB_ACTIONS') && !getenv('COMPOSER_TESTS_ARE_RUNNING')) { if (Platform::getEnv('GITHUB_ACTIONS') && !Platform::getEnv('COMPOSER_TESTS_ARE_RUNNING')) {
$message = $this->escapeData($message); $message = $this->escapeData($message);
if ($file && $line) { if ($file && $line) {

View File

@ -99,7 +99,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
} else { } else {
$msg = "Cloning ".$this->getShortHash($ref); $msg = "Cloning ".$this->getShortHash($ref);
$command = 'git clone --no-checkout -- %url% %path% && cd '.$flag.'%path% && git remote add composer -- %url% && git fetch composer && git remote set-url origin -- %sanitizedUrl% && git remote set-url composer -- %sanitizedUrl%'; $command = 'git clone --no-checkout -- %url% %path% && cd '.$flag.'%path% && git remote add composer -- %url% && git fetch composer && git remote set-url origin -- %sanitizedUrl% && git remote set-url composer -- %sanitizedUrl%';
if (getenv('COMPOSER_DISABLE_NETWORK')) { if (Platform::getEnv('COMPOSER_DISABLE_NETWORK')) {
throw new \RuntimeException('The required git reference for '.$package->getName().' is not in cache and network is disabled, aborting'); throw new \RuntimeException('The required git reference for '.$package->getName().' is not in cache and network is disabled, aborting');
} }
} }
@ -157,7 +157,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
} else { } else {
$msg = "Checking out ".$this->getShortHash($ref); $msg = "Checking out ".$this->getShortHash($ref);
$command = '(git remote set-url composer -- %url% && git rev-parse --quiet --verify %ref% || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- %sanitizedUrl%'; $command = '(git remote set-url composer -- %url% && git rev-parse --quiet --verify %ref% || (git fetch composer && git fetch --tags composer)) && git remote set-url composer -- %sanitizedUrl%';
if (getenv('COMPOSER_DISABLE_NETWORK')) { if (Platform::getEnv('COMPOSER_DISABLE_NETWORK')) {
throw new \RuntimeException('The required git reference for '.$target->getName().' is not in cache and network is disabled, aborting'); throw new \RuntimeException('The required git reference for '.$target->getName().' is not in cache and network is disabled, aborting');
} }
} }

View File

@ -255,7 +255,7 @@ class PathDownloader extends FileDownloader implements VcsCapableDownloaderInter
$currentStrategy = self::STRATEGY_SYMLINK; $currentStrategy = self::STRATEGY_SYMLINK;
$allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR); $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
$mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS'); $mirrorPathRepos = Platform::getEnv('COMPOSER_MIRROR_PATH_REPOS');
if ($mirrorPathRepos) { if ($mirrorPathRepos) {
$currentStrategy = self::STRATEGY_MIRROR; $currentStrategy = self::STRATEGY_MIRROR;
} }

View File

@ -161,7 +161,7 @@ class EventDispatcher
*/ */
protected function doDispatch(Event $event) protected function doDispatch(Event $event)
{ {
if (getenv('COMPOSER_DEBUG_EVENTS')) { if (Platform::getEnv('COMPOSER_DEBUG_EVENTS')) {
$details = null; $details = null;
if ($event instanceof PackageEvent) { if ($event instanceof PackageEvent) {
$details = (string) $event->getOperation(); $details = (string) $event->getOperation();
@ -199,7 +199,7 @@ class EventDispatcher
$args = array_merge($script, $event->getArguments()); $args = array_merge($script, $event->getArguments());
$flags = $event->getFlags(); $flags = $event->getFlags();
if (strpos($callable, '@composer ') === 0) { if (strpos($callable, '@composer ') === 0) {
$exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . ' ' . implode(' ', $args); $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(Platform::getEnv('COMPOSER_BINARY')) . ' ' . implode(' ', $args);
if (0 !== ($exitCode = $this->executeTty($exec))) { if (0 !== ($exitCode = $this->executeTty($exec))) {
$this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET); $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
@ -306,7 +306,7 @@ class EventDispatcher
// resolution, even if bin-dir contains composer too because the project requires composer/composer // resolution, even if bin-dir contains composer too because the project requires composer/composer
// see https://github.com/composer/composer/issues/8748 // see https://github.com/composer/composer/issues/8748
if (strpos($exec, 'composer ') === 0) { if (strpos($exec, 'composer ') === 0) {
$exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($exec, 8); $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(Platform::getEnv('COMPOSER_BINARY')) . substr($exec, 8);
} }
if (0 !== ($exitCode = $this->executeTty($exec))) { if (0 !== ($exitCode = $this->executeTty($exec))) {
@ -565,17 +565,18 @@ class EventDispatcher
*/ */
private function ensureBinDirIsInPath() private function ensureBinDirIsInPath()
{ {
$pathStr = 'PATH'; $pathEnv = 'PATH';
if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) { if (false === Platform::getEnv('PATH') && false !== Platform::getEnv('Path')) {
$pathStr = 'Path'; $pathEnv = 'Path';
} }
// add the bin dir to the PATH to make local binaries of deps usable in scripts // add the bin dir to the PATH to make local binaries of deps usable in scripts
$binDir = $this->composer->getConfig()->get('bin-dir'); $binDir = $this->composer->getConfig()->get('bin-dir');
if (is_dir($binDir)) { if (is_dir($binDir)) {
$binDir = realpath($binDir); $binDir = realpath($binDir);
if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) { $pathValue = Platform::getEnv($pathEnv);
Platform::putEnv($pathStr, $binDir.PATH_SEPARATOR.getenv($pathStr)); if (!preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $pathValue)) {
Platform::putEnv($pathEnv, $binDir.PATH_SEPARATOR.$pathValue);
} }
} }
} }

View File

@ -56,17 +56,17 @@ class Factory
*/ */
protected static function getHomeDir() protected static function getHomeDir()
{ {
$home = getenv('COMPOSER_HOME'); $home = Platform::getEnv('COMPOSER_HOME');
if ($home) { if ($home) {
return $home; return $home;
} }
if (Platform::isWindows()) { if (Platform::isWindows()) {
if (!getenv('APPDATA')) { if (!Platform::getEnv('APPDATA')) {
throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly'); throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
} }
return rtrim(strtr(getenv('APPDATA'), '\\', '/'), '/') . '/Composer'; return rtrim(strtr(Platform::getEnv('APPDATA'), '\\', '/'), '/') . '/Composer';
} }
$userDir = self::getUserDir(); $userDir = self::getUserDir();
@ -74,7 +74,7 @@ class Factory
if (self::useXdg()) { if (self::useXdg()) {
// XDG Base Directory Specifications // XDG Base Directory Specifications
$xdgConfig = getenv('XDG_CONFIG_HOME'); $xdgConfig = Platform::getEnv('XDG_CONFIG_HOME');
if (!$xdgConfig) { if (!$xdgConfig) {
$xdgConfig = $userDir . '/.config'; $xdgConfig = $userDir . '/.config';
} }
@ -101,18 +101,18 @@ class Factory
*/ */
protected static function getCacheDir($home) protected static function getCacheDir($home)
{ {
$cacheDir = getenv('COMPOSER_CACHE_DIR'); $cacheDir = Platform::getEnv('COMPOSER_CACHE_DIR');
if ($cacheDir) { if ($cacheDir) {
return $cacheDir; return $cacheDir;
} }
$homeEnv = getenv('COMPOSER_HOME'); $homeEnv = Platform::getEnv('COMPOSER_HOME');
if ($homeEnv) { if ($homeEnv) {
return $homeEnv . '/cache'; return $homeEnv . '/cache';
} }
if (Platform::isWindows()) { if (Platform::isWindows()) {
if ($cacheDir = getenv('LOCALAPPDATA')) { if ($cacheDir = Platform::getEnv('LOCALAPPDATA')) {
$cacheDir .= '/Composer'; $cacheDir .= '/Composer';
} else { } else {
$cacheDir = $home . '/cache'; $cacheDir = $home . '/cache';
@ -136,7 +136,7 @@ class Factory
} }
if (self::useXdg()) { if (self::useXdg()) {
$xdgCache = getenv('XDG_CACHE_HOME') ?: $userDir . '/.cache'; $xdgCache = Platform::getEnv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
return $xdgCache . '/composer'; return $xdgCache . '/composer';
} }
@ -150,7 +150,7 @@ class Factory
*/ */
protected static function getDataDir($home) protected static function getDataDir($home)
{ {
$homeEnv = getenv('COMPOSER_HOME'); $homeEnv = Platform::getEnv('COMPOSER_HOME');
if ($homeEnv) { if ($homeEnv) {
return $homeEnv; return $homeEnv;
} }
@ -161,7 +161,7 @@ class Factory
$userDir = self::getUserDir(); $userDir = self::getUserDir();
if ($home !== $userDir . '/.composer' && self::useXdg()) { if ($home !== $userDir . '/.composer' && self::useXdg()) {
$xdgData = getenv('XDG_DATA_HOME') ?: $userDir . '/.local/share'; $xdgData = Platform::getEnv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
return $xdgData . '/composer'; return $xdgData . '/composer';
} }
@ -225,7 +225,7 @@ class Factory
$config->setAuthConfigSource(new JsonConfigSource($file, true)); $config->setAuthConfigSource(new JsonConfigSource($file, true));
// load COMPOSER_AUTH environment variable if set // load COMPOSER_AUTH environment variable if set
if ($composerAuthEnv = getenv('COMPOSER_AUTH')) { if ($composerAuthEnv = Platform::getEnv('COMPOSER_AUTH')) {
$authData = json_decode($composerAuthEnv, true); $authData = json_decode($composerAuthEnv, true);
if (null === $authData) { if (null === $authData) {
@ -248,7 +248,7 @@ class Factory
*/ */
public static function getComposerFile() public static function getComposerFile()
{ {
return trim(getenv('COMPOSER')) ?: './composer.json'; return trim(Platform::getEnv('COMPOSER')) ?: './composer.json';
} }
/** /**
@ -713,7 +713,7 @@ class Factory
*/ */
private static function getUserDir() private static function getUserDir()
{ {
$home = getenv('HOME'); $home = Platform::getEnv('HOME');
if (!$home) { if (!$home) {
throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly'); throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
} }

View File

@ -488,7 +488,7 @@ class InstallationManager
if ( if (
$this->outputProgress $this->outputProgress
&& $this->io instanceof ConsoleIO && $this->io instanceof ConsoleIO
&& !getenv('CI') && !Platform::getEnv('CI')
&& !$this->io->isDebug() && !$this->io->isDebug()
&& count($promises) > 1 && count($promises) > 1
) { ) {

View File

@ -21,6 +21,7 @@ use Composer\Package\Version\VersionGuesser;
use Composer\Package\Version\VersionParser; use Composer\Package\Version\VersionParser;
use Composer\Package\RootPackage; use Composer\Package\RootPackage;
use Composer\Repository\RepositoryManager; use Composer\Repository\RepositoryManager;
use Composer\Util\Platform;
use Composer\Util\ProcessExecutor; use Composer\Util\ProcessExecutor;
/** /**
@ -83,8 +84,8 @@ class RootPackageLoader extends ArrayLoader
$commit = null; $commit = null;
// override with env var if available // override with env var if available
if (getenv('COMPOSER_ROOT_VERSION')) { if (Platform::getEnv('COMPOSER_ROOT_VERSION')) {
$config['version'] = getenv('COMPOSER_ROOT_VERSION'); $config['version'] = Platform::getEnv('COMPOSER_ROOT_VERSION');
} else { } else {
$versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd()); $versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
if ($versionData) { if ($versionData) {

View File

@ -179,7 +179,7 @@ class PathRepository extends ArrayRepository implements ConfigurableRepositoryIn
} }
// carry over the root package version if this path repo is in the same git repository as root package // carry over the root package version if this path repo is in the same git repository as root package
if (!isset($package['version']) && ($rootVersion = getenv('COMPOSER_ROOT_VERSION'))) { if (!isset($package['version']) && ($rootVersion = Platform::getEnv('COMPOSER_ROOT_VERSION'))) {
if ( if (
0 === $this->process->execute('git rev-parse HEAD', $ref1, $path) 0 === $this->process->execute('git rev-parse HEAD', $ref1, $path)
&& 0 === $this->process->execute('git rev-parse HEAD', $ref2) && 0 === $this->process->execute('git rev-parse HEAD', $ref2)

View File

@ -273,7 +273,7 @@ class Git
*/ */
public function syncMirror($url, $dir) public function syncMirror($url, $dir)
{ {
if (getenv('COMPOSER_DISABLE_NETWORK') && getenv('COMPOSER_DISABLE_NETWORK') !== 'prime') { if (Platform::getEnv('COMPOSER_DISABLE_NETWORK') && Platform::getEnv('COMPOSER_DISABLE_NETWORK') !== 'prime') {
$this->io->writeError('<warning>Aborting git mirror sync of '.$url.' as network is disabled</warning>'); $this->io->writeError('<warning>Aborting git mirror sync of '.$url.' as network is disabled</warning>');
return false; return false;
@ -401,20 +401,20 @@ class Git
} }
// added in git 1.7.1, prevents prompting the user for username/password // added in git 1.7.1, prevents prompting the user for username/password
if (getenv('GIT_ASKPASS') !== 'echo') { if (Platform::getEnv('GIT_ASKPASS') !== 'echo') {
Platform::putEnv('GIT_ASKPASS', 'echo'); Platform::putEnv('GIT_ASKPASS', 'echo');
} }
// clean up rogue git env vars in case this is running in a git hook // clean up rogue git env vars in case this is running in a git hook
if (getenv('GIT_DIR')) { if (Platform::getEnv('GIT_DIR')) {
Platform::clearEnv('GIT_DIR'); Platform::clearEnv('GIT_DIR');
} }
if (getenv('GIT_WORK_TREE')) { if (Platform::getEnv('GIT_WORK_TREE')) {
Platform::clearEnv('GIT_WORK_TREE'); Platform::clearEnv('GIT_WORK_TREE');
} }
// Run processes with predictable LANGUAGE // Run processes with predictable LANGUAGE
if (getenv('LANGUAGE') !== 'C') { if (Platform::getEnv('LANGUAGE') !== 'C') {
Platform::putEnv('LANGUAGE', 'C'); Platform::putEnv('LANGUAGE', 'C');
} }

View File

@ -70,7 +70,7 @@ class HttpDownloader
{ {
$this->io = $io; $this->io = $io;
$this->disabled = (bool) getenv('COMPOSER_DISABLE_NETWORK'); $this->disabled = (bool) Platform::getEnv('COMPOSER_DISABLE_NETWORK');
// Setup TLS options // Setup TLS options
// The cafile option can be set via config.json // The cafile option can be set via config.json
@ -88,7 +88,7 @@ class HttpDownloader
$this->rfs = new RemoteFilesystem($io, $config, $options, $disableTls); $this->rfs = new RemoteFilesystem($io, $config, $options, $disableTls);
if (is_numeric($maxJobs = getenv('COMPOSER_MAX_PARALLEL_HTTP'))) { if (is_numeric($maxJobs = Platform::getEnv('COMPOSER_MAX_PARALLEL_HTTP'))) {
$this->maxJobs = max(1, min(50, (int) $maxJobs)); $this->maxJobs = max(1, min(50, (int) $maxJobs));
} }
} }

View File

@ -24,6 +24,24 @@ class Platform
/** @var ?bool */ /** @var ?bool */
private static $isWindowsSubsystemForLinux = null; private static $isWindowsSubsystemForLinux = null;
/**
* getenv() equivalent but reads from the runtime global variables first
*
* @param string $name
* @return string|false
*/
public static function getEnv($name)
{
if (array_key_exists($name, $_SERVER)) {
return (string) $_SERVER[$name];
}
if (array_key_exists($name, $_ENV)) {
return (string) $_ENV[$name];
}
return getenv($name);
}
/** /**
* putenv() equivalent but updates the runtime global variables too * putenv() equivalent but updates the runtime global variables too
* *
@ -65,10 +83,10 @@ class Platform
return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) { return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
// Treat HOME as an alias for USERPROFILE on Windows for legacy reasons // Treat HOME as an alias for USERPROFILE on Windows for legacy reasons
if (Platform::isWindows() && $matches['var'] == 'HOME') { if (Platform::isWindows() && $matches['var'] == 'HOME') {
return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches['path']; return (Platform::getEnv('HOME') ?: Platform::getEnv('USERPROFILE')) . $matches['path'];
} }
return getenv($matches['var']) . $matches['path']; return Platform::getEnv($matches['var']) . $matches['path'];
}, $path); }, $path);
} }
@ -78,11 +96,11 @@ class Platform
*/ */
public static function getUserDirectory() public static function getUserDirectory()
{ {
if (false !== ($home = getenv('HOME'))) { if (false !== ($home = self::getEnv('HOME'))) {
return $home; return $home;
} }
if (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) { if (self::isWindows() && false !== ($home = self::getEnv('USERPROFILE'))) {
return $home; return $home;
} }
@ -159,7 +177,7 @@ class Platform
// detect msysgit/mingw and assume this is a tty because detection // detect msysgit/mingw and assume this is a tty because detection
// does not work correctly, see https://github.com/composer/composer/issues/9690 // does not work correctly, see https://github.com/composer/composer/issues/9690
if (in_array(strtoupper(getenv('MSYSTEM') ?: ''), array('MINGW32', 'MINGW64'), true)) { if (in_array(strtoupper(self::getEnv('MSYSTEM') ?: ''), array('MINGW32', 'MINGW64'), true)) {
return true; return true;
} }
@ -211,7 +229,7 @@ class Platform
} }
} }
if (getenv('COMPOSER_RUNTIME_ENV') === 'virtualbox') { if (self::getEnv('COMPOSER_RUNTIME_ENV') === 'virtualbox') {
return self::$isVirtualBoxGuest = true; return self::$isVirtualBoxGuest = true;
} }

View File

@ -122,7 +122,7 @@ final class StreamContextFactory
$phpVersion, $phpVersion,
$httpVersion, $httpVersion,
$platformPhpVersion ? '; Platform-PHP '.$platformPhpVersion : '', $platformPhpVersion ? '; Platform-PHP '.$platformPhpVersion : '',
getenv('CI') ? '; CI' : '' Platform::getEnv('CI') ? '; CI' : ''
); );
} }

View File

@ -24,6 +24,7 @@ use Composer\Script\ScriptEvents;
use Composer\Script\Event as ScriptEvent; use Composer\Script\Event as ScriptEvent;
use Composer\Util\ProcessExecutor; use Composer\Util\ProcessExecutor;
use Composer\Test\Mock\ProcessExecutorMock; use Composer\Test\Mock\ProcessExecutorMock;
use Composer\Util\Platform;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
class EventDispatcherTest extends TestCase class EventDispatcherTest extends TestCase
@ -294,9 +295,9 @@ class EventDispatcherTest extends TestCase
public function testDispatcherAppendsDirBinOnPathForEveryListener() public function testDispatcherAppendsDirBinOnPathForEveryListener()
{ {
$currentDirectoryBkp = getcwd(); $currentDirectoryBkp = getcwd();
$composerBinDirBkp = getenv('COMPOSER_BIN_DIR'); $composerBinDirBkp = Platform::getEnv('COMPOSER_BIN_DIR');
chdir(__DIR__); chdir(__DIR__);
putenv('COMPOSER_BIN_DIR=' . __DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR)); Platform::putEnv('COMPOSER_BIN_DIR', __DIR__ . '/vendor/bin');
$dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->setConstructorArgs(array( $dispatcher = $this->getMockBuilder('Composer\EventDispatcher\EventDispatcher')->setConstructorArgs(array(
$this->createComposerInstance(), $this->createComposerInstance(),
@ -314,11 +315,15 @@ class EventDispatcherTest extends TestCase
$dispatcher->expects($this->atLeastOnce())->method('getListeners')->will($this->returnValue($listeners)); $dispatcher->expects($this->atLeastOnce())->method('getListeners')->will($this->returnValue($listeners));
$dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false); $dispatcher->dispatchScript(ScriptEvents::POST_INSTALL_CMD, false);
rmdir(__DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR)); rmdir(__DIR__ . '/vendor/bin');
rmdir(__DIR__ . sprintf('%svendor', DIRECTORY_SEPARATOR)); rmdir(__DIR__ . '/vendor');
chdir($currentDirectoryBkp); chdir($currentDirectoryBkp);
putenv('COMPOSER_BIN_DIR' . ($composerBinDirBkp === false ? '' : '=' . $composerBinDirBkp)); if ($composerBinDirBkp) {
Platform::putEnv('COMPOSER_BIN_DIR', $composerBinDirBkp);
} else {
Platform::clearEnv('COMPOSER_BIN_DIR');
}
} }
/** /**
@ -326,14 +331,14 @@ class EventDispatcherTest extends TestCase
*/ */
public static function createsVendorBinFolderChecksEnvDoesNotContainsBin() public static function createsVendorBinFolderChecksEnvDoesNotContainsBin()
{ {
mkdir(__DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), 0700, true); mkdir(__DIR__ . '/vendor/bin', 0700, true);
$val = getenv('PATH'); $val = getenv('PATH');
if (!$val) { if (!$val) {
$val = getenv('Path'); $val = getenv('Path');
} }
self::assertFalse(strpos($val, __DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR))); self::assertStringNotContainsString(__DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'bin', $val);
} }
/** /**
@ -347,7 +352,7 @@ class EventDispatcherTest extends TestCase
$val = getenv('Path'); $val = getenv('Path');
} }
self::assertNotFalse(strpos($val, __DIR__ . sprintf('%svendor%sbin', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR))); self::assertStringContainsString(__DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'bin', $val);
} }
/** /**
@ -628,7 +633,7 @@ class EventDispatcherTest extends TestCase
private function createComposerInstance() private function createComposerInstance()
{ {
$composer = new Composer; $composer = new Composer;
$config = new Config; $config = new Config();
$composer->setConfig($config); $composer->setConfig($config);
$package = $this->getMockBuilder('Composer\Package\RootPackageInterface')->getMock(); $package = $this->getMockBuilder('Composer\Package\RootPackageInterface')->getMock();
$composer->setPackage($package); $composer->setPackage($package);