From dbea8258711bcdcc3ddf620c7e2e9783ea19f00a Mon Sep 17 00:00:00 2001 From: William Sandin Date: Sun, 31 Dec 2017 19:35:09 +0700 Subject: [PATCH 1/5] Raise a warning if current user and owner of deploy dir doesn't match --- src/Composer/Command/SelfUpdateCommand.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 055f8af7f..1f86e7ed9 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -93,7 +93,9 @@ EOT $cacheDir = $config->get('cache-dir'); $rollbackDir = $config->get('data-dir'); $home = $config->get('home'); + $homeOwner = posix_getpwuid(fileowner($home)); $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; + $composeUser = posix_getpwuid(posix_geteuid()); if ($input->getOption('update-keys')) { return $this->fetchKeys($io, $config); @@ -107,6 +109,11 @@ EOT throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written'); } + // check if composer is running as the same user that owns the directory root + if ($composeUser !== $homeOwner) { + $io->writeError('You are running composer as "'.$composeUser.'", while "'.$home.'" is owned by "'.$homeOwner.'"'); + } + if ($input->getOption('rollback')) { return $this->rollback($output, $rollbackDir, $localFilename); } From 4296fe657f3e0568f3e820473831536f254813e0 Mon Sep 17 00:00:00 2001 From: William Sandin Date: Sat, 6 Jan 2018 19:02:14 +0700 Subject: [PATCH 2/5] Adding check to confirm POSIX is defined and callable --- src/Composer/Command/SelfUpdateCommand.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 1f86e7ed9..147d65c02 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -93,9 +93,7 @@ EOT $cacheDir = $config->get('cache-dir'); $rollbackDir = $config->get('data-dir'); $home = $config->get('home'); - $homeOwner = posix_getpwuid(fileowner($home)); $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; - $composeUser = posix_getpwuid(posix_geteuid()); if ($input->getOption('update-keys')) { return $this->fetchKeys($io, $config); @@ -109,9 +107,13 @@ EOT throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written'); } - // check if composer is running as the same user that owns the directory root - if ($composeUser !== $homeOwner) { - $io->writeError('You are running composer as "'.$composeUser.'", while "'.$home.'" is owned by "'.$homeOwner.'"'); + // check if composer is running as the same user that owns the directory root, only if POSIX is defined and callable + if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) { + $composeUser = posix_getpwuid(posix_geteuid()); + $homeOwner = posix_getpwuid(fileowner($home)); + if ($composeUser !== $homeOwner) { + $io->writeError('You are running composer as "'.$composeUser.'", while "'.$home.'" is owned by "'.$homeOwner.'"'); + } } if ($input->getOption('rollback')) { From 49068c579ea5ace2e1b105da19ec81f5fa88c26b Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 24 Jan 2018 11:14:40 +0100 Subject: [PATCH 3/5] Fix indenting --- src/Composer/Command/SelfUpdateCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 147d65c02..3ed72bdbc 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -112,7 +112,7 @@ EOT $composeUser = posix_getpwuid(posix_geteuid()); $homeOwner = posix_getpwuid(fileowner($home)); if ($composeUser !== $homeOwner) { - $io->writeError('You are running composer as "'.$composeUser.'", while "'.$home.'" is owned by "'.$homeOwner.'"'); + $io->writeError('You are running composer as "'.$composeUser.'", while "'.$home.'" is owned by "'.$homeOwner.'"'); } } From 9bc83d698e48dff2cd5559134c9c0877ca6977a4 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Fri, 12 Jan 2018 10:42:46 +0100 Subject: [PATCH 4/5] Pass auth credentials to svn log while retrieving commit logs --- src/Composer/Downloader/SvnDownloader.php | 23 +++++++++++---- src/Composer/Util/Svn.php | 36 +++++++++++++++++++++-- 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/Composer/Downloader/SvnDownloader.php b/src/Composer/Downloader/SvnDownloader.php index 9cde1537b..9ce39c4b2 100644 --- a/src/Composer/Downloader/SvnDownloader.php +++ b/src/Composer/Downloader/SvnDownloader.php @@ -15,6 +15,7 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; use Composer\Util\Svn as SvnUtil; use Composer\Repository\VcsRepository; +use Composer\Util\ProcessExecutor; /** * @author Ben Bieker @@ -171,22 +172,34 @@ class SvnDownloader extends VcsDownloader protected function getCommitLogs($fromReference, $toReference, $path) { if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) { + // retrieve the svn base url from the checkout folder + $command = sprintf('svn info %s | grep ^URL:', ProcessExecutor::escape($path)); + if (0 !== $this->process->execute($command, $output, $path)) { + throw new \RuntimeException( + 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput() + ); + } + // parse info line like 'URL: https://example.com/my/svn/url' + list ($prefix, $baseUrl) = explode(" ", $output, 2); + // strip paths from references and only keep the actual revision $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference); $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference); $command = sprintf('svn log -r%s:%s --incremental', $fromRevision, $toRevision); - if (0 !== $this->process->execute($command, $output, $path)) { + $util = new SvnUtil($baseUrl, $this->io, $this->config); + $util->setCacheCredentials($this->cacheCredentials); + try { + return $util->executeLocal($command, $path, null, $this->io->isVerbose()); + } catch (\RuntimeException $e) { throw new \RuntimeException( - 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput() + 'Failed to execute ' . $command . "\n\n".$e->getMessage() ); } - } else { - $output = "Could not retrieve changes between $fromReference and $toReference due to missing revision information"; } - return $output; + return "Could not retrieve changes between $fromReference and $toReference due to missing revision information"; } protected function discardChanges($path) diff --git a/src/Composer/Util/Svn.php b/src/Composer/Util/Svn.php index 80f70faf6..082ece691 100644 --- a/src/Composer/Util/Svn.php +++ b/src/Composer/Util/Svn.php @@ -85,7 +85,7 @@ class Svn } /** - * Execute an SVN command and try to fix up the process with credentials + * Execute an SVN remote command and try to fix up the process with credentials * if necessary. * * @param string $command SVN command to run @@ -103,6 +103,36 @@ class Svn $this->config->prohibitUrlByConfig($url, $this->io); $svnCommand = $this->getCommand($command, $url, $path); + + return $this->executeWithAuthRetry($svnCommand, $cwd, $path, $verbose); + } + + /** + * Execute an SVN local command and try to fix up the process with credentials + * if necessary. + * + * @param string $command SVN command to run + * @param string $path Path argument passed thru to the command + * @param string $cwd Working directory + * @param bool $verbose Output all output to the user + * + * @throws \RuntimeException + * @return string + */ + public function executeLocal($command, $path, $cwd = null, $verbose = false) + { + $svnCommand = sprintf('%s %s%s %s', + $command, + '--non-interactive ', + $this->getCredentialString(), + ProcessExecutor::escape($path) + ); + + return $this->executeWithAuthRetry($svnCommand, $cwd, $path, $verbose); + } + + private function executeWithAuthRetry($command, $cwd, $path, $verbose) + { $output = null; $io = $this->io; $handler = function ($type, $buffer) use (&$output, $io, $verbose) { @@ -117,7 +147,7 @@ class Svn $io->writeError($buffer, false); } }; - $status = $this->process->execute($svnCommand, $handler, $cwd); + $status = $this->process->execute($command, $handler, $cwd); if (0 === $status) { return $output; } @@ -140,7 +170,7 @@ class Svn // try to authenticate if maximum quantity of tries not reached if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) { // restart the process - return $this->execute($command, $url, $cwd, $path, $verbose); + return $this->executeWithAuthRetry($command, $cwd, $path, $verbose); } throw new \RuntimeException( From e67a559db972a54c2534048e45c4953ef4981851 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Mon, 15 Jan 2018 09:35:49 +0100 Subject: [PATCH 5/5] make sure "svn info" output is parsed in a x-platform way --- src/Composer/Downloader/SvnDownloader.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Composer/Downloader/SvnDownloader.php b/src/Composer/Downloader/SvnDownloader.php index 9ce39c4b2..54d9718be 100644 --- a/src/Composer/Downloader/SvnDownloader.php +++ b/src/Composer/Downloader/SvnDownloader.php @@ -173,14 +173,21 @@ class SvnDownloader extends VcsDownloader { if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) { // retrieve the svn base url from the checkout folder - $command = sprintf('svn info %s | grep ^URL:', ProcessExecutor::escape($path)); + $command = sprintf('svn info --non-interactive --xml %s', ProcessExecutor::escape($path)); if (0 !== $this->process->execute($command, $output, $path)) { throw new \RuntimeException( 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput() ); } - // parse info line like 'URL: https://example.com/my/svn/url' - list ($prefix, $baseUrl) = explode(" ", $output, 2); + + $urlPattern = '#(.*)#'; + if (preg_match($urlPattern, $output, $matches)) { + $baseUrl = $matches[1]; + } else { + throw new \RuntimeException( + 'Unable to determine svn url for path '. $path + ); + } // strip paths from references and only keep the actual revision $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);