diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index ea0831818..54750d4ad 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -425,7 +425,14 @@ TAGSPUBKEY } try { - rename($newFilename, $localFilename); + if (Platform::isWindows()) { + // use copy to apply permissions from the destination directory + // as rename uses source permissions and may block other users + copy($newFilename, $localFilename); + @unlink($newFilename); + } else { + rename($newFilename, $localFilename); + } return true; } catch (\Exception $e) { @@ -534,7 +541,7 @@ TAGSPUBKEY /** * Invokes a UAC prompt to update composer.phar as an admin * - * Uses a .vbs script to elevate and run the cmd.exe move command. + * Uses a .vbs script to elevate and run the cmd.exe copy command. * * @param string $localFilename The composer.phar location * @param string $newFilename The downloaded or backup phar @@ -560,13 +567,13 @@ TAGSPUBKEY $checksum = hash_file('sha256', $newFilename); - // cmd's internal move is fussy about backslashes + // cmd's internal copy is fussy about backslashes $source = str_replace('/', '\\', $newFilename); $destination = str_replace('/', '\\', $localFilename); $vbs = <<writeError('Operation succeeded.'); + @unlink($newFilename); } else { - $io->writeError('Operation failed (file not written). '.$helpMessage.''); + $io->writeError('Operation failed.'.$helpMessage.''); } return $result; diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index d45684ef9..78270f4da 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -519,7 +519,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface { $path = $this->normalizePath($path); if (0 !== $this->process->execute('git clean -df && git reset --hard', $output, $path)) { - throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput()); + throw new \RuntimeException("Could not reset changes\n\n:".$output); } $this->hasDiscardedChanges[$path] = true; @@ -533,7 +533,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface { $path = $this->normalizePath($path); if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) { - throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput()); + throw new \RuntimeException("Could not stash changes\n\n:".$output); } $this->hasStashedChanges[$path] = true; @@ -547,7 +547,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface { $path = $this->normalizePath($path); if (0 !== $this->process->execute('git diff HEAD', $output, $path)) { - throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput()); + throw new \RuntimeException("Could not view diff\n\n:".$output); } $this->io->writeError($output); diff --git a/src/Composer/Util/Http/CurlDownloader.php b/src/Composer/Util/Http/CurlDownloader.php index 5e9494aed..7e4753496 100644 --- a/src/Composer/Util/Http/CurlDownloader.php +++ b/src/Composer/Util/Http/CurlDownloader.php @@ -183,7 +183,6 @@ class CurlDownloader } $options['http']['header'] = $this->authHelper->addAuthenticationHeader($options['http']['header'], $origin, $url); - // Merge in headers - we don't get any proxy values $options = StreamContextFactory::initOptions($url, $options, true); foreach (self::$options as $type => $curlOptions) { diff --git a/src/Composer/Util/Http/ProxyHelper.php b/src/Composer/Util/Http/ProxyHelper.php index 4ca7a4bc8..e291f5b81 100644 --- a/src/Composer/Util/Http/ProxyHelper.php +++ b/src/Composer/Util/Http/ProxyHelper.php @@ -131,12 +131,14 @@ class ProxyHelper $error = sprintf('malformed %s url', $envName); $proxy = parse_url($proxyUrl); + // We need parse_url to have identified a host if (!isset($proxy['host'])) { throw new \RuntimeException($error); } $proxyUrl = self::formatParsedUrl($proxy, true); + // We need a port because streams and curl use different defaults if (!parse_url($proxyUrl, PHP_URL_PORT)) { throw new \RuntimeException($error); } diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index ea899b312..8b8e0c3e0 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -254,7 +254,7 @@ class RemoteFilesystem $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet'))); - $proxy = ProxyManager::getInstance()->getProxyForRequest($fileUrl); + $proxy = $this->proxyManager->getProxyForRequest($fileUrl); $usingProxy = $proxy->getFormattedUrl(' using proxy (%s)'); $this->io->writeError((strpos($origFileUrl, 'http') === 0 ? 'Downloading ' : 'Reading ') . Url::sanitize($origFileUrl) . $usingProxy, true, IOInterface::DEBUG); unset($origFileUrl, $proxy, $usingProxy); diff --git a/tests/Composer/Test/AllFunctionalTest.php b/tests/Composer/Test/AllFunctionalTest.php index a901617f9..86e03f9e8 100644 --- a/tests/Composer/Test/AllFunctionalTest.php +++ b/tests/Composer/Test/AllFunctionalTest.php @@ -78,7 +78,7 @@ class AllFunctionalTest extends TestCase } } - $proc = new Process('php -dphar.readonly=0 '.escapeshellarg('./bin/compile'), $target); + $proc = new Process((defined('PHP_BINARY') ? escapeshellcmd(PHP_BINARY) : 'php').' -dphar.readonly=0 '.escapeshellarg('./bin/compile'), $target); $exitcode = $proc->run(); if ($exitcode !== 0 || trim($proc->getOutput())) { @@ -110,7 +110,7 @@ class AllFunctionalTest extends TestCase 'COMPOSER_CACHE_DIR' => $this->testDir.'cache', ); - $cmd = 'php '.escapeshellarg(self::$pharPath).' --no-ansi '.$testData['RUN']; + $cmd = (defined('PHP_BINARY') ? escapeshellcmd(PHP_BINARY) : 'php') .' '.escapeshellarg(self::$pharPath).' --no-ansi '.$testData['RUN']; $proc = new Process($cmd, $this->testDir, $env, null, 300); $output = '';