From 292bd3f6a3860de38ed8bfcfda8e1c299db43627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Faceira?= Date: Wed, 9 Dec 2015 15:09:56 +0000 Subject: [PATCH 01/11] Use vcs dir as git reference, if existing, to speed up download Also added home dir to default initial settings --- src/Composer/Config.php | 1 + src/Composer/Downloader/GitDownloader.php | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Composer/Config.php b/src/Composer/Config.php index 59306f9d2..d8da9f215 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -59,6 +59,7 @@ class Config 'platform' => array(), 'archive-format' => 'tar', 'archive-dir' => '.', + 'home' => '$HOME' // valid keys without defaults (auth config stuff): // bitbucket-oauth // github-oauth diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 94a8d78d9..c6767d2fe 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -42,10 +42,12 @@ 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 = file_exists($cachePath) ? $cacheOptions = '--reference '.$cachePath.' ' : ''; $ref = $package->getSourceReference(); $flag = Platform::isWindows() ? '/D ' : ''; - $command = 'git clone --no-checkout %s %s && 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'; $this->io->writeError(" Cloning ".$ref); $commandCallable = function ($url) use ($ref, $path, $command) { From 5dd35c590e3768c0fb0796191ca52d3dd3871221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Faceira?= Date: Wed, 9 Dec 2015 18:18:39 +0000 Subject: [PATCH 02/11] Escaped git --reference argument --- src/Composer/Downloader/GitDownloader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index c6767d2fe..261cdf3af 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -43,7 +43,7 @@ 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 = file_exists($cachePath) ? $cacheOptions = '--reference '.$cachePath.' ' : ''; + $cacheOptions = file_exists($cachePath) ? '--reference '.ProcessExecutor::escape($cachePath).' ' : ''; $ref = $package->getSourceReference(); $flag = Platform::isWindows() ? '/D ' : ''; From 7b22b7a5119007454e6be379c571c2bb45d5dacc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Faceira?= Date: Thu, 10 Dec 2015 00:48:29 +0000 Subject: [PATCH 03/11] Use dissociate git option Added the usage of dissociate so that the repos work properly even if the cache gets deleted after the clone --- src/Composer/Downloader/GitDownloader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 261cdf3af..37128d772 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -43,7 +43,7 @@ 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 = file_exists($cachePath) ? '--reference '.ProcessExecutor::escape($cachePath).' ' : ''; + $cacheOptions = file_exists($cachePath) ? '--dissociate --reference '.ProcessExecutor::escape($cachePath).' ' : ''; $ref = $package->getSourceReference(); $flag = Platform::isWindows() ? '/D ' : ''; From 1d733ba21aab47360910bde092f5a7d8042bbfc7 Mon Sep 17 00:00:00 2001 From: Luis Faceira Date: Thu, 10 Dec 2015 15:55:50 -0800 Subject: [PATCH 04/11] GitDownloaderTest uses temp dir as composer home config When creating a DownloaderMock a home config dir is ensured to exist, so that no test fails for lack of it that on a regular run would be set by the Factory --- src/Composer/Config.php | 1 - tests/Composer/Test/Downloader/GitDownloaderTest.php | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Composer/Config.php b/src/Composer/Config.php index d8da9f215..59306f9d2 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -59,7 +59,6 @@ class Config 'platform' => array(), 'archive-format' => 'tar', 'archive-dir' => '.', - 'home' => '$HOME' // valid keys without defaults (auth config stuff): // bitbucket-oauth // github-oauth diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php index 1ad627aac..32ab7927e 100644 --- a/tests/Composer/Test/Downloader/GitDownloaderTest.php +++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php @@ -46,6 +46,10 @@ class GitDownloaderTest extends TestCase if (!$config) { $config = new Config(); } + if (!$config->has('home')) { + $tmpDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'cmptest-'.md5(uniqid('', true)); + $config->merge(array('config' => array('home' => $tmpDir))); + } return new GitDownloader($io, $config, $executor, $filesystem); } From 5bb0433a51b160c06aef212e8d18cb19a2b62087 Mon Sep 17 00:00:00 2001 From: Marco Villegas Date: Sun, 29 May 2016 12:22:55 -0500 Subject: [PATCH 05/11] Provide a way to retirve git version from the related util class. --- src/Composer/Util/Git.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Composer/Util/Git.php b/src/Composer/Util/Git.php index 8d0c423bd..19e0a8e46 100644 --- a/src/Composer/Util/Git.php +++ b/src/Composer/Util/Git.php @@ -271,4 +271,20 @@ class Git throw new \RuntimeException(self::sanitizeUrl($message)); } + + /** + * Retrieves the current git version. + * + * @return string + * The git version number. + */ + public function getVersion() { + 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())); + } + if (strpos($output, 'git version ') === FALSE) { + throw new \RuntimeException('git --version output seems to have changed, expected "git version x.y.z".'); + } + return substr($output, 12); + } } From 7e91e9fd8063c620a27b88b788622568d2d21ec4 Mon Sep 17 00:00:00 2001 From: Marco Villegas Date: Sun, 29 May 2016 12:25:59 -0500 Subject: [PATCH 06/11] Use git cache path to mirror the repository before download to vendor target. --- src/Composer/Downloader/GitDownloader.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 37128d772..272d496e2 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -43,10 +43,21 @@ 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 = file_exists($cachePath) ? '--dissociate --reference '.ProcessExecutor::escape($cachePath).' ' : ''; - $ref = $package->getSourceReference(); $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); + } + } + $cacheOptions = file_exists($cachePath) ? '--dissociate --reference '.ProcessExecutor::escape($cachePath).' ' : ''; $command = 'git clone --no-checkout %s %s '.$cacheOptions.'&& cd '.$flag.'%2$s && git remote add composer %1$s && git fetch composer'; $this->io->writeError(" Cloning ".$ref); From b5c55d51670da9abcbf5e41f19e328309cc6df6a Mon Sep 17 00:00:00 2001 From: Marco Villegas Date: Mon, 30 May 2016 11:58:25 -0500 Subject: [PATCH 07/11] Adjust GitDownloaderTest to include for the new getVersion() method in Git. --- .../Test/Downloader/GitDownloaderTest.php | 65 ++++++++++++++----- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php index 32ab7927e..946143862 100644 --- a/tests/Composer/Test/Downloader/GitDownloaderTest.php +++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php @@ -85,23 +85,31 @@ class GitDownloaderTest extends TestCase ->will($this->returnValue('dev-master')); $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); - $expectedGitCommand = $this->winCompat("git clone --no-checkout 'https://example.com/composer/composer' 'composerPath' && cd 'composerPath' && git remote add composer 'https://example.com/composer/composer' && git fetch composer"); $processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($this->winCompat('git --version'))) + ->will($this->returnCallback(function($command, &$output = null) { + $output = 'git version 1.0.0'; + return 0; + })); + + $expectedGitCommand = $this->winCompat("git clone --no-checkout 'https://example.com/composer/composer' 'composerPath' && cd 'composerPath' && git remote add composer 'https://example.com/composer/composer' && git fetch composer"); + $processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedGitCommand)) ->will($this->returnValue(0)); - $processExecutor->expects($this->at(1)) + $processExecutor->expects($this->at(2)) ->method('execute') ->with($this->equalTo($this->winCompat("git branch -r")), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath'))) ->will($this->returnValue(0)); - $processExecutor->expects($this->at(2)) + $processExecutor->expects($this->at(3)) ->method('execute') ->with($this->equalTo($this->winCompat("git checkout 'master' --")), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath'))) ->will($this->returnValue(0)); - $processExecutor->expects($this->at(3)) + $processExecutor->expects($this->at(4)) ->method('execute') ->with($this->equalTo($this->winCompat("git reset --hard '1234567890123456789012345678901234567890' --")), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath'))) ->will($this->returnValue(0)); @@ -127,41 +135,49 @@ class GitDownloaderTest extends TestCase ->will($this->returnValue('1.0.0')); $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); - $expectedGitCommand = $this->winCompat("git clone --no-checkout 'https://github.com/mirrors/composer' 'composerPath' && cd 'composerPath' && git remote add composer 'https://github.com/mirrors/composer' && git fetch composer"); $processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($this->winCompat('git --version'))) + ->will($this->returnCallback(function($command, &$output = null) { + $output = 'git version 1.0.0'; + return 0; + })); + + $expectedGitCommand = $this->winCompat("git clone --no-checkout 'https://github.com/mirrors/composer' 'composerPath' && cd 'composerPath' && git remote add composer 'https://github.com/mirrors/composer' && git fetch composer"); + $processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedGitCommand)) ->will($this->returnValue(1)); - $processExecutor->expects($this->at(1)) + $processExecutor->expects($this->at(2)) ->method('getErrorOutput') ->with() ->will($this->returnValue('Error1')); $expectedGitCommand = $this->winCompat("git clone --no-checkout 'git@github.com:mirrors/composer' 'composerPath' && cd 'composerPath' && git remote add composer 'git@github.com:mirrors/composer' && git fetch composer"); - $processExecutor->expects($this->at(2)) + $processExecutor->expects($this->at(3)) ->method('execute') ->with($this->equalTo($expectedGitCommand)) ->will($this->returnValue(0)); $expectedGitCommand = $this->winCompat("git remote set-url origin 'https://github.com/composer/composer'"); - $processExecutor->expects($this->at(3)) - ->method('execute') - ->with($this->equalTo($expectedGitCommand), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath'))) - ->will($this->returnValue(0)); - - $expectedGitCommand = $this->winCompat("git remote set-url --push origin 'git@github.com:composer/composer.git'"); $processExecutor->expects($this->at(4)) ->method('execute') ->with($this->equalTo($expectedGitCommand), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath'))) ->will($this->returnValue(0)); + $expectedGitCommand = $this->winCompat("git remote set-url --push origin 'git@github.com:composer/composer.git'"); $processExecutor->expects($this->at(5)) + ->method('execute') + ->with($this->equalTo($expectedGitCommand), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath'))) + ->will($this->returnValue(0)); + + $processExecutor->expects($this->at(6)) ->method('execute') ->with($this->equalTo('git branch -r')) ->will($this->returnValue(0)); - $processExecutor->expects($this->at(6)) + $processExecutor->expects($this->at(7)) ->method('execute') ->with($this->equalTo($this->winCompat("git checkout 'ref' -- && git reset --hard 'ref' --")), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath'))) ->will($this->returnValue(0)); @@ -202,19 +218,27 @@ class GitDownloaderTest extends TestCase ->will($this->returnValue('1.0.0')); $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); - $expectedGitCommand = $this->winCompat("git clone --no-checkout '{$url}' 'composerPath' && cd 'composerPath' && git remote add composer '{$url}' && git fetch composer"); $processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($this->winCompat('git --version'))) + ->will($this->returnCallback(function($command, &$output = null) { + $output = 'git version 1.0.0'; + return 0; + })); + + $expectedGitCommand = $this->winCompat("git clone --no-checkout '{$url}' 'composerPath' && cd 'composerPath' && git remote add composer '{$url}' && git fetch composer"); + $processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedGitCommand)) ->will($this->returnValue(0)); $expectedGitCommand = $this->winCompat("git remote set-url --push origin '{$pushUrl}'"); - $processExecutor->expects($this->at(1)) + $processExecutor->expects($this->at(2)) ->method('execute') ->with($this->equalTo($expectedGitCommand), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath'))) ->will($this->returnValue(0)); - $processExecutor->expects($this->exactly(4)) + $processExecutor->expects($this->exactly(5)) ->method('execute') ->will($this->returnValue(0)); @@ -240,6 +264,13 @@ class GitDownloaderTest extends TestCase ->will($this->returnValue(array('https://example.com/composer/composer'))); $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); $processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($this->winCompat('git --version'))) + ->will($this->returnCallback(function($command, &$output = null) { + $output = 'git version 1.0.0'; + return 0; + })); + $processExecutor->expects($this->at(1)) ->method('execute') ->with($this->equalTo($expectedGitCommand)) ->will($this->returnValue(1)); From 75b88a13fea24de7fea0d2a35691d3087b50a040 Mon Sep 17 00:00:00 2001 From: Marco Villegas Date: Sat, 18 Jun 2016 17:43:25 -0500 Subject: [PATCH 08/11] Use regex to capture git version. --- src/Composer/Util/Git.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Composer/Util/Git.php b/src/Composer/Util/Git.php index 19e0a8e46..d1fb18a09 100644 --- a/src/Composer/Util/Git.php +++ b/src/Composer/Util/Git.php @@ -282,9 +282,9 @@ class Git 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())); } - if (strpos($output, 'git version ') === FALSE) { + if (preg_match('/^git version (.*)/', $output, $matches) !== 1) { throw new \RuntimeException('git --version output seems to have changed, expected "git version x.y.z".'); } - return substr($output, 12); + return $matches[1]; } } From 44f94a7b83a287177bbb912dee17dd660c3ba4c7 Mon Sep 17 00:00:00 2001 From: Marco Villegas Date: Sat, 18 Jun 2016 18:07:53 -0500 Subject: [PATCH 09/11] Prevent duplicate file checking on git download. --- src/Composer/Downloader/GitDownloader.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 272d496e2..9379e01b3 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -43,6 +43,7 @@ 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 ' : ''; @@ -56,8 +57,8 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface }; $this->gitUtil->runCommand($mirrorCommandCallable, $url, $path, true); } + $cacheOptions = sprintf('--dissociate --reference %s ', ProcessExecutor::escape($cachePath)); } - $cacheOptions = file_exists($cachePath) ? '--dissociate --reference '.ProcessExecutor::escape($cachePath).' ' : ''; $command = 'git clone --no-checkout %s %s '.$cacheOptions.'&& cd '.$flag.'%2$s && git remote add composer %1$s && git fetch composer'; $this->io->writeError(" Cloning ".$ref); From cb6cfa9635b1978f288ceec59eb7644a839f23c7 Mon Sep 17 00:00:00 2001 From: Marco Villegas Date: Sat, 18 Jun 2016 19:21:50 -0500 Subject: [PATCH 10/11] Isolate config setup to make it reusable at GitDownloaderTest. --- .../Test/Downloader/GitDownloaderTest.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php index 946143862..dd14b1938 100644 --- a/tests/Composer/Test/Downloader/GitDownloaderTest.php +++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php @@ -38,11 +38,7 @@ class GitDownloaderTest extends TestCase } } - protected function getDownloaderMock($io = null, $config = null, $executor = null, $filesystem = null) - { - $io = $io ?: $this->getMock('Composer\IO\IOInterface'); - $executor = $executor ?: $this->getMock('Composer\Util\ProcessExecutor'); - $filesystem = $filesystem ?: $this->getMock('Composer\Util\Filesystem'); + protected function setupConfig($config = null) { if (!$config) { $config = new Config(); } @@ -50,6 +46,15 @@ class GitDownloaderTest extends TestCase $tmpDir = realpath(sys_get_temp_dir()).DIRECTORY_SEPARATOR.'cmptest-'.md5(uniqid('', true)); $config->merge(array('config' => array('home' => $tmpDir))); } + return $config; + } + + protected function getDownloaderMock($io = null, $config = null, $executor = null, $filesystem = null) + { + $io = $io ?: $this->getMock('Composer\IO\IOInterface'); + $executor = $executor ?: $this->getMock('Composer\Util\ProcessExecutor'); + $filesystem = $filesystem ?: $this->getMock('Composer\Util\Filesystem'); + $config = $this->setupConfig($config); return new GitDownloader($io, $config, $executor, $filesystem); } From 869b3ef954e973a1eddf95cd4abf52af7f80bcd4 Mon Sep 17 00:00:00 2001 From: Marco Villegas Date: Sat, 18 Jun 2016 19:35:34 -0500 Subject: [PATCH 11/11] New test to check git download behavior with cache. --- .../Test/Downloader/GitDownloaderTest.php | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php index dd14b1938..b1a0446d1 100644 --- a/tests/Composer/Test/Downloader/GitDownloaderTest.php +++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php @@ -123,6 +123,65 @@ class GitDownloaderTest extends TestCase $downloader->download($packageMock, 'composerPath'); } + public function testDownloadWithCache() + { + $packageMock = $this->getMock('Composer\Package\PackageInterface'); + $packageMock->expects($this->any()) + ->method('getSourceReference') + ->will($this->returnValue('1234567890123456789012345678901234567890')); + $packageMock->expects($this->any()) + ->method('getSourceUrls') + ->will($this->returnValue(array('https://example.com/composer/composer'))); + $packageMock->expects($this->any()) + ->method('getSourceUrl') + ->will($this->returnValue('https://example.com/composer/composer')); + $packageMock->expects($this->any()) + ->method('getPrettyVersion') + ->will($this->returnValue('dev-master')); + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + + $processExecutor->expects($this->at(0)) + ->method('execute') + ->with($this->equalTo($this->winCompat('git --version'))) + ->will($this->returnCallback(function($command, &$output = null) { + $output = 'git version 2.3.1'; + return 0; + })); + + $config = new Config; + $this->setupConfig($config); + $cachePath = $config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', 'https://example.com/composer/composer').'/'; + $expectedGitCommand = $this->winCompat(sprintf("git clone --mirror 'https://example.com/composer/composer' '%s'", $cachePath)); + $processExecutor->expects($this->at(1)) + ->method('execute') + ->with($this->equalTo($expectedGitCommand)) + ->will($this->returnValue(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)); + $processExecutor->expects($this->at(2)) + ->method('execute') + ->with($this->equalTo($expectedGitCommand)) + ->will($this->returnValue(0)); + + $processExecutor->expects($this->at(3)) + ->method('execute') + ->with($this->equalTo($this->winCompat("git branch -r")), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath'))) + ->will($this->returnValue(0)); + + $processExecutor->expects($this->at(4)) + ->method('execute') + ->with($this->equalTo($this->winCompat("git checkout 'master' --")), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath'))) + ->will($this->returnValue(0)); + + $processExecutor->expects($this->at(5)) + ->method('execute') + ->with($this->equalTo($this->winCompat("git reset --hard '1234567890123456789012345678901234567890' --")), $this->equalTo(null), $this->equalTo($this->winCompat('composerPath'))) + ->will($this->returnValue(0)); + + $downloader = $this->getDownloaderMock(null, $config, $processExecutor); + $downloader->download($packageMock, 'composerPath'); + } + public function testDownloadUsesVariousProtocolsAndSetsPushUrlForGithub() { $packageMock = $this->getMock('Composer\Package\PackageInterface');