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(