Simulate apps database schema update on upgrade

When upgrade, also simulate the database schema update for apps before
doing the actual upgrade.
This commit is contained in:
Vincent Petry 2014-06-04 16:40:53 +02:00
parent 5adb8f0a8a
commit 5b97369b00
7 changed files with 103 additions and 39 deletions

View File

@ -15,6 +15,9 @@ if (OC::checkUpgrade(false)) {
$updater->listen('\OC\Updater', 'dbUpgrade', function () use ($eventSource, $l) {
$eventSource->send('success', (string)$l->t('Updated database'));
});
$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use ($eventSource, $l) {
$eventSource->send('success', (string)$l->t('Checked database schema update'));
});
$updater->listen('\OC\Updater', 'disabledApps', function ($appList) use ($eventSource, $l) {
$list = array();
foreach ($appList as $appId) {

View File

@ -56,6 +56,9 @@ class Upgrade extends Command {
$updater->listen('\OC\Updater', 'dbUpgrade', function () use($output) {
$output->writeln('<info>Updated database</info>');
});
$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($output) {
$output->writeln('<info>Checked database schema update</info>');
});
$updater->listen('\OC\Updater', 'disabledApps', function ($appList) use($output) {
$output->writeln('<info>Disabled incompatible apps: ' . implode(', ', $appList) . '</info>');
});

View File

@ -28,7 +28,7 @@
this.addMessage(t(
'core',
'Updating {productName} to version {version}, this may take a while.', {
productName: OC.theme.name,
productName: OC.theme.name || 'ownCloud',
version: OC.config.versionstring
}),
'bold'

View File

@ -875,6 +875,18 @@ class OC_App {
}
}
public static function shouldUpgrade($app) {
$versions = self::getAppVersions();
$currentVersion = OC_App::getAppVersion($app);
if ($currentVersion) {
$installedVersion = $versions[$app];
if (version_compare($currentVersion, $installedVersion, '>')) {
return true;
}
}
return false;
}
/**
* check if the app needs updating and update when needed
*
@ -885,26 +897,27 @@ class OC_App {
return;
}
self::$checkedApps[] = $app;
$versions = self::getAppVersions();
$currentVersion = OC_App::getAppVersion($app);
if ($currentVersion) {
$installedVersion = $versions[$app];
if (version_compare($currentVersion, $installedVersion, '>')) {
$info = self::getAppInfo($app);
OC_Log::write($app,
'starting app upgrade from ' . $installedVersion . ' to ' . $currentVersion,
OC_Log::DEBUG);
try {
OC_App::updateApp($app);
OC_Hook::emit('update', 'success', 'Updated ' . $info['name'] . ' app');
} catch (Exception $e) {
OC_Hook::emit('update', 'failure', 'Failed to update ' . $info['name'] . ' app: ' . $e->getMessage());
$l = OC_L10N::get('lib');
throw new RuntimeException($l->t('Failed to upgrade "%s".', array($app)), 0, $e);
}
OC_Appconfig::setValue($app, 'installed_version', OC_App::getAppVersion($app));
}
if (!self::shouldUpgrade($app)) {
return;
}
$versions = self::getAppVersions();
$installedVersion = $versions[$app];
$currentVersion = OC_App::getAppVersion($app);
OC_Log::write(
$app,
'starting app upgrade from ' . $installedVersion . ' to ' . $currentVersion,
OC_Log::DEBUG
);
$info = self::getAppInfo($app);
try {
OC_App::updateApp($app);
OC_Hook::emit('update', 'success', 'Updated ' . $info['name'] . ' app');
} catch (Exception $e) {
OC_Hook::emit('update', 'failure', 'Failed to update ' . $info['name'] . ' app: ' . $e->getMessage());
$l = OC_L10N::get('lib');
throw new RuntimeException($l->t('Failed to upgrade "%s".', array($app)), 0, $e);
}
OC_Appconfig::setValue($app, 'installed_version', OC_App::getAppVersion($app));
}
/**

View File

@ -307,15 +307,21 @@ class OC_DB {
/**
* update the database schema
* @param string $file file to read structure from
* @param bool $simulate whether to simulate the upgrade on separate tables
* @throws Exception
* @return string|boolean
*/
public static function updateDbFromStructure($file) {
public static function updateDbFromStructure($file, $simulate = false) {
$schemaManager = self::getMDB2SchemaManager();
try {
$result = $schemaManager->updateDbFromStructure($file);
$result = $schemaManager->updateDbFromStructure($file, false, $simulate);
} catch (Exception $e) {
OC_Log::write('core', 'Failed to update database structure ('.$e.')', OC_Log::FATAL);
if ($simulate) {
OC_Log::write('core', 'Database structure update simulation failed ('.$e.')', OC_Log::FATAL);
}
else {
OC_Log::write('core', 'Failed to update database structure ('.$e.')', OC_Log::FATAL);
}
throw $e;
}
return $result;

View File

@ -77,9 +77,10 @@ class MDB2SchemaManager {
* update the database scheme
* @param string $file file to read structure from
* @param bool $generateSql only return the sql needed for the upgrade
* @param bool $simulate whether to simulate on separate tables instead of the real onces
* @return string|boolean
*/
public function updateDbFromStructure($file, $generateSql = false) {
public function updateDbFromStructure($file, $generateSql = false, $simulate = false) {
$platform = $this->conn->getDatabasePlatform();
$schemaReader = new MDB2SchemaReader(\OC_Config::getObject(), $platform);
@ -89,8 +90,12 @@ class MDB2SchemaManager {
if ($generateSql) {
return $migrator->generateChangeScript($toSchema);
} else {
$migrator->checkMigrate($toSchema);
$migrator->migrate($toSchema);
if ($simulate) {
$migrator->checkMigrate($toSchema);
}
else {
$migrator->migrate($toSchema);
}
return true;
}
}

View File

@ -125,29 +125,63 @@ class Updater extends BasicEmitter {
* STOP CONFIG CHANGES FOR OLDER VERSIONS
*/
$canUpgrade = false;
// simulate DB upgrade
try {
\OC_DB::updateDbFromStructure(\OC::$SERVERROOT . '/db_structure.xml');
$this->emit('\OC\Updater', 'dbUpgrade');
// simulate core DB upgrade
\OC_DB::updateDbFromStructure(\OC::$SERVERROOT . '/db_structure.xml', true);
// simulate apps DB upgrade
$version = \OC_Util::getVersion();
$apps = \OC_App::getEnabledApps();
foreach ($apps as $appId) {
$info = \OC_App::getAppInfo($appId);
if (\OC_App::isAppCompatible($version, $info) && \OC_App::shouldUpgrade($appId)) {
if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
\OC_DB::updateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml', true);
}
}
}
$this->emit('\OC\Updater', 'dbSimulateUpgrade');
$canUpgrade = true;
} catch (\Exception $exception) {
$this->emit('\OC\Updater', 'failure', array($exception->getMessage()));
}
\OC_Config::setValue('version', implode('.', \OC_Util::getVersion()));
$disabledApps = \OC_App::checkAppsRequirements();
if (!empty($disabledApps)) {
$this->emit('\OC\Updater', 'disabledApps', array($disabledApps));
if ($canUpgrade) {
// proceed with real upgrade
try {
// do the real upgrade
\OC_DB::updateDbFromStructure(\OC::$SERVERROOT . '/db_structure.xml');
$this->emit('\OC\Updater', 'dbUpgrade');
} catch (\Exception $exception) {
$this->emit('\OC\Updater', 'failure', array($exception->getMessage()));
return false;
}
// TODO: why not do this at the end ?
\OC_Config::setValue('version', implode('.', \OC_Util::getVersion()));
$disabledApps = \OC_App::checkAppsRequirements();
if (!empty($disabledApps)) {
$this->emit('\OC\Updater', 'disabledApps', array($disabledApps));
}
// load all apps to also upgrade enabled apps
\OC_App::loadApps();
$repair = new Repair();
$repair->run();
//Invalidate update feed
\OC_Appconfig::setValue('core', 'lastupdatedat', 0);
}
// load all apps to also upgrade enabled apps
\OC_App::loadApps();
$repair = new Repair();
$repair->run();
//Invalidate update feed
\OC_Appconfig::setValue('core', 'lastupdatedat', 0);
\OC_Config::setValue('maintenance', false);
$this->emit('\OC\Updater', 'maintenanceEnd');
return $canUpgrade;
}
}