diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php
index 055f8af7f..3ed72bdbc 100644
--- a/src/Composer/Command/SelfUpdateCommand.php
+++ b/src/Composer/Command/SelfUpdateCommand.php
@@ -107,6 +107,15 @@ 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, 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')) {
return $this->rollback($output, $rollbackDir, $localFilename);
}
diff --git a/src/Composer/Downloader/SvnDownloader.php b/src/Composer/Downloader/SvnDownloader.php
index 9cde1537b..54d9718be 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,41 @@ 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 --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()
+ );
+ }
+
+ $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);
$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(