diff --git a/src/Composer/Downloader/DownloadManager.php b/src/Composer/Downloader/DownloadManager.php index d59be4530..a4ac66006 100644 --- a/src/Composer/Downloader/DownloadManager.php +++ b/src/Composer/Downloader/DownloadManager.php @@ -74,6 +74,41 @@ class DownloadManager return $this->downloaders[$type]; } + /** + * Returns downloader for already installed package. + * + * @param PackageInterface $package package instance + * + * @return DownloaderInterface + * + * @throws InvalidArgumentException if package has no installation source specified + * @throws LogicException if specific downloader used to load package with + * wrong type + */ + public function getDownloaderForInstalledPackage(PackageInterface $package) + { + $installationSource = $package->getInstallationSource(); + + if ('dist' === $installationSource) { + $downloader = $this->getDownloader($package->getDistType()); + } elseif ('source' === $installationSource) { + $downloader = $this->getDownloader($package->getSourceType()); + } else { + throw new \InvalidArgumentException( + 'Package '.$package.' seems not been installed properly' + ); + } + + if ($installationSource !== $downloader->getInstallationSource()) { + throw new \LogicException(sprintf( + 'Downloader "%s" is a %s type downloader and can not be used to download %s', + get_class($downloader), $downloader->getInstallationSource(), $installationSource + )); + } + + return $downloader; + } + /** * Downloads package into target dir. * @@ -81,8 +116,6 @@ class DownloadManager * @param string $targetDir target dir * @param Boolean $preferSource prefer installation from source * - * @return string downloader type (source/dist) - * * @throws InvalidArgumentException if package have no urls to download from */ public function download(PackageInterface $package, $targetDir, $preferSource = null) @@ -92,20 +125,17 @@ class DownloadManager $distType = $package->getDistType(); if (!($preferSource && $sourceType) && $distType) { - $downloader = $this->getDownloader($distType); $package->setInstallationSource('dist'); - $downloader->distDownload($package, $targetDir); - return 'dist'; - } - - if ($sourceType) { - $downloader = $this->getDownloader($sourceType); + } elseif ($sourceType) { $package->setInstallationSource('source'); - $downloader->sourceDownload($package, $targetDir); - return 'source'; + } else { + throw new \InvalidArgumentException( + 'Package '.$package.' should have source or dist specified' + ); } - throw new \InvalidArgumentException('Package should have dist or source specified'); + $downloader = $this->getDownloaderForInstalledPackage($package); + $downloader->download($package, $targetDir); } /** @@ -119,15 +149,10 @@ class DownloadManager */ public function update(PackageInterface $initial, PackageInterface $target, $targetDir) { - if (null === $installationType = $initial->getInstallationSource()) { - throw new \InvalidArgumentException( - 'Package '.$initial.' was not been installed propertly and can not be updated' - ); - } + $downloader = $this->getDownloaderForInstalledPackage($initial); + $installationSource = $initial->getInstallationSource(); - $useSource = 'source' === $installationType; - - if (!$useSource) { + if ('dist' === $installationSource) { $initialType = $initial->getDistType(); $targetType = $target->getDistType(); } else { @@ -135,15 +160,12 @@ class DownloadManager $targetType = $target->getSourceType(); } - $downloader = $this->getDownloader($initialType); - if ($initialType === $targetType) { - $target->setInstallationSource($installationType); - $method = $useSource ? 'sourceUpdate' : 'distUpdate'; - $downloader->$method($initial, $target, $targetDir); + $target->setInstallationSource($installationSource); + $downloader->update($initial, $target, $targetDir); } else { $downloader->remove($initial, $targetDir); - $this->download($target, $targetDir, $useSource); + $this->download($target, $targetDir, 'source' === $installationSource); } } @@ -155,14 +177,7 @@ class DownloadManager */ public function remove(PackageInterface $package, $targetDir) { - if (null === $installationType = $package->getInstallationSource()) { - throw new \InvalidArgumentException( - 'Package '.$package.' was not been installed propertly and can not be removed' - ); - } - - $useSource = 'source' === $installationType; - $downloaderType = $useSource ? $package->getSourceType() : $package->getDistType(); - $this->getDownloader($downloaderType)->remove($package, $targetDir); + $downloader = $this->getDownloaderForInstalledPackage($package); + $downloader->remove($package, $targetDir); } } diff --git a/src/Composer/Downloader/DownloaderInterface.php b/src/Composer/Downloader/DownloaderInterface.php index 0c6215c52..8c6ed4c07 100644 --- a/src/Composer/Downloader/DownloaderInterface.php +++ b/src/Composer/Downloader/DownloaderInterface.php @@ -23,29 +23,19 @@ use Composer\Package\PackageInterface; interface DownloaderInterface { /** - * Downloads specific package into specific folder from dist. + * Returns installation source (either source or dist). * - * @param PackageInterface $package package instance - * @param string $path download path + * @return string "source" or "dist" */ - function distDownload(PackageInterface $package, $path); + function getInstallationSource(); /** - * Downloads specific package into specific folder from source. + * Downloads specific package into specific folder. * * @param PackageInterface $package package instance * @param string $path download path */ - function sourceDownload(PackageInterface $package, $path); - - /** - * Updates specific package in specific folder from initial to target version. - * - * @param PackageInterface $initial initial package - * @param PackageInterface $target updated package - * @param string $path download path - */ - function distUpdate(PackageInterface $initial, PackageInterface $target, $path); + function download(PackageInterface $package, $path); /** * Updates specific package in specific folder from initial to target version. @@ -54,7 +44,7 @@ interface DownloaderInterface * @param PackageInterface $target updated package * @param string $path download path */ - function sourceUpdate(PackageInterface $initial, PackageInterface $target, $path); + function update(PackageInterface $initial, PackageInterface $target, $path); /** * Removes specific package from specific folder. diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index 849122608..32fb186f9 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -24,50 +24,19 @@ abstract class FileDownloader implements DownloaderInterface /** * {@inheritDoc} */ - public function distDownload(PackageInterface $package, $path) + public function getInstallationSource() { - $this->download($package->getDistUrl(), $path, $package->getDistSha1Checksum()); + return 'dist'; } /** * {@inheritDoc} */ - public function sourceDownload(PackageInterface $package, $path) + public function download(PackageInterface $package, $path) { - $this->download($package->getSourceUrl(), $path); - } - - /** - * {@inheritDoc} - */ - public function distUpdate(PackageInterface $initial, PackageInterface $target, $path) - { - $fs = new Util\Filesystem(); - $fs->remove($path); - $this->download($target->getDistUrl(), $path, $target->getDistSha1Checksum()); - } - - /** - * {@inheritDoc} - */ - public function sourceUpdate(PackageInterface $initial, PackageInterface $target, $path) - { - $fs = new Util\Filesystem(); - $fs->remove($path); - $this->download($target->getSourceUrl(), $path); - } - - /** - * {@inheritDoc} - */ - public function remove(PackageInterface $package, $path) - { - $fs = new Util\Filesystem(); - $fs->remove($path); - } + $url = $package->getDistUrl(); + $checksum = $package->getDistSha1Checksum(); - public function download($url, $path, $checksum = null) - { if (!is_dir($path)) { if (file_exists($path)) { throw new \UnexpectedValueException($path.' exists and is not a directory'); @@ -112,6 +81,25 @@ abstract class FileDownloader implements DownloaderInterface } } + /** + * {@inheritDoc} + */ + public function update(PackageInterface $initial, PackageInterface $target, $path) + { + $fs = new Util\Filesystem(); + $fs->remove($path); + $this->download($target, $path); + } + + /** + * {@inheritDoc} + */ + public function remove(PackageInterface $package, $path) + { + $fs = new Util\Filesystem(); + $fs->remove($path); + } + /** * Extract file to directory * @@ -119,4 +107,4 @@ abstract class FileDownloader implements DownloaderInterface * @param string $path Directory */ protected abstract function extract($file, $path); -} \ No newline at end of file +} diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index df13de9cb..53e30b808 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -22,17 +22,15 @@ class GitDownloader implements DownloaderInterface /** * {@inheritDoc} */ - public function distDownload(PackageInterface $package, $path) + public function getInstallationSource() { - $url = escapeshellarg($package->getDistUrl()); - $ref = escapeshellarg($package->getDistReference()); - system(sprintf('git archive --format=tar --prefix=%s --remote=%s %s | tar -xf -', $path, $url, $ref)); + return 'source'; } /** * {@inheritDoc} */ - public function sourceDownload(PackageInterface $package, $path) + public function download(PackageInterface $package, $path) { if (!$package->getSourceReference()) { throw new \InvalidArgumentException('The given package is missing reference information'); @@ -46,15 +44,7 @@ class GitDownloader implements DownloaderInterface /** * {@inheritDoc} */ - public function distUpdate(PackageInterface $initial, PackageInterface $target, $path) - { - throw new \Exception('Updating dist installs from git is not implemented yet'); - } - - /** - * {@inheritDoc} - */ - public function sourceUpdate(PackageInterface $initial, PackageInterface $target, $path) + public function update(PackageInterface $initial, PackageInterface $target, $path) { if (!$target->getSourceReference()) { throw new \InvalidArgumentException('The given package is missing reference information'); diff --git a/tests/Composer/Test/Downloader/DownloadManagerTest.php b/tests/Composer/Test/Downloader/DownloadManagerTest.php index 947b48dfd..fd55f77e6 100644 --- a/tests/Composer/Test/Downloader/DownloadManagerTest.php +++ b/tests/Composer/Test/Downloader/DownloadManagerTest.php @@ -28,6 +28,149 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase $manager->getDownloader('unregistered'); } + public function testGetDownloaderForIncorrectlyInstalledPackage() + { + $package = $this->createPackageMock(); + $package + ->expects($this->once()) + ->method('getInstallationSource') + ->will($this->returnValue(null)); + + $manager = new DownloadManager(); + + $this->setExpectedException('InvalidArgumentException'); + + $manager->getDownloaderForInstalledPackage($package); + } + + public function testGetDownloaderForCorrectlyInstalledDistPackage() + { + $package = $this->createPackageMock(); + $package + ->expects($this->once()) + ->method('getInstallationSource') + ->will($this->returnValue('dist')); + $package + ->expects($this->once()) + ->method('getDistType') + ->will($this->returnValue('pear')); + + $downloader = $this->createDownloaderMock(); + $downloader + ->expects($this->once()) + ->method('getInstallationSource') + ->will($this->returnValue('dist')); + + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloader')) + ->getMock(); + + $manager + ->expects($this->once()) + ->method('getDownloader') + ->with('pear') + ->will($this->returnValue($downloader)); + + $this->assertSame($downloader, $manager->getDownloaderForInstalledPackage($package)); + } + + public function testGetDownloaderForIncorrectlyInstalledDistPackage() + { + $package = $this->createPackageMock(); + $package + ->expects($this->once()) + ->method('getInstallationSource') + ->will($this->returnValue('dist')); + $package + ->expects($this->once()) + ->method('getDistType') + ->will($this->returnValue('git')); + + $downloader = $this->createDownloaderMock(); + $downloader + ->expects($this->exactly(2)) + ->method('getInstallationSource') + ->will($this->returnValue('source')); + + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloader')) + ->getMock(); + + $manager + ->expects($this->once()) + ->method('getDownloader') + ->with('git') + ->will($this->returnValue($downloader)); + + $this->setExpectedException('LogicException'); + + $manager->getDownloaderForInstalledPackage($package); + } + + public function testGetDownloaderForCorrectlyInstalledSourcePackage() + { + $package = $this->createPackageMock(); + $package + ->expects($this->once()) + ->method('getInstallationSource') + ->will($this->returnValue('source')); + $package + ->expects($this->once()) + ->method('getSourceType') + ->will($this->returnValue('git')); + + $downloader = $this->createDownloaderMock(); + $downloader + ->expects($this->once()) + ->method('getInstallationSource') + ->will($this->returnValue('source')); + + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloader')) + ->getMock(); + + $manager + ->expects($this->once()) + ->method('getDownloader') + ->with('git') + ->will($this->returnValue($downloader)); + + $this->assertSame($downloader, $manager->getDownloaderForInstalledPackage($package)); + } + + public function testGetDownloaderForIncorrectlyInstalledSourcePackage() + { + $package = $this->createPackageMock(); + $package + ->expects($this->once()) + ->method('getInstallationSource') + ->will($this->returnValue('source')); + $package + ->expects($this->once()) + ->method('getSourceType') + ->will($this->returnValue('pear')); + + $downloader = $this->createDownloaderMock(); + $downloader + ->expects($this->exactly(2)) + ->method('getInstallationSource') + ->will($this->returnValue('dist')); + + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloader')) + ->getMock(); + + $manager + ->expects($this->once()) + ->method('getDownloader') + ->with('pear') + ->will($this->returnValue($downloader)); + + $this->setExpectedException('LogicException'); + + $manager->getDownloaderForInstalledPackage($package); + } + public function testFullPackageDownload() { $package = $this->createPackageMock(); @@ -45,14 +188,20 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase ->method('setInstallationSource') ->with('dist'); - $pearDownloader = $this->createDownloaderMock(); - $pearDownloader + $downloader = $this->createDownloaderMock(); + $downloader ->expects($this->once()) - ->method('distDownload') + ->method('download') ->with($package, 'target_dir'); - $manager = new DownloadManager(); - $manager->setDownloader('pear', $pearDownloader); + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloaderForInstalledPackage')) + ->getMock(); + $manager + ->expects($this->once()) + ->method('getDownloaderForInstalledPackage') + ->with($package) + ->will($this->returnValue($downloader)); $manager->download($package, 'target_dir'); } @@ -92,14 +241,20 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase ->method('setInstallationSource') ->with('dist'); - $pearDownloader = $this->createDownloaderMock(); - $pearDownloader + $downloader = $this->createDownloaderMock(); + $downloader ->expects($this->once()) - ->method('distDownload') + ->method('download') ->with($package, 'target_dir'); - $manager = new DownloadManager(); - $manager->setDownloader('pear', $pearDownloader); + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloaderForInstalledPackage')) + ->getMock(); + $manager + ->expects($this->once()) + ->method('getDownloaderForInstalledPackage') + ->with($package) + ->will($this->returnValue($downloader)); $manager->download($package, 'target_dir'); } @@ -115,21 +270,28 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase ->expects($this->once()) ->method('getDistType') ->will($this->returnValue(null)); + $package ->expects($this->once()) ->method('setInstallationSource') ->with('source'); - $gitDownloader = $this->createDownloaderMock(); - $gitDownloader + $downloader = $this->createDownloaderMock(); + $downloader ->expects($this->once()) - ->method('sourceDownload') - ->with($package, 'vendor/pkg'); + ->method('download') + ->with($package, 'target_dir'); - $manager = new DownloadManager(); - $manager->setDownloader('git', $gitDownloader); + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloaderForInstalledPackage')) + ->getMock(); + $manager + ->expects($this->once()) + ->method('getDownloaderForInstalledPackage') + ->with($package) + ->will($this->returnValue($downloader)); - $manager->download($package, 'vendor/pkg'); + $manager->download($package, 'target_dir'); } public function testFullPackageDownloadWithSourcePreferred() @@ -149,17 +311,23 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase ->method('setInstallationSource') ->with('source'); - $gitDownloader = $this->createDownloaderMock(); - $gitDownloader + $downloader = $this->createDownloaderMock(); + $downloader ->expects($this->once()) - ->method('sourceDownload') - ->with($package, 'vendor/pkg'); + ->method('download') + ->with($package, 'target_dir'); - $manager = new DownloadManager(); - $manager->setDownloader('git', $gitDownloader); - $manager->preferSource(); + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloaderForInstalledPackage')) + ->getMock(); + $manager + ->expects($this->once()) + ->method('getDownloaderForInstalledPackage') + ->with($package) + ->will($this->returnValue($downloader)); - $manager->download($package, 'vendor/pkg'); + $manager->preferSource(); + $manager->download($package, 'target_dir'); } public function testDistOnlyPackageDownloadWithSourcePreferred() @@ -179,16 +347,22 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase ->method('setInstallationSource') ->with('dist'); - $pearDownloader = $this->createDownloaderMock(); - $pearDownloader + $downloader = $this->createDownloaderMock(); + $downloader ->expects($this->once()) - ->method('distDownload') + ->method('download') ->with($package, 'target_dir'); - $manager = new DownloadManager(); - $manager->setDownloader('pear', $pearDownloader); - $manager->preferSource(); + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloaderForInstalledPackage')) + ->getMock(); + $manager + ->expects($this->once()) + ->method('getDownloaderForInstalledPackage') + ->with($package) + ->will($this->returnValue($downloader)); + $manager->preferSource(); $manager->download($package, 'target_dir'); } @@ -209,17 +383,23 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase ->method('setInstallationSource') ->with('source'); - $gitDownloader = $this->createDownloaderMock(); - $gitDownloader + $downloader = $this->createDownloaderMock(); + $downloader ->expects($this->once()) - ->method('sourceDownload') - ->with($package, 'vendor/pkg'); + ->method('download') + ->with($package, 'target_dir'); - $manager = new DownloadManager(); - $manager->setDownloader('git', $gitDownloader); - $manager->preferSource(); + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloaderForInstalledPackage')) + ->getMock(); + $manager + ->expects($this->once()) + ->method('getDownloaderForInstalledPackage') + ->with($package) + ->will($this->returnValue($downloader)); - $manager->download($package, 'vendor/pkg'); + $manager->preferSource(); + $manager->download($package, 'target_dir'); } public function testBadPackageDownloadWithSourcePreferred() @@ -266,11 +446,17 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase $pearDownloader = $this->createDownloaderMock(); $pearDownloader ->expects($this->once()) - ->method('distUpdate') + ->method('update') ->with($initial, $target, 'vendor/bundles/FOS/UserBundle'); - $manager = new DownloadManager(); - $manager->setDownloader('pear', $pearDownloader); + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloaderForInstalledPackage')) + ->getMock(); + $manager + ->expects($this->once()) + ->method('getDownloaderForInstalledPackage') + ->with($initial) + ->will($this->returnValue($pearDownloader)); $manager->update($initial, $target, 'vendor/bundles/FOS/UserBundle'); } @@ -300,14 +486,18 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase ->with($initial, 'vendor/bundles/FOS/UserBundle'); $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') - ->setMethods(array('download')) + ->setMethods(array('getDownloaderForInstalledPackage', 'download')) ->getMock(); + $manager + ->expects($this->once()) + ->method('getDownloaderForInstalledPackage') + ->with($initial) + ->will($this->returnValue($pearDownloader)); $manager ->expects($this->once()) ->method('download') ->with($target, 'vendor/bundles/FOS/UserBundle', false); - $manager->setDownloader('pear', $pearDownloader); $manager->update($initial, $target, 'vendor/bundles/FOS/UserBundle'); } @@ -332,11 +522,17 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase $svnDownloader = $this->createDownloaderMock(); $svnDownloader ->expects($this->once()) - ->method('sourceUpdate') + ->method('update') ->with($initial, $target, 'vendor/pkg'); - $manager = new DownloadManager(); - $manager->setDownloader('svn', $svnDownloader); + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloaderForInstalledPackage', 'download')) + ->getMock(); + $manager + ->expects($this->once()) + ->method('getDownloaderForInstalledPackage') + ->with($initial) + ->will($this->returnValue($svnDownloader)); $manager->update($initial, $target, 'vendor/pkg'); } @@ -366,39 +562,24 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase ->with($initial, 'vendor/pkg'); $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') - ->setMethods(array('download')) + ->setMethods(array('getDownloaderForInstalledPackage', 'download')) ->getMock(); + $manager + ->expects($this->once()) + ->method('getDownloaderForInstalledPackage') + ->with($initial) + ->will($this->returnValue($svnDownloader)); $manager ->expects($this->once()) ->method('download') ->with($target, 'vendor/pkg', true); - $manager->setDownloader('svn', $svnDownloader); $manager->update($initial, $target, 'vendor/pkg'); } - public function testUpdateBadlyInstalledPackage() - { - $initial = $this->createPackageMock(); - $target = $this->createPackageMock(); - - $this->setExpectedException('InvalidArgumentException'); - - $manager = new DownloadManager(); - $manager->update($initial, $target, 'vendor/pkg'); - } - - public function testRemoveDist() + public function testRemove() { $package = $this->createPackageMock(); - $package - ->expects($this->once()) - ->method('getInstallationSource') - ->will($this->returnValue('dist')); - $package - ->expects($this->once()) - ->method('getDistType') - ->will($this->returnValue('pear')); $pearDownloader = $this->createDownloaderMock(); $pearDownloader @@ -406,45 +587,16 @@ class DownloadManagerTest extends \PHPUnit_Framework_TestCase ->method('remove') ->with($package, 'vendor/bundles/FOS/UserBundle'); - $manager = new DownloadManager(); - $manager->setDownloader('pear', $pearDownloader); - - $manager->remove($package, 'vendor/bundles/FOS/UserBundle'); - } - - public function testRemoveSource() - { - $package = $this->createPackageMock(); - $package - ->expects($this->once()) - ->method('getInstallationSource') - ->will($this->returnValue('source')); - $package - ->expects($this->once()) - ->method('getSourceType') - ->will($this->returnValue('svn')); - - $svnDownloader = $this->createDownloaderMock(); - $svnDownloader + $manager = $this->getMockBuilder('Composer\Downloader\DownloadManager') + ->setMethods(array('getDownloaderForInstalledPackage')) + ->getMock(); + $manager ->expects($this->once()) - ->method('remove') - ->with($package, 'vendor/pkg'); - - $manager = new DownloadManager(); - $manager->setDownloader('svn', $svnDownloader); + ->method('getDownloaderForInstalledPackage') + ->with($package) + ->will($this->returnValue($pearDownloader)); - $manager->remove($package, 'vendor/pkg'); - } - - /** - * @expectedException InvalidArgumentException - */ - public function testRemoveBadlyInstalledPackage() - { - $package = $this->createPackageMock(); - $manager = new DownloadManager(); - - $manager->remove($package, 'vendor/pkg'); + $manager->remove($package, 'vendor/bundles/FOS/UserBundle'); } private function createDownloaderMock()