diff --git a/src/Composer/Downloader/DownloadManager.php b/src/Composer/Downloader/DownloadManager.php index e466bbb09..e1441f182 100644 --- a/src/Composer/Downloader/DownloadManager.php +++ b/src/Composer/Downloader/DownloadManager.php @@ -125,14 +125,14 @@ class DownloadManager $sourceType = $package->getSourceType(); $distType = $package->getDistType(); - if (!($preferSource && $sourceType) && $distType) { + if (!$package->isDev() && !($preferSource && $sourceType) && $distType) { $package->setInstallationSource('dist'); } elseif ($sourceType) { $package->setInstallationSource('source'); + } elseif ($package->isDev()) { + throw new \InvalidArgumentException('Dev package '.$package.' must have a source specified'); } else { - throw new \InvalidArgumentException( - 'Package '.$package.' should have source or dist specified' - ); + throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified'); } $fs = new Filesystem(); diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index a3f0b2b74..8eef0d7ed 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -109,7 +109,9 @@ class LibraryInstaller implements InstallerInterface $this->downloadManager->update($initial, $target, $downloadPath); $this->installBinaries($target); $this->repository->removePackage($initial); - $this->repository->addPackage(clone $target); + if (!$this->repository->hasPackage($target)) { + $this->repository->addPackage(clone $target); + } } /** diff --git a/src/Composer/Package/MemoryPackage.php b/src/Composer/Package/MemoryPackage.php index d1e63e102..a57f2b6f6 100644 --- a/src/Composer/Package/MemoryPackage.php +++ b/src/Composer/Package/MemoryPackage.php @@ -41,6 +41,7 @@ class MemoryPackage extends BasePackage protected $extra = array(); protected $binaries = array(); protected $scripts = array(); + protected $dev; protected $requires = array(); protected $conflicts = array(); @@ -63,6 +64,16 @@ class MemoryPackage extends BasePackage $this->version = $version; $this->prettyVersion = $prettyVersion; + + $this->dev = 'dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4); + } + + /** + * {@inheritDoc} + */ + public function isDev() + { + return $this->dev; } /** diff --git a/src/Composer/Package/PackageInterface.php b/src/Composer/Package/PackageInterface.php index c8f92b581..1f19a835f 100644 --- a/src/Composer/Package/PackageInterface.php +++ b/src/Composer/Package/PackageInterface.php @@ -68,6 +68,13 @@ interface PackageInterface */ function matches($name, LinkConstraintInterface $constraint); + /** + * Returns whether the package is a development virtual package or a concrete one + * + * @return Boolean + */ + function isDev(); + /** * Returns the package type, e.g. library * diff --git a/tests/Composer/Test/Installer/InstallerInstallerTest.php b/tests/Composer/Test/Installer/InstallerInstallerTest.php index 4e2f8c732..eab2d948a 100644 --- a/tests/Composer/Test/Installer/InstallerInstallerTest.php +++ b/tests/Composer/Test/Installer/InstallerInstallerTest.php @@ -67,9 +67,9 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase ->method('getPackages') ->will($this->returnValue(array($this->packages[0]))); $this->repository - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('hasPackage') - ->will($this->returnValue(true)); + ->will($this->onConsecutiveCalls(true, false)); $installer = new InstallerInstallerMock(__DIR__.'/Fixtures/', __DIR__.'/Fixtures/bin', $this->dm, $this->repository, $this->io, $this->im); $test = $this; @@ -90,9 +90,9 @@ class InstallerInstallerTest extends \PHPUnit_Framework_TestCase ->method('getPackages') ->will($this->returnValue(array($this->packages[1]))); $this->repository - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('hasPackage') - ->will($this->returnValue(true)); + ->will($this->onConsecutiveCalls(true, false)); $installer = new InstallerInstallerMock(__DIR__.'/Fixtures/', __DIR__.'/Fixtures/bin', $this->dm, $this->repository, $this->io, $this->im); $test = $this; diff --git a/tests/Composer/Test/Installer/LibraryInstallerTest.php b/tests/Composer/Test/Installer/LibraryInstallerTest.php index 3399345f0..ba86954e3 100644 --- a/tests/Composer/Test/Installer/LibraryInstallerTest.php +++ b/tests/Composer/Test/Installer/LibraryInstallerTest.php @@ -128,10 +128,9 @@ class LibraryInstallerTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue('package1')); $this->repository - ->expects($this->exactly(2)) + ->expects($this->exactly(3)) ->method('hasPackage') - ->with($initial) - ->will($this->onConsecutiveCalls(true, false)); + ->will($this->onConsecutiveCalls(true, false, false)); $this->dm ->expects($this->once())