diff --git a/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php index e090c1b6e..da4695f57 100644 --- a/src/Composer/Downloader/FileDownloader.php +++ b/src/Composer/Downloader/FileDownloader.php @@ -218,7 +218,8 @@ class FileDownloader implements DownloaderInterface $from = $initial->getPrettyVersion(); $to = $target->getPrettyVersion(); - $this->io->writeError(" - Updating " . $name . " (" . $from . " => " . $to . "): ", false); + $actionName = version_compare($from, $to, '<') ? 'Updating' : 'Downgrading'; + $this->io->writeError(" - " . $actionName . " " . $name . " (" . $from . " => " . $to . "): ", false); $this->remove($initial, $path, false); $this->download($target, $path, false); diff --git a/src/Composer/Downloader/VcsDownloader.php b/src/Composer/Downloader/VcsDownloader.php index cdc63e5ec..a0ccacdf1 100644 --- a/src/Composer/Downloader/VcsDownloader.php +++ b/src/Composer/Downloader/VcsDownloader.php @@ -130,7 +130,8 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa $to = $target->getFullPrettyVersion(); } - $this->io->writeError(" - Updating " . $name . " (" . $from . " => " . $to . "): ", false); + $actionName = $this->packageCompare($initial, $target, '>') ? 'Downgrading' : 'Updating'; + $this->io->writeError(" - " . $actionName . " " . $name . " (" . $from . " => " . $to . "): ", false); $this->cleanChanges($initial, $path, true); $urls = $target->getSourceUrls(); @@ -242,6 +243,23 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa } } + /** + * Compare two packages. Always false if both versions are references + * + * @param PackageInterface $initial + * @param PackageInterface $target + * @param string $operation + * @return bool + */ + protected function packageCompare(PackageInterface $initial, PackageInterface $target, $operation = '<') + { + if ($initial->getPrettyVersion() == $target->getPrettyVersion()) { + return false; + } + + return version_compare($initial->getFullPrettyVersion(), $target->getFullPrettyVersion(), $operation); + } + /** * Guarantee that no changes have been made to the local copy * diff --git a/tests/Composer/Test/Downloader/FileDownloaderTest.php b/tests/Composer/Test/Downloader/FileDownloaderTest.php index 1c51c2abe..fab0c43d1 100644 --- a/tests/Composer/Test/Downloader/FileDownloaderTest.php +++ b/tests/Composer/Test/Downloader/FileDownloaderTest.php @@ -205,4 +205,38 @@ class FileDownloaderTest extends TestCase $this->assertContains('checksum verification', $e->getMessage()); } } + + public function testDowngradeShowsAppropriateMessage() + { + $oldPackage = $this->getMock('Composer\Package\PackageInterface'); + $oldPackage->expects($this->once()) + ->method('getPrettyVersion') + ->will($this->returnValue('1.0.0')); + $oldPackage->expects($this->any()) + ->method('getDistUrl') + ->will($this->returnValue($distUrl = 'http://example.com/script.js')); + $oldPackage->expects($this->once()) + ->method('getDistUrls') + ->will($this->returnValue(array($distUrl))); + + $newPackage = $this->getMock('Composer\Package\PackageInterface'); + $newPackage->expects($this->once()) + ->method('getPrettyVersion') + ->will($this->returnValue('1.2.0')); + + $ioMock = $this->getMock('Composer\IO\IOInterface'); + $ioMock->expects(($this->at(0))) + ->method('writeError') + ->with($this->stringContains('Downgrading')); + + $path = $this->getUniqueTmpDirectory(); + touch($path.'/script.js'); + $filesystem = $this->getMock('Composer\Util\Filesystem'); + $filesystem->expects($this->once()) + ->method('removeDirectory') + ->will($this->returnValue(true)); + + $downloader = $this->getDownloader($ioMock, null, null, null, null, $filesystem); + $downloader->update($newPackage, $oldPackage, $path); + } } diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php index 588d4d2ee..2400fdb56 100644 --- a/tests/Composer/Test/Downloader/GitDownloaderTest.php +++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php @@ -596,6 +596,90 @@ composer https://github.com/old/url (push) $downloader->update($packageMock, $packageMock, $this->workingDir); } + public function testDowngradeShowsAppropriateMessage() + { + $oldPackage = $this->getMock('Composer\Package\PackageInterface'); + $oldPackage->expects($this->any()) + ->method('getPrettyVersion') + ->will($this->returnValue('1.0.0')); + $oldPackage->expects($this->any()) + ->method('getFullPrettyVersion') + ->will($this->returnValue('1.0.0')); + $oldPackage->expects($this->any()) + ->method('getSourceReference') + ->will($this->returnValue('ref')); + $oldPackage->expects($this->any()) + ->method('getSourceUrls') + ->will($this->returnValue(array('/foo/bar', 'https://github.com/composer/composer'))); + + $newPackage = $this->getMock('Composer\Package\PackageInterface'); + $newPackage->expects($this->any()) + ->method('getSourceReference') + ->will($this->returnValue('ref')); + $newPackage->expects($this->any()) + ->method('getSourceUrls') + ->will($this->returnValue(array('https://github.com/composer/composer'))); + $newPackage->expects($this->any()) + ->method('getPrettyVersion') + ->will($this->returnValue('1.2.0')); + $newPackage->expects($this->any()) + ->method('getFullPrettyVersion') + ->will($this->returnValue('1.2.0')); + + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + $processExecutor->expects($this->any()) + ->method('execute') + ->will($this->returnValue(0)); + + $ioMock = $this->getMock('Composer\IO\IOInterface'); + $ioMock->expects(($this->at(0))) + ->method('writeError') + ->with($this->stringContains('Downgrading')); + + $this->fs->ensureDirectoryExists($this->workingDir.'/.git'); + $downloader = $this->getDownloaderMock($ioMock, null, $processExecutor); + $downloader->update($newPackage, $oldPackage, $this->workingDir); + } + + public function testNotUsingDowngradingWithReferences() + { + $oldPackage = $this->getMock('Composer\Package\PackageInterface'); + $oldPackage->expects($this->any()) + ->method('getPrettyVersion') + ->will($this->returnValue('ref')); + $oldPackage->expects($this->any()) + ->method('getSourceReference') + ->will($this->returnValue('ref')); + $oldPackage->expects($this->any()) + ->method('getSourceUrls') + ->will($this->returnValue(array('/foo/bar', 'https://github.com/composer/composer'))); + + $newPackage = $this->getMock('Composer\Package\PackageInterface'); + $newPackage->expects($this->any()) + ->method('getSourceReference') + ->will($this->returnValue('ref')); + $newPackage->expects($this->any()) + ->method('getSourceUrls') + ->will($this->returnValue(array('https://github.com/composer/composer'))); + $newPackage->expects($this->any()) + ->method('getPrettyVersion') + ->will($this->returnValue('ref')); + + $processExecutor = $this->getMock('Composer\Util\ProcessExecutor'); + $processExecutor->expects($this->any()) + ->method('execute') + ->will($this->returnValue(0)); + + $ioMock = $this->getMock('Composer\IO\IOInterface'); + $ioMock->expects(($this->at(0))) + ->method('writeError') + ->with($this->stringContains('updating')); + + $this->fs->ensureDirectoryExists($this->workingDir.'/.git'); + $downloader = $this->getDownloaderMock($ioMock, null, $processExecutor); + $downloader->update($newPackage, $oldPackage, $this->workingDir); + } + public function testRemove() { $expectedGitResetCommand = $this->winCompat("cd 'composerPath' && git status --porcelain --untracked-files=no");