Browse Source

Re-use mirror code from the git driver, refs #5384

Jordi Boggiano 8 years ago
parent
commit
4998ee27b3

+ 4 - 9
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';

+ 2 - 21
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('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$e->getMessage().')</error>');
-                }
-            } 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('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
             }
 
             $cacheUrl = $this->url;

+ 39 - 7
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];
     }
 }

+ 5 - 0
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) {