Skip to content

Commit

Permalink
Attempt to use shallow clones, fixes composer#3449
Browse files Browse the repository at this point in the history
  • Loading branch information
Seldaek committed Feb 25, 2016
1 parent c0883d8 commit f7977c8
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 18 deletions.
25 changes: 16 additions & 9 deletions src/Composer/Downloader/GitDownloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ public function doDownload(PackageInterface $package, $path, $url)

$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 --depth 1 --single-branch %s %s --branch %s || git clone --no-checkout %1$s %2$s)'.
' && cd '.$flag.'%2$s && git remote add composer %1$s && (git fetch composer %3$s || git fetch composer)';
$this->io->writeError(" Cloning ".$ref);

$commandCallable = function ($url) use ($ref, $path, $command) {
return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($path), ProcessExecutor::escape($ref));
$branch = $this->guessBranchName($package);
$commandCallable = function ($url) use ($ref, $path, $command, $branch) {
return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($path), ProcessExecutor::escape($branch));
};

$this->gitUtil->runCommand($commandCallable, $url, $path, true);
Expand All @@ -59,7 +61,7 @@ public function doDownload(PackageInterface $package, $path, $url)
}
$this->setPushUrl($path, $url);

if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
if ($newRef = $this->updateToCommit($path, $ref, $branch, $package->getReleaseDate())) {
if ($package->getDistReference() === $package->getSourceReference()) {
$package->setDistReference($newRef);
}
Expand All @@ -79,14 +81,15 @@ public function doUpdate(PackageInterface $initial, PackageInterface $target, $p

$ref = $target->getSourceReference();
$this->io->writeError(" Checking out ".$ref);
$command = 'git remote set-url composer %s && git fetch composer && git fetch --tags composer';
$command = 'git remote set-url composer %s && (git fetch composer %s || git fetch composer) && git fetch --tags composer';
$branch = $this->guessBranchName($target);

$commandCallable = function ($url) use ($command) {
return sprintf($command, ProcessExecutor::escape($url));
$commandCallable = function ($url) use ($command, $branch) {
return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($branch));
};

$this->gitUtil->runCommand($commandCallable, $url, $path);
if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
if ($newRef = $this->updateToCommit($path, $ref, $branch, $target->getReleaseDate())) {
if ($target->getDistReference() === $target->getSourceReference()) {
$target->setDistReference($newRef);
}
Expand Down Expand Up @@ -228,7 +231,6 @@ protected function updateToCommit($path, $reference, $branch, $date)
// If the non-existent branch is actually the name of a file, the file
// is checked out.
$template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
$branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);

$branches = null;
if (0 === $this->process->execute('git branch -r', $output, $path)) {
Expand Down Expand Up @@ -380,4 +382,9 @@ protected function hasMetadataRepository($path)

return is_dir($path.'/.git');
}

private function guessBranchName(PackageInterface $package)
{
return preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $package->getPrettyVersion());;
}
}
27 changes: 18 additions & 9 deletions tests/Composer/Test/Downloader/GitDownloaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function testDownload()
->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");
$expectedGitCommand = $this->winCompat("(git clone --no-checkout --depth 1 --single-branch 'https://example.com/composer/composer' 'composerPath' --branch 'master' || git clone --no-checkout 'https://example.com/composer/composer' 'composerPath') && cd 'composerPath' && git remote add composer 'https://example.com/composer/composer' && (git fetch composer 'master' || git fetch composer)");
$processExecutor->expects($this->at(0))
->method('execute')
->with($this->equalTo($expectedGitCommand))
Expand Down Expand Up @@ -123,13 +123,13 @@ public function testDownloadUsesVariousProtocolsAndSetsPushUrlForGithub()
->will($this->returnValue('1.0.0'));
$processExecutor = $this->getMock('Composer\Util\ProcessExecutor');

$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");
$expectedGitCommand = $this->winCompat("(git clone --no-checkout --depth 1 --single-branch 'git://github.com/mirrors/composer' 'composerPath' --branch '1.0.0' || git clone --no-checkout 'git://github.com/mirrors/composer' 'composerPath') && cd 'composerPath' && git remote add composer 'git://github.com/mirrors/composer' && (git fetch composer '1.0.0' || git fetch composer)");
$processExecutor->expects($this->at(0))
->method('execute')
->with($this->equalTo($expectedGitCommand))
->will($this->returnValue(1));

