Merge pull request #18684 from owncloud/explicit-upgrade-version

Explicit upgrade version + prevent downgrades
This commit is contained in:
Morris Jobke 2015-09-09 11:08:55 +02:00
commit c4c9c5ffad
4 changed files with 94 additions and 25 deletions

View File

@ -211,20 +211,27 @@ class Updater extends BasicEmitter {
return $success; return $success;
} }
/**
* Return version from which this version is allowed to upgrade from
*
* @return string allowed previous version
*/
private function getAllowedPreviousVersion() {
// this should really be a JSON file
require \OC::$SERVERROOT . '/version.php';
return implode('.', $OC_VersionCanBeUpgradedFrom);
}
/** /**
* Whether an upgrade to a specified version is possible * Whether an upgrade to a specified version is possible
* @param string $oldVersion * @param string $oldVersion
* @param string $newVersion * @param string $newVersion
* @param string $allowedPreviousVersion
* @return bool * @return bool
*/ */
public function isUpgradePossible($oldVersion, $newVersion) { public function isUpgradePossible($oldVersion, $newVersion, $allowedPreviousVersion) {
$oldVersion = explode('.', $oldVersion); return (version_compare($allowedPreviousVersion, $oldVersion, '<=')
$newVersion = explode('.', $newVersion); && version_compare($oldVersion, $newVersion, '<='));
if($newVersion[0] > ($oldVersion[0] + 1) || $oldVersion[0] > $newVersion[0]) {
return false;
}
return true;
} }
/** /**
@ -259,8 +266,9 @@ class Updater extends BasicEmitter {
*/ */
private function doUpgrade($currentVersion, $installedVersion) { private function doUpgrade($currentVersion, $installedVersion) {
// Stop update if the update is over several major versions // Stop update if the update is over several major versions
if (!self::isUpgradePossible($installedVersion, $currentVersion)) { $allowedPreviousVersion = $this->getAllowedPreviousVersion();
throw new \Exception('Updates between multiple major versions are unsupported.'); if (!self::isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersion)) {
throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
} }
// Update .htaccess files // Update .htaccess files

View File

@ -1456,8 +1456,12 @@ class OC_Util {
if ($config->getSystemValue('installed', false)) { if ($config->getSystemValue('installed', false)) {
$installedVersion = $config->getSystemValue('version', '0.0.0'); $installedVersion = $config->getSystemValue('version', '0.0.0');
$currentVersion = implode('.', OC_Util::getVersion()); $currentVersion = implode('.', OC_Util::getVersion());
if (version_compare($currentVersion, $installedVersion, '>')) { $versionDiff = version_compare($currentVersion, $installedVersion);
if ($versionDiff > 0) {
return true; return true;
} else if ($versionDiff < 0) {
// downgrade attempt, throw exception
throw new \OC\HintException('Downgrading is not supported and is likely to cause unpredictable issues (from ' . $installedVersion . ' to ' . $currentVersion . ')');
} }
// also check for upgrades for apps (independently from the user) // also check for upgrades for apps (independently from the user)

View File

@ -67,14 +67,68 @@ class UpdaterTest extends \Test\TestCase {
*/ */
public function versionCompatibilityTestData() { public function versionCompatibilityTestData() {
return [ return [
['1.0.0.0', '2.2.0', true], ['1', '2', '1', true],
['1.1.1.1', '2.0.0', true], ['2', '2', '2', true],
['5.0.3', '4.0.3', false], ['6.0.5.0', '6.0.6.0', '5.0', true],
['12.0.3', '13.4.5', true], ['5.0.6.0', '7.0.4.0', '6.0', false],
['1', '2', true], // allow upgrading within the same major release
['2', '2', true], ['8.0.0.0', '8.0.0.0', '8.0', true],
['6.0.5', '6.0.6', true], ['8.0.0.0', '8.0.0.4', '8.0', true],
['5.0.6', '7.0.4', false], ['8.0.0.0', '8.0.1.0', '8.0', true],
['8.0.0.0', '8.0.2.0', '8.0', true],
// does not allow downgrading within the same major release
['8.0.1.0', '8.0.0.0', '8.0', false],
['8.0.2.0', '8.0.1.0', '8.0', false],
['8.0.0.4', '8.0.0.0', '8.0', false],
// allows upgrading within the patch version
['8.0.0.0', '8.0.0.1', '8.0', true],
['8.0.0.0', '8.0.0.2', '8.0', true],
// does not allow downgrading within the same major release
['8.0.0.1', '8.0.0.0', '8.0', false],
['8.0.0.2', '8.0.0.0', '8.0', false],
// allow upgrading to the next major release
['8.0.0.0', '8.1.0.0', '8.0', true],
['8.0.0.0', '8.1.1.0', '8.0', true],
['8.0.0.0', '8.1.1.5', '8.0', true],
['8.0.0.2', '8.1.1.5', '8.0', true],
['8.1.0.0', '8.2.0.0', '8.1', true],
['8.1.0.2', '8.2.0.4', '8.1', true],
['8.1.0.5', '8.2.0.1', '8.1', true],
['8.1.0.0', '8.2.1.0', '8.1', true],
['8.1.0.2', '8.2.1.5', '8.1', true],
['8.1.0.5', '8.2.1.1', '8.1', true],
// does not allow downgrading to the previous major release
['8.1.0.0', '8.0.0.0', '7.0', false],
['8.1.1.0', '8.0.0.0', '7.0', false],
// does not allow skipping major releases
['8.0.0.0', '8.2.0.0', '8.1', false],
['8.0.0.0', '8.2.1.0', '8.1', false],
['8.0.0.0', '9.0.1.0', '8.2', false],
['8.0.0.0', '10.0.0.0', '9.3', false],
// allows updating to the next major release
['8.2.0.0', '9.0.0.0', '8.2', true],
['8.2.0.0', '9.0.0.0', '8.2', true],
['8.2.0.0', '9.0.1.0', '8.2', true],
['8.2.0.0', '9.0.1.1', '8.2', true],
['8.2.0.2', '9.0.1.1', '8.2', true],
['8.2.2.0', '9.0.1.0', '8.2', true],
['8.2.2.2', '9.0.1.1', '8.2', true],
['9.0.0.0', '9.1.0.0', '9.0', true],
['9.0.0.0', '9.1.0.2', '9.0', true],
['9.0.0.2', '9.1.0.1', '9.0', true],
['9.1.0.0', '9.2.0.0', '9.1', true],
['9.2.0.0', '9.3.0.0', '9.2', true],
['9.3.0.0', '10.0.0.0', '9.3', true],
// does not allow updating to the next major release (first number)
['9.0.0.0', '8.2.0.0', '8.1', false],
// other cases
['8.0.0.0', '8.1.5.0', '8.0', true],
['8.2.0.0', '9.0.0.0', '8.2', true],
['8.2.0.0', '9.1.0.0', '9.0', false],
['9.0.0.0', '8.1.0.0', '8.0', false],
['9.0.0.0', '8.0.0.0', '7.0', false],
['9.1.0.0', '8.0.0.0', '7.0', false],
['8.2.0.0', '8.1.0.0', '8.0', false],
]; ];
} }
@ -106,9 +160,9 @@ class UpdaterTest extends \Test\TestCase {
* @param string $newVersion * @param string $newVersion
* @param bool $result * @param bool $result
*/ */
public function testIsUpgradePossible($oldVersion, $newVersion, $result) { public function testIsUpgradePossible($oldVersion, $newVersion, $allowedVersion, $result) {
$updater = new Updater($this->httpHelper, $this->config); $updater = new Updater($this->httpHelper, $this->config);
$this->assertSame($result, $updater->isUpgradePossible($oldVersion, $newVersion)); $this->assertSame($result, $updater->isUpgradePossible($oldVersion, $newVersion, $allowedVersion));
} }
public function testCheckInCache() { public function testCheckInCache() {

View File

@ -2,6 +2,7 @@
/** /**
* @author Frank Karlitschek <frank@owncloud.org> * @author Frank Karlitschek <frank@owncloud.org>
* @author Lukas Reschke <lukas@owncloud.com> * @author Lukas Reschke <lukas@owncloud.com>
* @author Vincent Petry <pvince81@owncloud.com>
* *
* @copyright Copyright (c) 2015, ownCloud, Inc. * @copyright Copyright (c) 2015, ownCloud, Inc.
* @license AGPL-3.0 * @license AGPL-3.0
@ -22,14 +23,16 @@
// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades // We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel
// when updating major/minor version number. // when updating major/minor version number.
$OC_Version=array(8, 2, 0, 4); $OC_Version = [8, 2, 0, 4];
// The human readable string // The human readable string
$OC_VersionString='8.2 pre alpha'; $OC_VersionString = '8.2 pre alpha';
$OC_VersionCanBeUpgradedFrom = [8, 1];
// The ownCloud channel // The ownCloud channel
$OC_Channel='git'; $OC_Channel = 'git';
// The build number // The build number
$OC_Build=''; $OC_Build = '';