From 2da352c4b8b84603548999d9f95b9a9d41499a0d Mon Sep 17 00:00:00 2001 From: Thomas Rueckstiess Date: Wed, 27 Apr 2016 16:04:10 +1000 Subject: [PATCH] rename userData dir and migrate to JSON backend --- package.json | 6 ++- src/app/index.js | 2 +- src/app/migrations/1.2.0.js | 82 +++++++++++++++++++++++++++++++++++ src/app/migrations/index.js | 41 ++++++++++++++---- src/app/models/preferences.js | 8 ++-- src/app/models/user.js | 7 +-- src/main/migrations/1.2.0.js | 48 ++++++++++++++++++++ src/main/migrations/index.js | 48 ++++++++++++++++++++ src/main/window-manager.js | 8 +++- 9 files changed, 230 insertions(+), 20 deletions(-) create mode 100644 src/app/migrations/1.2.0.js create mode 100644 src/main/migrations/1.2.0.js create mode 100644 src/main/migrations/index.js diff --git a/package.json b/package.json index 9f98365b7c6..16faa465c4d 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "get-object-path": "azer/get-object-path#74eb42de0cfd02c14ffdd18552f295aba723d394", "hadron-auto-update-manager": "^0.0.12", "hadron-compile-cache": "^0.0.3", - "hadron-ipc": "^0.0.6", + "hadron-ipc": "^0.0.7", "hadron-module-cache": "^0.0.3", "highlight.js": "^8.9.1", "jquery": "^2.1.4", @@ -125,12 +125,14 @@ "mongodb-ns": "^1.0.3", "mongodb-schema": "^4.2.0", "ms": "^0.7.1", + "npc": "0.0.1", "numeral": "^1.5.3", "pluralize": "^1.2.1", "qs": "^5.2.0", "raf": "^3.1.0", + "rimraf": "^2.5.2", "semver": "^5.1.0", - "storage-mixin": "^0.5.1", + "storage-mixin": "^0.6.0", "turf-destination": "^1.2.1", "turf-distance": "^1.1.0", "turf-point": "^2.0.1", diff --git a/src/app/index.js b/src/app/index.js index c98cc405d22..4ca7d302b8a 100644 --- a/src/app/index.js +++ b/src/app/index.js @@ -1,6 +1,6 @@ /* eslint no-console:0 */ if (process.env.NODE_ENV !== 'production') { - require('debug'); + require('debug').enable('mon*,had*'); require('debug/browser'); require('debug').enable('mon*,had*'); } diff --git a/src/app/migrations/1.2.0.js b/src/app/migrations/1.2.0.js new file mode 100644 index 00000000000..c9c601657c3 --- /dev/null +++ b/src/app/migrations/1.2.0.js @@ -0,0 +1,82 @@ +var Preferences = require('../models/preferences'); +var User = require('../models/user'); +var pkg = require('../../../package.json'); +var async = require('async'); +var app = require('ampersand-app'); + +var PreferenceMigrationModel = Preferences.extend({ + idAttribute: 'id', + namespace: 'Preferences', + storage: { + backend: 'local', + appName: pkg.productName + } +}); + +var UserMigrationModel = User.extend({ + idAttribute: 'id', + namespace: 'Users', + storage: { + backend: 'local', + appName: pkg.productName + } +}); + +// var debug = require('debug')('mongodb-compass:migrations:1.2.0'); + +/** + * Imports the preferences from IndexedDB and converts them to JSON, using + * the `disk` storage backend in the storage-mixin module. + * + * @param {Function} done callback when finished + */ +function convertPreferencesBackendToJSON(done) { + var oldPrefs = new PreferenceMigrationModel(); + oldPrefs.once('sync', function() { + app.preferences.save(oldPrefs.serialize(), { + success: function() { + oldPrefs.destroy(); + done(null); + }, + error: function(model, err) { + done(err); + } + }); + }); + oldPrefs.fetch(); +} + +/** + * Imports the user data from IndexedDB and converts it to JSON, using + * the `disk` storage backend in the storage-mixin module. + * + * @param {Function} done callback when finished + */ +function convertUserBackendToJSON(done) { + var oldUser = new UserMigrationModel(); + oldUser.once('sync', function() { + app.user.save(oldUser.serialize(), { + success: function() { + oldUser.destroy(); + done(null); + }, + error: function(model, err) { + done(err); + } + }); + }); + oldUser.fetch(); +} + +module.exports = function(previousVersion, currentVersion, callback) { + // do migration tasks here + async.series([ + convertPreferencesBackendToJSON, + convertUserBackendToJSON + ], function(err) { + if (err) { + return callback(err); + } + callback(null, 'successful migration to 1.2.0'); + }); +}; diff --git a/src/app/migrations/index.js b/src/app/migrations/index.js index b6976a4dd3f..d84d6861654 100644 --- a/src/app/migrations/index.js +++ b/src/app/migrations/index.js @@ -1,21 +1,25 @@ var pkg = require('../../../package.json'); var Model = require('ampersand-model'); var storageMixin = require('storage-mixin'); +var electronApp = require('electron').remote.app; var migrations = { - '1.1.2': require('./1.1.2') + '1.1.2': require('./1.1.2'), + '1.2.0': require('./1.2.0') }; var migrate = require('app-migrations')(migrations); +var debug = require('debug')('mongodb-compass:migrations'); + function getPreviousVersion(done) { - var MiniPrefModel = Model.extend(storageMixin, { + var DiskPrefModel = Model.extend(storageMixin, { extraProperties: 'ignore', idAttribute: 'id', - namespace: 'Preferences', + namespace: 'AppPreferences', storage: { - backend: 'local', - appName: pkg.productName + backend: 'disk', + basepath: electronApp.getPath('userData') }, props: { id: ['string', true, 'General'], @@ -23,11 +27,29 @@ function getPreviousVersion(done) { } }); - var miniPrefs = new MiniPrefModel(); - miniPrefs.once('sync', function(ret) { - done(null, ret.lastKnownVersion || '0.0.0'); + var IndexedDBPrefModel = DiskPrefModel.extend({ + namespace: 'Preferences', + storage: { + backend: 'local', + appName: pkg.productName + } + }); + + // first try to get previous version from disk-backed (JSON) model + var diskPrefs = new DiskPrefModel(); + diskPrefs.once('sync', function(ret) { + if (ret.lastKnownVersion) { + return done(null, ret.lastKnownVersion); + } + // if that is not present, try IndexedDB-backed model (pre-1.2.0) + var indexedDBPrefs = new IndexedDBPrefModel(); + indexedDBPrefs.once('sync', function(ret2) { + // return version, or 0.0.0 if no version present + return done(null, ret2.lastKnownVersion || '0.0.0'); + }); + indexedDBPrefs.fetch(); }); - miniPrefs.fetch(); + diskPrefs.fetch(); } module.exports = function(done) { @@ -38,6 +60,7 @@ module.exports = function(done) { // strip any prerelease parts off previousVersion = previousVersion.split('-')[0]; var currentVersion = pkg.version.split('-')[0]; + debug('renderer process migrations from %s to %s', previousVersion, currentVersion); migrate(previousVersion, currentVersion, done); }); }; diff --git a/src/app/models/preferences.js b/src/app/models/preferences.js index eb5f44c1f72..53e14f9130d 100644 --- a/src/app/models/preferences.js +++ b/src/app/models/preferences.js @@ -1,17 +1,17 @@ var Model = require('ampersand-model'); var storageMixin = require('storage-mixin'); -var pkg = require('../../../package.json'); var _ = require('lodash'); var format = require('util').format; +var electronApp = require('electron').remote.app; var debug = require('debug')('mongodb-compass:models:preferences'); var Preferences = Model.extend(storageMixin, { extraProperties: 'reject', // prevents bugs idAttribute: 'id', - namespace: 'Preferences', + namespace: 'AppPreferences', storage: { - backend: 'local', - appName: pkg.productName + backend: 'disk', + basepath: electronApp.getPath('userData') }, props: { /** diff --git a/src/app/models/user.js b/src/app/models/user.js index 9b1a7b08cf9..7aa45513e2b 100644 --- a/src/app/models/user.js +++ b/src/app/models/user.js @@ -1,7 +1,8 @@ var Model = require('ampersand-model'); var storageMixin = require('storage-mixin'); var uuid = require('uuid'); -var pkg = require('../../../package.json'); +var electronApp = require('electron').remote.app; + // var debug = require('debug')('scout:user'); @@ -9,8 +10,8 @@ var User = Model.extend(storageMixin, { idAttribute: 'id', namespace: 'Users', storage: { - backend: 'local', - appName: pkg.productName + backend: 'disk', + basepath: electronApp.getPath('userData') }, props: { id: { diff --git a/src/main/migrations/1.2.0.js b/src/main/migrations/1.2.0.js new file mode 100644 index 00000000000..7b4822e8092 --- /dev/null +++ b/src/main/migrations/1.2.0.js @@ -0,0 +1,48 @@ +// var async = require('async'); +var ncp = require('ncp'); +var rimraf = require('rimraf'); +var path = require('path'); +var app = require('electron').app; + +// var debug = require('debug')('mongodb-compass:migrations:1.2.0'); + +/** + * In 1.2.0 we changed the user preferences location directory from + * `mongodb-compass` to `MongoDB Compass`. + * + * This migration moves the directory to the new location. + * + * @param {Function} done callback when finished + */ +function changeUserDataDirectoryLocation(done) { + var oldDir = 'mongodb-compass'; + // check if old preferences directory exists + var oldUserDir = path.join(app.getPath('appData'), oldDir); + var newUserDir = app.getPath('userData'); + try { + ncp(oldUserDir, newUserDir, function(errCp) { + if (errCp) { + return done(errCp); + } + rimraf(oldUserDir, function(errRm) { + if (errRm) { + return done(errRm); + } + done(); + }); + }); + } catch (e) { + // failed migration, handle gracefully + done(new Error('Failed migration ChangeUserDataDirectoryLocation: ' + e.message)); + } +} + +module.exports = function(previousVersion, currentVersion, callback) { + // do migration tasks here + changeUserDataDirectoryLocation(function(err) { + if (err) { + return callback(err); + } + callback(null, 'successful migration to 1.2.0'); + }); +}; diff --git a/src/main/migrations/index.js b/src/main/migrations/index.js new file mode 100644 index 00000000000..e681e2f6f17 --- /dev/null +++ b/src/main/migrations/index.js @@ -0,0 +1,48 @@ +var pkg = require('../../../package.json'); +var Model = require('ampersand-model'); +var storageMixin = require('storage-mixin'); +var electronApp = require('electron').app; + +var migrations = { + '1.2.0': require('./1.2.0') +}; + +var migrate = require('app-migrations')(migrations); + +var debug = require('debug')('mongodb-compass:main:migrations'); + +function getPreviousVersion(done) { + var DiskPrefModel = Model.extend(storageMixin, { + extraProperties: 'ignore', + idAttribute: 'id', + namespace: 'AppPreferences', + storage: { + backend: 'disk', + basepath: electronApp.getPath('userData') + }, + props: { + id: ['string', true, 'General'], + lastKnownVersion: ['string', false, ''] + } + }); + + // try to get previous version from disk-backed (JSON) model, else return 0.0.0 + var diskPrefs = new DiskPrefModel(); + diskPrefs.once('sync', function(ret) { + return done(null, ret.lastKnownVersion || '0.0.0'); + }); + diskPrefs.fetch(); +} + +module.exports = function(done) { + getPreviousVersion(function(err, previousVersion) { + if (err) { + return done(err); + } + // strip any prerelease parts off + previousVersion = previousVersion.split('-')[0]; + var currentVersion = pkg.version.split('-')[0]; + debug('main process migrations from %s to %s', previousVersion, currentVersion); + migrate(previousVersion, currentVersion, done); + }); +}; diff --git a/src/main/window-manager.js b/src/main/window-manager.js index d94285d388b..bd0207d3101 100644 --- a/src/main/window-manager.js +++ b/src/main/window-manager.js @@ -9,6 +9,7 @@ var BrowserWindow = electron.BrowserWindow; var _ = require('lodash'); var app = electron.app; var config = require('./config'); +var migrate = require('./migrations'); var debug = require('debug')('mongodb-compass:electron:window-manager'); var dialog = electron.dialog; var path = require('path'); @@ -229,5 +230,10 @@ app.on('before-quit', function() { * state between application launches. */ app.on('ready', function() { - showConnectDialog(); + migrate(function(err) { + if (err) { + // ignore migration errors silently. + } + showConnectDialog(); + }); });