$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");
$expectedGitCommand = $this->winCompat("(git clone --no-checkout --depth 1 --single-branch 'https://github.com/mirrors/composer' 'composerPath' --branch '1.0.0' || git clone --no-checkout 'https://github.com/mirrors/composer' 'composerPath') && cd 'composerPath' && git remote add composer 'https://github.com/mirrors/composer' && (git fetch composer '1.0.0' || git fetch composer)");
$processExecutor->expects($this->at(2))
->method('execute')
->with($this->equalTo($expectedGitCommand))
Expand Down Expand Up @@ -189,7 +189,7 @@ public function testDownloadAndSetPushUrlUseCustomVariousProtocolsForGithub($pro
->will($this->returnValue('1.0.0'));
$processExecutor = $this->getMock('Composer\Util\ProcessExecutor');

$expectedGitCommand = $this->winCompat("git clone --no-checkout '{$protocol}://github.com/composer/composer' 'composerPath' && cd 'composerPath' && git remote add composer '{$protocol}://github.com/composer/composer' && git fetch composer");
$expectedGitCommand = $this->winCompat("(git clone --no-checkout --depth 1 --single-branch '{$protocol}://github.com/composer/composer' 'composerPath' --branch '1.0.0' || git clone --no-checkout '{$protocol}://github.com/composer/composer' 'composerPath') && cd 'composerPath' && git remote add composer '{$protocol}://github.com/composer/composer' && (git fetch composer '1.0.0' || git fetch composer)");
$processExecutor->expects($this->at(0))
->method('execute')
->with($this->equalTo($expectedGitCommand))
Expand Down Expand Up @@ -217,14 +217,17 @@ public function testDownloadAndSetPushUrlUseCustomVariousProtocolsForGithub($pro
*/
public function testDownloadThrowsRuntimeExceptionIfGitCommandFails()
{
$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");
$expectedGitCommand = $this->winCompat("(git clone --no-checkout --depth 1 --single-branch 'https://example.com/composer/composer' 'composerPath' --branch '1.0.0' || git clone --no-checkout 'https://example.com/composer/composer' 'composerPath') && cd 'composerPath' && git remote add composer 'https://example.com/composer/composer' && (git fetch composer '1.0.0' || git fetch composer)");
$packageMock = $this->getMock('Composer\Package\PackageInterface');
$packageMock->expects($this->any())
->method('getSourceReference')
->will($this->returnValue('ref'));
$packageMock->expects($this->any())
->method('getSourceUrls')
->will($this->returnValue(array('https://example.com/composer/composer')));
$packageMock->expects($this->any())
->method('getPrettyVersion')
->will($this->returnValue('1.0.0'));
$processExecutor = $this->getMock('Composer\Util\ProcessExecutor');
$processExecutor->expects($this->at(0))
->method('execute')
Expand Down Expand Up @@ -252,7 +255,7 @@ public function testUpdateforPackageWithoutSourceReference()

public function testUpdate()
{
$expectedGitUpdateCommand = $this->winCompat("git remote set-url composer 'git://github.com/composer/composer' && git fetch composer && git fetch --tags composer");
$expectedGitUpdateCommand = $this->winCompat("git remote set-url composer 'git://github.com/composer/composer' && (git fetch composer '1.0.0' || git fetch composer) && git fetch --tags composer");

$packageMock = $this->getMock('Composer\Package\PackageInterface');
$packageMock->expects($this->any())
Expand Down Expand Up @@ -297,7 +300,7 @@ public function testUpdate()
*/
public function testUpdateThrowsRuntimeExceptionIfGitCommandFails()
{
$expectedGitUpdateCommand = $this->winCompat("git remote set-url composer 'git://github.com/composer/composer' && git fetch composer && git fetch --tags composer");
$expectedGitUpdateCommand = $this->winCompat("git remote set-url composer 'git://github.com/composer/composer' && (git fetch composer '1.0.0' || git fetch composer) && git fetch --tags composer");

$packageMock = $this->getMock('Composer\Package\PackageInterface');
$packageMock->expects($this->any())
Expand All @@ -306,6 +309,9 @@ public function testUpdateThrowsRuntimeExceptionIfGitCommandFails()
$packageMock->expects($this->any())
->method('getSourceUrls')
->will($this->returnValue(array('https://github.com/composer/composer')));
$packageMock->expects($this->any())
->method('getPrettyVersion')
->will($this->returnValue('1.0.0'));
$processExecutor = $this->getMock('Composer\Util\ProcessExecutor');
$processExecutor->expects($this->at(0))
->method('execute')
Expand All @@ -327,8 +333,8 @@ public function testUpdateThrowsRuntimeExceptionIfGitCommandFails()

public function testUpdateDoesntThrowsRuntimeExceptionIfGitCommandFailsAtFirstButIsAbleToRecover()
{
$expectedFirstGitUpdateCommand = $this->winCompat("git remote set-url composer '' && git fetch composer && git fetch --tags composer");
$expectedSecondGitUpdateCommand = $this->winCompat("git remote set-url composer 'git://github.com/composer/composer' && git fetch composer && git fetch --tags composer");
$expectedFirstGitUpdateCommand = $this->winCompat("git remote set-url composer '' && (git fetch composer '1.0.0' || git fetch composer) && git fetch --tags composer");
$expectedSecondGitUpdateCommand = $this->winCompat("git remote set-url composer 'git://github.com/composer/composer' && (git fetch composer '1.0.0' || git fetch composer) && git fetch --tags composer");

$packageMock = $this->getMock('Composer\Package\PackageInterface');
$packageMock->expects($this->any())
Expand All @@ -337,6 +343,9 @@ public function testUpdateDoesntThrowsRuntimeExceptionIfGitCommandFailsAtFirstBu
$packageMock->expects($this->any())
->method('getSourceUrls')
->will($this->returnValue(array('/foo/bar', 'https://github.com/composer/composer')));
$packageMock->expects($this->any())
->method('getPrettyVersion')
->will($this->returnValue('1.0.0'));
$processExecutor = $this->getMock('Composer\Util\ProcessExecutor');
$processExecutor->expects($this->at(0))
->method('execute')
Expand Down

0 comments on commit f7977c8

Please sign in to comment.