From a21b0f82db18808012984f86524cfcd9f13d1ad3 Mon Sep 17 00:00:00 2001 From: Benjamin Grandfond Date: Fri, 30 May 2014 17:14:43 +0200 Subject: [PATCH] Allow SVN to connect with credentials provided with the auth.json file --- src/Composer/Downloader/SvnDownloader.php | 2 +- src/Composer/Repository/Vcs/SvnDriver.php | 2 +- src/Composer/Util/Svn.php | 82 +++++++++++++++---- .../Test/Repository/Vcs/SvnDriverTest.php | 3 - tests/Composer/Test/Util/SvnTest.php | 25 +++++- 5 files changed, 90 insertions(+), 24 deletions(-) diff --git a/src/Composer/Downloader/SvnDownloader.php b/src/Composer/Downloader/SvnDownloader.php index 495979d40..689781f6c 100644 --- a/src/Composer/Downloader/SvnDownloader.php +++ b/src/Composer/Downloader/SvnDownloader.php @@ -84,7 +84,7 @@ class SvnDownloader extends VcsDownloader */ protected function execute($baseUrl, $command, $url, $cwd = null, $path = null) { - $util = new SvnUtil($baseUrl, $this->io); + $util = new SvnUtil($baseUrl, $this->io, $this->config); try { return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose()); } catch (\RuntimeException $e) { diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index 506c176b8..fde529b16 100644 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -306,7 +306,7 @@ class SvnDriver extends VcsDriver protected function execute($command, $url) { if (null === $this->util) { - $this->util = new SvnUtil($this->baseUrl, $this->io, $this->process); + $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process); } try { diff --git a/src/Composer/Util/Svn.php b/src/Composer/Util/Svn.php index 9db0930e6..bad4202c8 100644 --- a/src/Composer/Util/Svn.php +++ b/src/Composer/Util/Svn.php @@ -12,6 +12,7 @@ namespace Composer\Util; +use Composer\Config; use Composer\IO\IOInterface; /** @@ -57,15 +58,21 @@ class Svn */ protected $qtyAuthTries = 0; + /** + * @var \Composer\Config + */ + protected $config; + /** * @param string $url * @param \Composer\IO\IOInterface $io * @param ProcessExecutor $process */ - public function __construct($url, IOInterface $io, ProcessExecutor $process = null) + public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null) { $this->url = $url; $this->io = $io; + $this->config = $config; $this->process = $process ?: new ProcessExecutor; } @@ -123,16 +130,12 @@ class Svn throw new \RuntimeException($output); } - // no auth supported for non interactive calls - if (!$this->io->isInteractive()) { - throw new \RuntimeException( - 'can not ask for authentication in non interactive mode ('.$output.')' - ); + if (!$this->hasAuth()) { + $this->doAuthDance(); } // try to authenticate if maximum quantity of tries not reached - if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES || !$this->hasAuth()) { - $this->doAuthDance(); + if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) { // restart the process return $this->execute($command, $url, $cwd, $path, $verbose); @@ -147,9 +150,17 @@ class Svn * Repositories requests credentials, let's put them in. * * @return \Composer\Util\Svn + * @throws \RuntimeException */ protected function doAuthDance() { + // cannot ask for credentials in non interactive mode + if (!$this->io->isInteractive()) { + throw new \RuntimeException( + 'can not ask for authentication in non interactive mode' + ); + } + $this->io->write("The Subversion server ({$this->url}) requested credentials:"); $this->hasAuth = true; @@ -248,17 +259,11 @@ class Svn return $this->hasAuth; } - $uri = parse_url($this->url); - if (empty($uri['user'])) { - return $this->hasAuth = false; - } - - $this->credentials['username'] = $uri['user']; - if (!empty($uri['pass'])) { - $this->credentials['password'] = $uri['pass']; + if (false === $this->createAuthFromConfig()) { + $this->createAuthFromUrl(); } - return $this->hasAuth = true; + return $this->hasAuth; } /** @@ -270,4 +275,47 @@ class Svn { return $this->cacheCredentials ? '' : '--no-auth-cache '; } + + /** + * Create the auth params from the configuration file. + * + * @return bool + */ + protected function createAuthFromConfig() + { + if (!$this->config->has('http-basic')) { + return $this->hasAuth = false; + } + + $authConfig = $this->config->get('http-basic'); + + if (array_key_exists($this->url, $authConfig)) { + $this->credentials['username'] = $authConfig[$this->url]['username']; + $this->credentials['password'] = $authConfig[$this->url]['password']; + + return $this->hasAuth = true; + } + + return $this->hasAuth = false; + } + + /** + * Create the auth params from the url + * + * @return bool + */ + protected function createAuthFromUrl() + { + $uri = parse_url($this->url); + if (empty($uri['user'])) { + return $this->hasAuth = false; + } + + $this->credentials['username'] = $uri['user']; + if (!empty($uri['pass'])) { + $this->credentials['password'] = $uri['pass']; + } + + return $this->hasAuth = true; + } } diff --git a/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php b/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php index 2f698565f..2ef1baa18 100644 --- a/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php +++ b/tests/Composer/Test/Repository/Vcs/SvnDriverTest.php @@ -23,9 +23,6 @@ class SvnDriverTest extends \PHPUnit_Framework_TestCase public function testWrongCredentialsInUrl() { $console = $this->getMock('Composer\IO\IOInterface'); - $console->expects($this->exactly(6)) - ->method('isInteractive') - ->will($this->returnValue(true)); $output = "svn: OPTIONS of 'http://corp.svn.local/repo':"; $output .= " authorization failed: Could not authenticate to server:"; diff --git a/tests/Composer/Test/Util/SvnTest.php b/tests/Composer/Test/Util/SvnTest.php index fb938d72e..69fb1c804 100644 --- a/tests/Composer/Test/Util/SvnTest.php +++ b/tests/Composer/Test/Util/SvnTest.php @@ -1,6 +1,7 @@ setAccessible(true); @@ -41,7 +42,7 @@ class SvnTest extends \PHPUnit_Framework_TestCase { $url = 'http://svn.example.org'; - $svn = new Svn($url, new NullIO()); + $svn = new Svn($url, new NullIO(), new Config()); $reflMethod = new \ReflectionMethod('Composer\\Util\\Svn', 'getCommand'); $reflMethod->setAccessible(true); @@ -51,6 +52,26 @@ class SvnTest extends \PHPUnit_Framework_TestCase ); } + public function testCredentialsFromConfig() + { + $url = 'http://svn.apache.org'; + + $config = new Config(); + $config->merge(array( + 'config' => array( + 'http-basic' => array( + $url => array('username' => 'foo', 'password' => 'bar') + ) + ) + )); + + $svn = new Svn($url, new NullIO, $config); + $reflMethod = new \ReflectionMethod('Composer\\Util\\Svn', 'getCredentialString'); + $reflMethod->setAccessible(true); + + $this->assertEquals($this->getCmd(" --username 'foo' --password 'bar' "), $reflMethod->invoke($svn)); + } + private function getCmd($cmd) { if (defined('PHP_WINDOWS_VERSION_BUILD')) {