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");