diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php
index 9379e01b3..5f41d6842 100644
--- a/src/Composer/Downloader/GitDownloader.php
+++ b/src/Composer/Downloader/GitDownloader.php
@@ -48,15 +48,10 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
$flag = Platform::isWindows() ? '/D ' : '';
// --dissociate option is only available since git 2.3.0-rc0
- if (version_compare($this->gitUtil->getVersion(), '2.3.0-rc0', '>=')) {
- if (!file_exists($cachePath)) {
- $this->io->writeError(sprintf(' Cloning to cache at %s', ProcessExecutor::escape($cachePath)));
- $mirrorCommand = 'git clone --mirror %s %s';
- $mirrorCommandCallable = function ($url) use ($cachePath, $mirrorCommand) {
- return sprintf($mirrorCommand, ProcessExecutor::escape($url), ProcessExecutor::escape($cachePath));
- };
- $this->gitUtil->runCommand($mirrorCommandCallable, $url, $path, true);
- }
+ $gitVersion = $this->gitUtil->getVersion();
+ if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=')) {
+ $this->io->writeError(sprintf(' Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
+ $this->gitUtil->syncMirror($url, $cachePath);
$cacheOptions = sprintf('--dissociate --reference %s ', ProcessExecutor::escape($cachePath));
}
$command = 'git clone --no-checkout %s %s '.$cacheOptions.'&& cd '.$flag.'%2$s && git remote add composer %1$s && git fetch composer';
diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php
index e98858abc..bacad4d2c 100644
--- a/src/Composer/Repository/Vcs/GitDriver.php
+++ b/src/Composer/Repository/Vcs/GitDriver.php
@@ -58,27 +58,8 @@ class GitDriver extends VcsDriver
}
$gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
-
- // update the repo if it is a valid git repository
- if (is_dir($this->repoDir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $this->repoDir) && trim($output) === '.') {
- try {
- $commandCallable = function ($url) {
- return sprintf('git remote set-url origin %s && git remote update --prune origin', ProcessExecutor::escape($url));
- };
- $gitUtil->runCommand($commandCallable, $this->url, $this->repoDir);
- } catch (\Exception $e) {
- $this->io->writeError('Failed to update '.$this->url.', package information from this repository may be outdated ('.$e->getMessage().')');
- }
- } else {
- // clean up directory and do a fresh clone into it
- $fs->removeDirectory($this->repoDir);
-
- $repoDir = $this->repoDir;
- $commandCallable = function ($url) use ($repoDir) {
- return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($repoDir));
- };
-
- $gitUtil->runCommand($commandCallable, $this->url, $this->repoDir, true);
+ if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
+ $this->io->writeError('Failed to update '.$this->url.', package information from this repository may be outdated');
}
$cacheUrl = $this->url;
diff --git a/src/Composer/Util/Git.php b/src/Composer/Util/Git.php
index 9ddb13c80..596188fe6 100644
--- a/src/Composer/Util/Git.php
+++ b/src/Composer/Util/Git.php
@@ -20,6 +20,8 @@ use Composer\IO\IOInterface;
*/
class Git
{
+ private static $version;
+
/** @var IOInterface */
protected $io;
/** @var Config */
@@ -198,6 +200,34 @@ class Git
}
}
+ public function syncMirror($url, $dir)
+ {
+ // update the repo if it is a valid git repository
+ if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
+ try {
+ $commandCallable = function ($url) {
+ return sprintf('git remote set-url origin %s && git remote update --prune origin', ProcessExecutor::escape($url));
+ };
+ $this->runCommand($commandCallable, $url, $dir);
+ } catch (\Exception $e) {
+ return false;
+ }
+
+ return true;
+ }
+
+ // clean up directory and do a fresh clone into it
+ $this->filesystem->removeDirectory($dir);
+
+ $commandCallable = function ($url) use ($dir) {
+ return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
+ };
+
+ $this->runCommand($commandCallable, $url, $dir, true);
+
+ return true;
+ }
+
private function isAuthenticationFailure($url, &$match)
{
if (!preg_match('{(https?://)([^/]+)(.*)$}i', $url, $match)) {
@@ -277,16 +307,18 @@ class Git
/**
* Retrieves the current git version.
*
- * @return string
- * The git version number.
+ * @return string|null The git version number.
*/
- public function getVersion() {
+ public function getVersion()
+ {
+ if (isset(self::$version)) {
+ return self::$version;
+ }
if (0 !== $this->process->execute('git --version', $output)) {
- throw new \RuntimeException(self::sanitizeUrl('Failed retrieve git version, git was not found, check that it is installed and in your PATH env.' . "\n\n" . $this->process->getErrorOutput()));
+ return;
}
- if (preg_match('/^git version (.*)/', $output, $matches) !== 1) {
- throw new \RuntimeException('git --version output seems to have changed, expected "git version x.y.z".');
+ if (preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
+ return self::$version = $matches[1];
}
- return $matches[1];
}
}
diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php
index b1a0446d1..297362a44 100644
--- a/tests/Composer/Test/Downloader/GitDownloaderTest.php
+++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php
@@ -36,6 +36,11 @@ class GitDownloaderTest extends TestCase
if (is_dir($this->workingDir)) {
$this->fs->removeDirectory($this->workingDir);
}
+
+ // reset the static version cache
+ $refl = new \ReflectionProperty('Composer\Util\Git', 'version');
+ $refl->setAccessible(true);
+ $refl->setValue(null, null);
}
protected function setupConfig($config = null) {