From 0ad985122df53b26b72df99ac7437b2721213188 Mon Sep 17 00:00:00 2001 From: Robert Lu Date: Wed, 13 Sep 2017 19:50:02 +0800 Subject: [PATCH 1/3] Don't fetch when ref already on local --- src/Composer/Downloader/GitDownloader.php | 29 ++++++++++++++++------- src/Composer/Util/Git.php | 16 +++++++++++++ 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 5cd69d5e4..65936b242 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -12,13 +12,13 @@ namespace Composer\Downloader; +use Composer\Config; +use Composer\IO\IOInterface; use Composer\Package\PackageInterface; +use Composer\Util\Filesystem; use Composer\Util\Git as GitUtil; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; -use Composer\IO\IOInterface; -use Composer\Util\Filesystem; -use Composer\Config; /** * @author Jordi Boggiano @@ -43,30 +43,41 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface GitUtil::cleanEnv(); $path = $this->normalizePath($path); $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/'; - $cacheOptions = ''; $ref = $package->getSourceReference(); $flag = Platform::isWindows() ? '/D ' : ''; // --dissociate option is only available since git 2.3.0-rc0 $gitVersion = $this->gitUtil->getVersion(); $msg = "Cloning ".$this->getShortHash($ref); + + $command = 'git clone --no-checkout %url% %path% && cd '.$flag.'%path% && git remote add composer %url% && git fetch composer'; if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=')) { $this->io->writeError('', true, IOInterface::DEBUG); $this->io->writeError(sprintf(' Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG); try { - $this->gitUtil->syncMirror($url, $cachePath); + $this->gitUtil->lazySyncMirror($url, $cachePath, $ref); if (is_dir($cachePath)) { - $cacheOptions = sprintf('--dissociate --reference %s ', ProcessExecutor::escape($cachePath)); + $command = + 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% ' + . '&& cd '.$flag.'%path% ' + . '&& git remote set-url origin %url% && git remote add composer %url%'; $msg = "Cloning ".$this->getShortHash($ref).' from cache'; } } catch (\RuntimeException $e) { } } - $command = 'git clone --no-checkout %s %s '.$cacheOptions.'&& cd '.$flag.'%2$s && git remote add composer %1$s && git fetch composer'; $this->io->writeError($msg); - $commandCallable = function ($url) use ($ref, $path, $command) { - return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($path), ProcessExecutor::escape($ref)); + $commandCallable = function ($url) use ($path, $command, $cachePath) { + return str_replace( + array('%url%', '%path%', '%cachePath%'), + array( + ProcessExecutor::escape($url), + ProcessExecutor::escape($path), + ProcessExecutor::escape($cachePath), + ), + $command + ); }; $this->gitUtil->runCommand($commandCallable, $url, $path, true); diff --git a/src/Composer/Util/Git.php b/src/Composer/Util/Git.php index a6e199bc9..93351964b 100644 --- a/src/Composer/Util/Git.php +++ b/src/Composer/Util/Git.php @@ -228,6 +228,22 @@ class Git return true; } + public function lazySyncMirror($url, $dir, $ref) + { + if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') { + try { + $commandCallable = function ($ref) { + return sprintf('git cat-file -t %s', ProcessExecutor::escape($ref)); + }; + $this->runCommand($commandCallable, $ref, $dir); + return true; + } catch (\Exception $e) { + } + } + + return $this->syncMirror($url, $dir); + } + private function isAuthenticationFailure($url, &$match) { if (!preg_match('{(https?://)([^/]+)(.*)$}i', $url, $match)) { From e768e297cd233438a12697823347e45f19f9f52a Mon Sep 17 00:00:00 2001 From: Robert Lu Date: Wed, 13 Sep 2017 22:59:47 +0800 Subject: [PATCH 2/3] fetch tag,commit form local but not ref --- src/Composer/Downloader/GitDownloader.php | 4 +++- src/Composer/Util/Git.php | 28 +++++++++++++++++------ 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 65936b242..af3cb75c9 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -55,12 +55,14 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface $this->io->writeError('', true, IOInterface::DEBUG); $this->io->writeError(sprintf(' Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG); try { - $this->gitUtil->lazySyncMirror($url, $cachePath, $ref); + $cached = $this->gitUtil->fetchRef($url, $cachePath, $ref); if (is_dir($cachePath)) { $command = 'git clone --no-checkout %cachePath% %path% --dissociate --reference %cachePath% ' . '&& cd '.$flag.'%path% ' . '&& git remote set-url origin %url% && git remote add composer %url%'; + if (!$cached) + $command .= ' && git fetch composer'; $msg = "Cloning ".$this->getShortHash($ref).' from cache'; } } catch (\RuntimeException $e) { diff --git a/src/Composer/Util/Git.php b/src/Composer/Util/Git.php index 93351964b..fcc83f9f2 100644 --- a/src/Composer/Util/Git.php +++ b/src/Composer/Util/Git.php @@ -228,20 +228,34 @@ class Git return true; } - public function lazySyncMirror($url, $dir, $ref) + public function fetchRef($url, $dir, $ref) { if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') { try { - $commandCallable = function ($ref) { - return sprintf('git cat-file -t %s', ProcessExecutor::escape($ref)); - }; - $this->runCommand($commandCallable, $ref, $dir); - return true; + $isTag = $isRef = $actualCommit = false; + $escapedRef = ProcessExecutor::escape($ref); + $exitCode = $this->process->execute(sprintf('git show-ref --tags %s', $escapedRef), $output, $dir); + if (!$exitCode) + $isTag = true; + $exitCode = $this->process->execute(sprintf('git show-ref %s', $escapedRef), $output, $dir); + if (!$exitCode) + $isRef = true; + $exitCode = $this->process->execute(sprintf('git cat-file -t %s', $escapedRef), $output, $dir); + if (!$exitCode && trim($output) == "commit") + $actualCommit = true; + + if ($isTag){ + return true; + } + if (!$isRef && $actualCommit) { + return true; + } } catch (\Exception $e) { } } - return $this->syncMirror($url, $dir); + $this->syncMirror($url, $dir); + return false; } private function isAuthenticationFailure($url, &$match) From 3ce71a55bfa9206031c77687ff37fad0345547e5 Mon Sep 17 00:00:00 2001 From: Robert Lu Date: Wed, 13 Sep 2017 20:35:30 +0800 Subject: [PATCH 3/3] fix unittest --- tests/Composer/Test/Downloader/GitDownloaderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php index e0081d990..f5aa4fe9e 100644 --- a/tests/Composer/Test/Downloader/GitDownloaderTest.php +++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php @@ -173,7 +173,7 @@ class GitDownloaderTest extends TestCase return 0; })); - $expectedGitCommand = $this->winCompat(sprintf("git clone --no-checkout 'https://example.com/composer/composer' 'composerPath' --dissociate --reference '%s' && cd 'composerPath' && git remote add composer 'https://example.com/composer/composer' && git fetch composer", $cachePath)); + $expectedGitCommand = $this->winCompat(sprintf("git clone --no-checkout '%1\$s' 'composerPath' --dissociate --reference '%1\$s' && cd 'composerPath' && git remote set-url origin 'https://example.com/composer/composer' && git remote add composer 'https://example.com/composer/composer' && git fetch composer", $cachePath)); $processExecutor->expects($this->at(2)) ->method('execute') ->with($this->equalTo($expectedGitCommand))