1
0
Fork 0

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

pull/5490/head
Jordi Boggiano 2016-07-02 17:20:25 +01:00
parent 55e90093a4
commit 4998ee27b3
4 changed files with 50 additions and 37 deletions

View File

@ -48,15 +48,10 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
$flag = Platform::isWindows() ? '/D ' : ''; $flag = Platform::isWindows() ? '/D ' : '';
// --dissociate option is only available since git 2.3.0-rc0 // --dissociate option is only available since git 2.3.0-rc0
if (version_compare($this->gitUtil->getVersion(), '2.3.0-rc0', '>=')) { $gitVersion = $this->gitUtil->getVersion();
if (!file_exists($cachePath)) { if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=')) {
$this->io->writeError(sprintf(' Cloning to cache at %s', ProcessExecutor::escape($cachePath))); $this->io->writeError(sprintf(' Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
$mirrorCommand = 'git clone --mirror %s %s'; $this->gitUtil->syncMirror($url, $cachePath);
$mirrorCommandCallable = function ($url) use ($cachePath, $mirrorCommand) {
return sprintf($mirrorCommand, ProcessExecutor::escape($url), ProcessExecutor::escape($cachePath));
};
$this->gitUtil->runCommand($mirrorCommandCallable, $url, $path, true);
}
$cacheOptions = sprintf('--dissociate --reference %s ', ProcessExecutor::escape($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'; $command = 'git clone --no-checkout %s %s '.$cacheOptions.'&& cd '.$flag.'%2$s && git remote add composer %1$s && git fetch composer';

View File

@ -58,27 +58,8 @@ class GitDriver extends VcsDriver
} }
$gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs); $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
// update the repo if it is a valid git repository $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
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);
} }
$cacheUrl = $this->url; $cacheUrl = $this->url;

View File

@ -20,6 +20,8 @@ use Composer\IO\IOInterface;
*/ */
class Git class Git
{ {
private static $version;
/** @var IOInterface */ /** @var IOInterface */
protected $io; protected $io;
/** @var Config */ /** @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) private function isAuthenticationFailure($url, &$match)
{ {
if (!preg_match('{(https?://)([^/]+)(.*)$}i', $url, $match)) { if (!preg_match('{(https?://)([^/]+)(.*)$}i', $url, $match)) {
@ -277,16 +307,18 @@ class Git
/** /**
* Retrieves the current git version. * Retrieves the current git version.
* *
* @return string * @return string|null The git version number.
* 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)) { 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) { if (preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
throw new \RuntimeException('git --version output seems to have changed, expected "git version x.y.z".'); return self::$version = $matches[1];
} }
return $matches[1];
} }
} }

View File

@ -36,6 +36,11 @@ class GitDownloaderTest extends TestCase
if (is_dir($this->workingDir)) { if (is_dir($this->workingDir)) {
$this->fs->removeDirectory($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) { protected function setupConfig($config = null) {