Jordi Boggiano 7 жил өмнө
parent
commit
5f97eb1578

+ 9 - 0
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('<warning>You are running composer as "'.$composeUser.'", while "'.$home.'" is owned by "'.$homeOwner.'"</warning>');
+            }
+        }
+
         if ($input->getOption('rollback')) {
             return $this->rollback($output, $rollbackDir, $localFilename);
         }

+ 25 - 5
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 <mail@ben-bieker.de>
@@ -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 = '#<url>(.*)</url>#';
+            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)

+ 33 - 3
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(