From 584bd15b7616a80466b618e76401f6b874fe2f53 Mon Sep 17 00:00:00 2001 From: Katharina Irrgang Date: Thu, 26 Jan 2017 13:12:00 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20=20remove=20database=20version?= =?UTF-8?q?=20(#7894)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refs #7489 - as we are now using a different migration approach (knex-migrator), we don't need to remember the database version anymore - it was once used to check the state of a database and based on it we decided to migrate or not - with knex-migrator everything depends on the migration table entries and the current ghost version you are on - on current master the leftover usage is to add the db version when exporting the database, which can be replaced by reading the ghost version - removing this solves also an interesting migration case with knex-migrator: - you are on 1.0 - you update to 1.1, but 1.1 has no migrations - the db version would remain in 1.0 - because the db version was only updated when knex migrator executed a migration --- MigratorConfig.js | 4 +- core/server/data/export/index.js | 4 +- .../data/migrations/hooks/init/after.js | 40 ++-- .../data/migrations/hooks/migrate/after.js | 40 ++-- core/server/data/schema/default-settings.json | 3 - core/server/data/schema/index.js | 1 - core/server/data/schema/versioning.js | 78 -------- core/server/index.js | 31 ++- core/server/models/settings.js | 4 - core/server/translations/en.json | 11 - core/server/utils/index.js | 3 +- .../test/integration/api/api_settings_spec.js | 10 +- core/test/integration/export_spec.js | 23 +-- core/test/integration/import_spec.js | 73 +------ .../integration/model/model_settings_spec.js | 1 - core/test/unit/exporter_spec.js | 13 +- core/test/unit/migration_spec.js | 7 +- core/test/unit/versioning_spec.js | 189 ------------------ .../utils/fixtures/export/export-000.json | 11 - .../utils/fixtures/export/export-001.json | 13 +- .../utils/fixtures/export/export-002.json | 13 +- .../export/export-003-duplicate-posts.json | 13 +- .../export/export-003-duplicate-tags.json | 11 - .../export/export-003-mu-noOwner.json | 11 - .../utils/fixtures/export/export-003-mu.json | 13 +- .../utils/fixtures/export/export-003.json | 13 +- index.js | 10 +- 27 files changed, 103 insertions(+), 540 deletions(-) delete mode 100644 core/server/data/schema/versioning.js delete mode 100644 core/test/unit/versioning_spec.js diff --git a/MigratorConfig.js b/MigratorConfig.js index 475ec77750..38a488edfd 100644 --- a/MigratorConfig.js +++ b/MigratorConfig.js @@ -1,8 +1,8 @@ var config = require('./core/server/config'), - versioning = require('./core/server/data/schema/versioning'); + utils = require('./core/server/utils'); module.exports = { - currentVersion: versioning.getNewestDatabaseVersion(), + currentVersion: utils.ghostVersion.safe, database: config.get('database'), migrationPath: config.get('paths:migrationPath') }; diff --git a/core/server/data/export/index.js b/core/server/data/export/index.js index 7ffbd3726a..966e8cb58e 100644 --- a/core/server/data/export/index.js +++ b/core/server/data/export/index.js @@ -2,8 +2,8 @@ var _ = require('lodash'), Promise = require('bluebird'), db = require('../../data/db'), commands = require('../schema').commands, - versioning = require('../schema').versioning, serverUtils = require('../../utils'), + ghostVersion = require('../../utils/ghost-version'), errors = require('../../errors'), logging = require('../../logging'), settings = require('../../api/settings'), @@ -36,7 +36,7 @@ exportFileName = function exportFileName() { getVersionAndTables = function getVersionAndTables() { var props = { - version: versioning.getDatabaseVersion(), + version: ghostVersion.full, tables: commands.getTables() }; diff --git a/core/server/data/migrations/hooks/init/after.js b/core/server/data/migrations/hooks/init/after.js index 6e18f285ed..0f260ab3e6 100644 --- a/core/server/data/migrations/hooks/init/after.js +++ b/core/server/data/migrations/hooks/init/after.js @@ -1,30 +1,18 @@ -var errors = require('../../../../errors'), - config = require('../../../../config'), - versioning = require('../../../schema/versioning'), +var config = require('../../../../config'), database = require('../../../db'); -module.exports = function after(options) { - return versioning.getDatabaseVersion(options) - .catch(function (err) { - if (err instanceof errors.DatabaseVersionError && err.code === 'VERSION_DOES_NOT_EXIST') { - return versioning.setDatabaseVersion(options); - } +module.exports = function after() { + // do not close database connection in test mode, because all tests are executed one after another + // this check is not nice, but there is only one other solution i can think of: + // forward a custom object to knex-migrator, which get's forwarded to the hooks + if (config.get('env').match(/testing/g)) { + return; + } - throw err; - }) - .finally(function destroyConnection() { - // do not close database connection in test mode, because all tests are executed one after another - // this check is not nice, but there is only one other solution i can think of: - // forward a custom object to knex-migrator, which get's forwarded to the hooks - if (config.get('env').match(/testing/g)) { - return; - } - - // we need to close the database connection - // the after hook signals the last step of a knex-migrator command - // Example: - // Ghost-CLI calls knexMigrator.init and afterwards it starts Ghost, but Ghost-CLI can't shutdown - // if Ghost keeps a connection alive - return database.knex.destroy(); - }); + // we need to close the database connection + // the after hook signals the last step of a knex-migrator command + // Example: + // Ghost-CLI calls knexMigrator.init and afterwards it starts Ghost, but Ghost-CLI can't shutdown + // if Ghost keeps a connection alive + return database.knex.destroy(); }; diff --git a/core/server/data/migrations/hooks/migrate/after.js b/core/server/data/migrations/hooks/migrate/after.js index 6e18f285ed..0f260ab3e6 100644 --- a/core/server/data/migrations/hooks/migrate/after.js +++ b/core/server/data/migrations/hooks/migrate/after.js @@ -1,30 +1,18 @@ -var errors = require('../../../../errors'), - config = require('../../../../config'), - versioning = require('../../../schema/versioning'), +var config = require('../../../../config'), database = require('../../../db'); -module.exports = function after(options) { - return versioning.getDatabaseVersion(options) - .catch(function (err) { - if (err instanceof errors.DatabaseVersionError && err.code === 'VERSION_DOES_NOT_EXIST') { - return versioning.setDatabaseVersion(options); - } +module.exports = function after() { + // do not close database connection in test mode, because all tests are executed one after another + // this check is not nice, but there is only one other solution i can think of: + // forward a custom object to knex-migrator, which get's forwarded to the hooks + if (config.get('env').match(/testing/g)) { + return; + } - throw err; - }) - .finally(function destroyConnection() { - // do not close database connection in test mode, because all tests are executed one after another - // this check is not nice, but there is only one other solution i can think of: - // forward a custom object to knex-migrator, which get's forwarded to the hooks - if (config.get('env').match(/testing/g)) { - return; - } - - // we need to close the database connection - // the after hook signals the last step of a knex-migrator command - // Example: - // Ghost-CLI calls knexMigrator.init and afterwards it starts Ghost, but Ghost-CLI can't shutdown - // if Ghost keeps a connection alive - return database.knex.destroy(); - }); + // we need to close the database connection + // the after hook signals the last step of a knex-migrator command + // Example: + // Ghost-CLI calls knexMigrator.init and afterwards it starts Ghost, but Ghost-CLI can't shutdown + // if Ghost keeps a connection alive + return database.knex.destroy(); }; diff --git a/core/server/data/schema/default-settings.json b/core/server/data/schema/default-settings.json index a588012120..60b579e34f 100644 --- a/core/server/data/schema/default-settings.json +++ b/core/server/data/schema/default-settings.json @@ -1,8 +1,5 @@ { "core": { - "databaseVersion": { - "defaultValue": null - }, "dbHash": { "defaultValue": null }, diff --git a/core/server/data/schema/index.js b/core/server/data/schema/index.js index fa76343f64..182b5e97a3 100644 --- a/core/server/data/schema/index.js +++ b/core/server/data/schema/index.js @@ -1,5 +1,4 @@ module.exports.tables = require('./schema'); module.exports.checks = require('./checks'); module.exports.commands = require('./commands'); -module.exports.versioning = require('./versioning'); module.exports.defaultSettings = require('./default-settings'); diff --git a/core/server/data/schema/versioning.js b/core/server/data/schema/versioning.js deleted file mode 100644 index 7896787cb6..0000000000 --- a/core/server/data/schema/versioning.js +++ /dev/null @@ -1,78 +0,0 @@ -var Promise = require('bluebird'), - db = require('../db'), - errors = require('../../errors'), - ghostVersion = require('../../utils/ghost-version'); - -/** - * Database version has always two digits - * Database version is Ghost Version X.X - * - * @TODO: remove alpha text! - * @TODO: extend database validation - */ -function validateDatabaseVersion(version) { - if (version === null) { - throw new errors.DatabaseVersionError({ - code: 'VERSION_DOES_NOT_EXIST' - }); - } - - if (!version.match(/\d\.\d/gi)) { - throw new errors.DatabaseVersionError({ - message: 'Your database version is not compatible with Ghost 1.0.0 Alpha (master branch)', - context: 'Want to keep your DB? Use Ghost < 1.0.0 or the "stable" branch. Otherwise please delete your DB and restart Ghost', - help: 'More information on the Ghost 1.0.0 Alpha at https://support.ghost.org/v1-0-alpha' - }); - } - - return version; -} - -/** - * If the database version is null, the database was never seeded. - * The init migration script will set your database to current Ghost Version. - */ -function getDatabaseVersion(options) { - options = options || {}; - - return (options.transacting || db.knex).schema.hasTable('settings') - .then(function (exists) { - if (!exists) { - return Promise.reject(new errors.DatabaseVersionError({ - code: 'SETTINGS_TABLE_DOES_NOT_EXIST' - })); - } - - return (options.transacting || db.knex)('settings') - .where('key', 'databaseVersion') - .first('value') - .then(function (version) { - return validateDatabaseVersion(version ? version.value : null); - }); - }); -} - -function getNewestDatabaseVersion() { - return ghostVersion.safe; -} - -/** - * Database version cannot set from outside. - * If this function get called, we set the database version to your current Ghost version. - */ -function setDatabaseVersion(options) { - options = options || {}; - - return (options.transacting || db.knex)('settings') - .where('key', 'databaseVersion') - .update({ - value: getNewestDatabaseVersion() - }); -} - -module.exports = { - canMigrateFromVersion: '1.0', - getNewestDatabaseVersion: getNewestDatabaseVersion, - getDatabaseVersion: getDatabaseVersion, - setDatabaseVersion: setDatabaseVersion -}; diff --git a/core/server/index.js b/core/server/index.js index f09d4806ca..34aad92bed 100644 --- a/core/server/index.js +++ b/core/server/index.js @@ -19,6 +19,7 @@ var debug = require('debug')('ghost:boot:init'), KnexMigrator = require('knex-migrator'), config = require('./config'), logging = require('./logging'), + errors = require('./errors'), i18n = require('./i18n'), api = require('./api'), models = require('./models'), @@ -83,7 +84,35 @@ function init(options) { models.init(); }).then(function () { - return knexMigrator.isDatabaseOK(); + return knexMigrator.isDatabaseOK() + .catch(function (outerErr) { + if (outerErr.code === 'DB_NOT_INITIALISED') { + throw outerErr; + } + + // CASE: migration table does not exist, figure out if database is compatible + return models.Settings.findOne({key: 'databaseVersion', context: {internal: true}}) + .then(function (response) { + // CASE: no db version key, database is compatible + if (!response) { + throw outerErr; + } + + throw new errors.DatabaseVersionError({ + message: 'Your database version is not compatible with Ghost 1.0.0 Alpha (master branch)', + context: 'Want to keep your DB? Use Ghost < 1.0.0 or the "stable" branch. Otherwise please delete your DB and restart Ghost.', + help: 'More information on the Ghost 1.0.0 Alpha at https://support.ghost.org/v1-0-alpha' + }); + }) + .catch(function (err) { + // CASE: settings table does not exist + if (err.errno === 1 || err.errno === 1146) { + throw outerErr; + } + + throw err; + }); + }); }).then(function () { // Populate any missing default settings return models.Settings.populateDefaults(); diff --git a/core/server/models/settings.js b/core/server/models/settings.js index f22c42477f..c53d8d41fc 100644 --- a/core/server/models/settings.js +++ b/core/server/models/settings.js @@ -167,10 +167,6 @@ Settings = ghostBookshelf.Model.extend({ _.each(getDefaultSettings(), function each(defaultSetting, defaultSettingKey) { var isMissingFromDB = usedKeys.indexOf(defaultSettingKey) === -1; - // Temporary code to deal with old databases with currentVersion settings - if (defaultSettingKey === 'databaseVersion' && usedKeys.indexOf('currentVersion') !== -1) { - isMissingFromDB = false; - } if (isMissingFromDB) { defaultSetting.value = defaultSetting.defaultValue; insertOperations.push(Settings.forge(defaultSetting).save(null, options)); diff --git a/core/server/translations/en.json b/core/server/translations/en.json index 955490f02a..8f4be204cd 100644 --- a/core/server/translations/en.json +++ b/core/server/translations/en.json @@ -448,17 +448,6 @@ } } }, - "versioning": { - "index": { - "dbVersionNotRecognized": "Database version is not recognized", - "databaseNotPopulated": "Database is not populated.", - "databaseNotSeeded": "Database is not seeded.", - "cannotMigrate": { - "error": "Unable to upgrade from version 0.4.2 or earlier.", - "context": "Please upgrade to 0.7.1 first." - } - } - }, "xml": { "xmlrpc": { "pingUpdateFailed": { diff --git a/core/server/utils/index.js b/core/server/utils/index.js index 4eda940475..a792ebf336 100644 --- a/core/server/utils/index.js +++ b/core/server/utils/index.js @@ -107,7 +107,8 @@ utils = { generateAssetHash: require('./asset-hash'), url: require('./url'), tokens: require('./tokens'), - sequence: require('./sequence') + sequence: require('./sequence'), + ghostVersion: require('./ghost-version') }; module.exports = utils; diff --git a/core/test/integration/api/api_settings_spec.js b/core/test/integration/api/api_settings_spec.js index 7270ac8386..fa0d2f19d5 100644 --- a/core/test/integration/api/api_settings_spec.js +++ b/core/test/integration/api/api_settings_spec.js @@ -88,8 +88,8 @@ describe('Settings API', function () { }); it('cannot read core settings if not an internal request', function () { - return callApiWithContext(defaultContext, 'read', {key: 'databaseVersion'}).then(function () { - throw new Error('Allowed to read databaseVersion with external request'); + return callApiWithContext(defaultContext, 'read', {key: 'dbHash'}).then(function () { + throw new Error('Allowed to read dbHash with external request'); }).catch(function (error) { should.exist(error); error.errorType.should.eql('NoPermissionError'); @@ -97,7 +97,7 @@ describe('Settings API', function () { }); it('can read core settings if an internal request', function () { - return callApiWithContext(internalContext, 'read', {key: 'databaseVersion'}).then(function (response) { + return callApiWithContext(internalContext, 'read', {key: 'dbHash'}).then(function (response) { should.exist(response); testUtils.API.checkResponse(response, 'settings'); response.settings.length.should.equal(1); @@ -134,7 +134,7 @@ describe('Settings API', function () { }); it('cannot edit a core setting if not an internal request', function () { - return callApiWithContext(defaultContext, 'edit', {settings: [{key: 'databaseVersion', value: '999'}]}, {}) + return callApiWithContext(defaultContext, 'edit', {settings: [{key: 'dbHash', value: 'hash'}]}, {}) .then(function () { throw new Error('Allowed to edit a core setting as external request'); }).catch(function (err) { @@ -145,7 +145,7 @@ describe('Settings API', function () { }); it('can edit a core setting with an internal request', function () { - return callApiWithContext(internalContext, 'edit', {settings: [{key: 'databaseVersion', value: '999'}]}, {}) + return callApiWithContext(internalContext, 'edit', {settings: [{key: 'dbHash', value: 'hash'}]}, {}) .then(function (response) { should.exist(response); testUtils.API.checkResponse(response, 'settings'); diff --git a/core/test/integration/export_spec.js b/core/test/integration/export_spec.js index 6af33d675a..afef2a4e13 100644 --- a/core/test/integration/export_spec.js +++ b/core/test/integration/export_spec.js @@ -1,14 +1,12 @@ var testUtils = require('../utils/index'), should = require('should'), sinon = require('sinon'), - Promise = require('bluebird'), _ = require('lodash'), // Stuff we are testing - versioning = require('../../server/data/schema').versioning, exporter = require('../../server/data/export'), + utils = require('../../server/utils'), - DEF_DB_VERSION = versioning.getNewestDatabaseVersion(), sandbox = sinon.sandbox.create(); describe('Exporter', function () { @@ -22,36 +20,23 @@ describe('Exporter', function () { should.exist(exporter); it('exports data', function (done) { - // Stub migrations to return DEF_DB_VERSION as the current database version - var versioningStub = sandbox.stub(versioning, 'getDatabaseVersion', function () { - return Promise.resolve(DEF_DB_VERSION); - }); - exporter.doExport().then(function (exportData) { var tables = ['posts', 'users', 'roles', 'roles_users', 'permissions', 'permissions_roles', - 'permissions_users', 'settings', 'tags', 'posts_tags'], - dbVersionSetting; + 'permissions_users', 'settings', 'tags', 'posts_tags']; should.exist(exportData); should.exist(exportData.meta); should.exist(exportData.data); - exportData.meta.version.should.equal(DEF_DB_VERSION); - - dbVersionSetting = _.find(exportData.data.settings, {key: 'databaseVersion'}); - - should.exist(dbVersionSetting); - - dbVersionSetting.value.should.equal(DEF_DB_VERSION); + exportData.meta.version.should.equal(utils.ghostVersion.full); _.each(tables, function (name) { should.exist(exportData.data[name]); }); + // should not export sqlite data should.not.exist(exportData.data.sqlite_sequence); - - versioningStub.restore(); done(); }).catch(done); }); diff --git a/core/test/integration/import_spec.js b/core/test/integration/import_spec.js index 2ad55a40c2..385108ea4d 100644 --- a/core/test/integration/import_spec.js +++ b/core/test/integration/import_spec.js @@ -9,12 +9,10 @@ var testUtils = require('../utils/index'), // Stuff we are testing db = require('../../server/data/db'), - versioning = require('../../server/data/schema').versioning, exporter = require('../../server/data/export'), importer = require('../../server/data/import'), DataImporter = require('../../server/data/import/data-importer'), - DEF_DB_VERSION = versioning.getNewestDatabaseVersion(), knex = db.knex, sandbox = sinon.sandbox.create(); @@ -150,7 +148,6 @@ describe('Import', function () { // test settings settings.length.should.be.above(0, 'Wrong number of settings'); - _.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version'); // test tags tags.length.should.equal(exportData.data.tags.length, 'no new tags'); @@ -204,10 +201,6 @@ describe('Import', function () { // import no longer requires all data to be dropped, and adds posts posts.length.should.equal(exportData.data.posts.length, 'Wrong number of posts'); - // test settings - settings.length.should.be.above(0, 'Wrong number of settings'); - _.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version'); - // activeTheme should NOT have been overridden _.find(settings, {key: 'activeTheme'}).value.should.equal('casper', 'Wrong theme'); @@ -246,17 +239,15 @@ describe('Import', function () { Promise.all([ knex('users').select(), knex('posts').select(), - knex('settings').select(), knex('tags').select() ]).then(function (importedData) { should.exist(importedData); - importedData.length.should.equal(4, 'Did not get data successfully'); + importedData.length.should.equal(3, 'Did not get data successfully'); var users = importedData[0], posts = importedData[1], - settings = importedData[2], - tags = importedData[3]; + tags = importedData[2]; // we always have 1 user, the default user we added users.length.should.equal(1, 'There should only be one user'); @@ -265,10 +256,6 @@ describe('Import', function () { posts.length.should.equal(0, 'Wrong number of posts'); tags.length.should.equal(0, 'no new tags'); - // test settings - settings.length.should.be.above(0, 'Wrong number of settings'); - _.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version'); - done(); }); }).catch(done); @@ -291,17 +278,15 @@ describe('Import', function () { Promise.all([ knex('users').select(), knex('posts').select(), - knex('settings').select(), knex('tags').select() ]).then(function (importedData) { should.exist(importedData); - importedData.length.should.equal(4, 'Did not get data successfully'); + importedData.length.should.equal(3, 'Did not get data successfully'); var users = importedData[0], posts = importedData[1], - settings = importedData[2], - tags = importedData[3]; + tags = importedData[2]; // we always have 1 user, the default user we added users.length.should.equal(1, 'There should only be one user'); @@ -310,10 +295,6 @@ describe('Import', function () { posts.length.should.equal(0, 'Wrong number of posts'); tags.length.should.equal(0, 'no new tags'); - // test settings - settings.length.should.be.above(0, 'Wrong number of settings'); - _.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version'); - done(); }); }).catch(done); @@ -368,10 +349,6 @@ describe('Import', function () { // import no longer requires all data to be dropped, and adds posts posts.length.should.equal(exportData.data.posts.length, 'Wrong number of posts'); - // test settings - settings.length.should.be.above(0, 'Wrong number of settings'); - _.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version'); - // activeTheme should NOT have been overridden _.find(settings, {key: 'activeTheme'}).value.should.equal('casper', 'Wrong theme'); @@ -410,17 +387,15 @@ describe('Import', function () { Promise.all([ knex('users').select(), knex('posts').select(), - knex('settings').select(), knex('tags').select() ]).then(function (importedData) { should.exist(importedData); - importedData.length.should.equal(4, 'Did not get data successfully'); + importedData.length.should.equal(3, 'Did not get data successfully'); var users = importedData[0], posts = importedData[1], - settings = importedData[2], - tags = importedData[3]; + tags = importedData[2]; // we always have 1 user, the owner user we added users.length.should.equal(1, 'There should only be one user'); @@ -428,10 +403,6 @@ describe('Import', function () { posts.length.should.equal(0, 'Wrong number of posts'); tags.length.should.equal(0, 'no new tags'); - // test settings - settings.length.should.be.above(0, 'Wrong number of settings'); - _.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version'); - done(); }); }).catch(done); @@ -454,17 +425,15 @@ describe('Import', function () { Promise.all([ knex('users').select(), knex('posts').select(), - knex('settings').select(), knex('tags').select() ]).then(function (importedData) { should.exist(importedData); - importedData.length.should.equal(4, 'Did not get data successfully'); + importedData.length.should.equal(3, 'Did not get data successfully'); var users = importedData[0], posts = importedData[1], - settings = importedData[2], - tags = importedData[3]; + tags = importedData[2]; // we always have 1 user, the owner user we added users.length.should.equal(1, 'There should only be one user'); @@ -472,10 +441,6 @@ describe('Import', function () { posts.length.should.equal(0, 'Wrong number of posts'); tags.length.should.equal(0, 'no new tags'); - // test settings - settings.length.should.be.above(0, 'Wrong number of settings'); - _.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version'); - done(); }); }).catch(done); @@ -496,18 +461,16 @@ describe('Import', function () { return Promise.all([ knex('users').select(), knex('posts').select(), - knex('settings').select(), knex('tags').select() ]); }).then(function (importedData) { should.exist(importedData); - importedData.length.should.equal(4, 'Did not get data successfully'); + importedData.length.should.equal(3, 'Did not get data successfully'); var users = importedData[0], posts = importedData[1], - settings = importedData[2], - tags = importedData[3]; + tags = importedData[2]; // user should still have the credentials from the original insert, not the import users[0].email.should.equal(testUtils.DataGenerator.Content.users[0].email); @@ -522,10 +485,6 @@ describe('Import', function () { // test tags tags.length.should.equal(1, 'no new tags'); - // test settings - settings.length.should.be.above(0, 'Wrong number of settings'); - _.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version'); - done(); }).catch(done); }); @@ -712,10 +671,6 @@ describe('Import (new test structure)', function () { // test tags tags.length.should.equal(3, 'should be 3 tags'); - // test settings - settings.length.should.be.above(0, 'Wrong number of settings'); - _.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version'); - done(); }).catch(done); }); @@ -937,10 +892,6 @@ describe('Import (new test structure)', function () { // test tags tags.length.should.equal(3, 'should be 3 tags'); - // test settings - settings.length.should.be.above(0, 'Wrong number of settings'); - _.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version'); - done(); }).catch(done); }); @@ -1174,10 +1125,6 @@ describe('Import (new test structure)', function () { tags[0].name.should.equal(testUtils.DataGenerator.Content.tags[0].name); - // test settings - settings.length.should.be.above(0, 'Wrong number of settings'); - _.find(settings, {key: 'databaseVersion'}).value.should.equal(DEF_DB_VERSION, 'Wrong database version'); - done(); }).catch(done); }); diff --git a/core/test/integration/model/model_settings_spec.js b/core/test/integration/model/model_settings_spec.js index ad04242c0d..da93bd8ab7 100644 --- a/core/test/integration/model/model_settings_spec.js +++ b/core/test/integration/model/model_settings_spec.js @@ -153,7 +153,6 @@ describe('Settings Model', function () { it('can destroy', function (done) { SettingsModel.findAll().then(function (allSettings) { - // dont't use index 0, since it will delete databaseversion SettingsModel.findOne({id: allSettings.models[1].id}).then(function (results) { should.exist(results); results.attributes.id.should.equal(allSettings.models[1].id); diff --git a/core/test/unit/exporter_spec.js b/core/test/unit/exporter_spec.js index f58f12280f..d2e1fb5b8d 100644 --- a/core/test/unit/exporter_spec.js +++ b/core/test/unit/exporter_spec.js @@ -1,16 +1,17 @@ var should = require('should'), sinon = require('sinon'), + rewire = require('rewire'), Promise = require('bluebird'), db = require('../../server/data/db'), errors = require('../../server/errors'), - exporter = require('../../server/data/export'), + exporter = rewire('../../server/data/export'), schema = require('../../server/data/schema'), settings = require('../../server/api/settings'), schemaTables = Object.keys(schema.tables), sandbox = sinon.sandbox.create(); describe('Exporter', function () { - var versionStub, tablesStub, queryMock, knexMock, knexStub; + var tablesStub, queryMock, knexMock, knexStub; afterEach(function () { sandbox.restore(); @@ -19,7 +20,10 @@ describe('Exporter', function () { describe('doExport', function () { beforeEach(function () { - versionStub = sandbox.stub(schema.versioning, 'getDatabaseVersion').returns(new Promise.resolve('004')); + exporter.__set__('ghostVersion', { + full: '1.0.0' + }); + tablesStub = sandbox.stub(schema.commands, 'getTables').returns(schemaTables); queryMock = { @@ -43,7 +47,8 @@ describe('Exporter', function () { should.exist(exportData); - versionStub.calledOnce.should.be.true(); + exportData.meta.version.should.eql('1.0.0'); + tablesStub.calledOnce.should.be.true(); knexStub.get.called.should.be.true(); knexMock.called.should.be.true(); diff --git a/core/test/unit/migration_spec.js b/core/test/unit/migration_spec.js index 4a87854662..04f92e376e 100644 --- a/core/test/unit/migration_spec.js +++ b/core/test/unit/migration_spec.js @@ -1,5 +1,4 @@ -var should = require('should'), - sinon = require('sinon'), +var sinon = require('sinon'), rewire = require('rewire'), _ = require('lodash'), Promise = require('bluebird'), @@ -10,7 +9,6 @@ var should = require('should'), schema = require('../../server/data/schema'), backupDatabase = rewire('../../server/data/db/backup'), fixtures = require('../../server/data/schema/fixtures'), - defaultSettings = schema.defaultSettings, sandbox = sinon.sandbox.create(); // Check version integrity @@ -38,11 +36,8 @@ describe('DB version integrity', function () { schemaHash = crypto.createHash('md5').update(JSON.stringify(tablesNoValidation)).digest('hex'); fixturesHash = crypto.createHash('md5').update(JSON.stringify(fixtures)).digest('hex'); - // by default the database version is null - should.not.exist(defaultSettings.core.databaseVersion.defaultValue); schemaHash.should.eql(currentSchemaHash); fixturesHash.should.eql(currentFixturesHash); - schema.versioning.canMigrateFromVersion.should.eql('1.0'); }); }); diff --git a/core/test/unit/versioning_spec.js b/core/test/unit/versioning_spec.js deleted file mode 100644 index d2d59333ed..0000000000 --- a/core/test/unit/versioning_spec.js +++ /dev/null @@ -1,189 +0,0 @@ -var should = require('should'), - sinon = require('sinon'), - Promise = require('bluebird'), - - // Stuff we are testing - versioning = require('../../server/data/schema').versioning, - db = require('../../server/data/db'), - errors = require('../../server/errors'), - - sandbox = sinon.sandbox.create(); - -describe('Versioning', function () { - afterEach(function () { - sandbox.restore(); - }); - - describe('getNewestDatabaseVersion', function () { - it('should return the correct version', function () { - var currentVersion = '1.0'; - - // This function has an internal cache, so we call it twice. - // First, to check that it fetches the correct version from default-settings.json. - versioning.getNewestDatabaseVersion().should.eql(currentVersion); - // Second, to check that it returns the same value from the cache. - versioning.getNewestDatabaseVersion().should.eql(currentVersion); - }); - }); - - describe('getDatabaseVersion', function () { - var knexStub, knexMock, queryMock; - - beforeEach(function () { - queryMock = { - where: sandbox.stub().returnsThis(), - first: sandbox.stub() - }; - - knexMock = sandbox.stub().returns(queryMock); - knexMock.schema = { - hasTable: sandbox.stub() - }; - - // this MUST use sinon, not sandbox, see sinonjs/sinon#781 - knexStub = sinon.stub(db, 'knex', { - get: function () { - return knexMock; - } - }); - }); - - afterEach(function () { - knexStub.restore(); - }); - - it('should throw error if settings table does not exist', function (done) { - // Setup - knexMock.schema.hasTable.returns(new Promise.resolve(false)); - - // Execute - versioning.getDatabaseVersion().then(function () { - done('Should throw an error if the settings table does not exist'); - }).catch(function (err) { - should.exist(err); - (err instanceof errors.DatabaseVersionError).should.eql(true); - - knexStub.get.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('settings').should.be.true(); - queryMock.where.called.should.be.false(); - queryMock.first.called.should.be.false(); - done(); - }).catch(done); - }); - - it('should lookup & return version, if settings table exists', function (done) { - // Setup - knexMock.schema.hasTable.returns(new Promise.resolve(true)); - queryMock.first.returns(new Promise.resolve({value: '1.0'})); - - // Execute - versioning.getDatabaseVersion().then(function (version) { - should.exist(version); - version.should.eql('1.0'); - - knexStub.get.calledTwice.should.be.true(); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('settings').should.be.true(); - queryMock.where.called.should.be.true(); - queryMock.first.called.should.be.true(); - - done(); - }).catch(done); - }); - - it('should throw error if version does not exist', function (done) { - // Setup - knexMock.schema.hasTable.returns(new Promise.resolve(true)); - queryMock.first.returns(new Promise.resolve()); - - // Execute - versioning.getDatabaseVersion().then(function () { - done('Should throw an error if version does not exist'); - }).catch(function (err) { - should.exist(err); - (err instanceof errors.DatabaseVersionError).should.eql(true); - err.code.should.eql('VERSION_DOES_NOT_EXIST'); - - knexStub.get.calledTwice.should.be.true(); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('settings').should.be.true(); - queryMock.where.called.should.be.true(); - queryMock.first.called.should.be.true(); - - done(); - }).catch(done); - }); - - it('should throw error if version is not a number', function (done) { - // Setup - knexMock.schema.hasTable.returns(new Promise.resolve(true)); - queryMock.first.returns(new Promise.resolve({value: 'Eyjafjallajökull'})); - - // Execute - versioning.getDatabaseVersion().then(function () { - done('Should throw an error if version is not a number'); - }).catch(function (err) { - should.exist(err); - (err instanceof errors.DatabaseVersionError).should.eql(true); - - knexStub.get.calledTwice.should.be.true(); - knexMock.schema.hasTable.calledOnce.should.be.true(); - knexMock.schema.hasTable.calledWith('settings').should.be.true(); - queryMock.where.called.should.be.true(); - queryMock.first.called.should.be.true(); - - done(); - }).catch(done); - }); - - it('database does exist: expect alpha error', function (done) { - knexMock.schema.hasTable.returns(new Promise.resolve(true)); - queryMock.first.returns(new Promise.resolve({value: '008'})); - - versioning.getDatabaseVersion() - .then(function () { - done('Should throw an error if version is not a number'); - }) - .catch(function (err) { - (err instanceof errors.DatabaseVersionError).should.eql(true); - err.message.should.eql('Your database version is not compatible with Ghost 1.0.0 Alpha (master branch)'); - done(); - }); - }); - }); - - describe('setDatabaseVersion', function () { - var knexStub, knexMock, queryMock; - - beforeEach(function () { - queryMock = { - where: sandbox.stub().returnsThis(), - update: sandbox.stub().returns(new Promise.resolve()) - }; - - knexMock = sandbox.stub().returns(queryMock); - - // this MUST use sinon, not sandbox, see sinonjs/sinon#781 - knexStub = sinon.stub(db, 'knex', { - get: function () { - return knexMock; - } - }); - }); - - afterEach(function () { - knexStub.restore(); - }); - - it('should try to update the databaseVersion', function (done) { - versioning.setDatabaseVersion().then(function () { - knexStub.get.calledOnce.should.be.true(); - queryMock.where.called.should.be.true(); - queryMock.update.called.should.be.true(); - - done(); - }).catch(done); - }); - }); -}); diff --git a/core/test/utils/fixtures/export/export-000.json b/core/test/utils/fixtures/export/export-000.json index cb3dd17622..1e95233511 100644 --- a/core/test/utils/fixtures/export/export-000.json +++ b/core/test/utils/fixtures/export/export-000.json @@ -119,17 +119,6 @@ } ], "settings": [ - { - "id": 1, - "uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e", - "key": "databaseVersion", - "value": "000", - "type": "core", - "created_at": 1388318310829, - "created_by": 1, - "updated_at": 1388318310829, - "updated_by": 1 - }, { "id": 3, "uuid": "c356fbde-0bc5-4fe1-9309-2510291aa34d", diff --git a/core/test/utils/fixtures/export/export-001.json b/core/test/utils/fixtures/export/export-001.json index 54d6dad9c3..95dff34c8e 100644 --- a/core/test/utils/fixtures/export/export-001.json +++ b/core/test/utils/fixtures/export/export-001.json @@ -149,17 +149,6 @@ } ], "settings": [ - { - "id": 1, - "uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e", - "key": "databaseVersion", - "value": "001", - "type": "core", - "created_at": 1388318310829, - "created_by": 1, - "updated_at": 1388318310829, - "updated_by": 1 - }, { "id": 2, "uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5", @@ -328,4 +317,4 @@ } ] } -} \ No newline at end of file +} diff --git a/core/test/utils/fixtures/export/export-002.json b/core/test/utils/fixtures/export/export-002.json index 813c1f8dfa..488c1bcec9 100644 --- a/core/test/utils/fixtures/export/export-002.json +++ b/core/test/utils/fixtures/export/export-002.json @@ -149,17 +149,6 @@ } ], "settings": [ - { - "id": 1, - "uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e", - "key": "databaseVersion", - "value": "001", - "type": "core", - "created_at": 1388318310829, - "created_by": 1, - "updated_at": 1388318310829, - "updated_by": 1 - }, { "id": 2, "uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5", @@ -328,4 +317,4 @@ } ] } -} \ No newline at end of file +} diff --git a/core/test/utils/fixtures/export/export-003-duplicate-posts.json b/core/test/utils/fixtures/export/export-003-duplicate-posts.json index d100ed547d..b06b91490a 100644 --- a/core/test/utils/fixtures/export/export-003-duplicate-posts.json +++ b/core/test/utils/fixtures/export/export-003-duplicate-posts.json @@ -171,17 +171,6 @@ } ], "settings": [ - { - "id": 1, - "uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e", - "key": "databaseVersion", - "value": "001", - "type": "core", - "created_at": 1388318310829, - "created_by": 1, - "updated_at": 1388318310829, - "updated_by": 1 - }, { "id": 2, "uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5", @@ -388,4 +377,4 @@ } ] } -} \ No newline at end of file +} diff --git a/core/test/utils/fixtures/export/export-003-duplicate-tags.json b/core/test/utils/fixtures/export/export-003-duplicate-tags.json index dc1a836f5b..a14fbbbdc6 100644 --- a/core/test/utils/fixtures/export/export-003-duplicate-tags.json +++ b/core/test/utils/fixtures/export/export-003-duplicate-tags.json @@ -149,17 +149,6 @@ } ], "settings": [ - { - "id": 1, - "uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e", - "key": "databaseVersion", - "value": "001", - "type": "core", - "created_at": 1388318310829, - "created_by": 1, - "updated_at": 1388318310829, - "updated_by": 1 - }, { "id": 2, "uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5", diff --git a/core/test/utils/fixtures/export/export-003-mu-noOwner.json b/core/test/utils/fixtures/export/export-003-mu-noOwner.json index 0e5596d8c8..bd047126e9 100644 --- a/core/test/utils/fixtures/export/export-003-mu-noOwner.json +++ b/core/test/utils/fixtures/export/export-003-mu-noOwner.json @@ -157,17 +157,6 @@ } ], "settings": [ - { - "id": 1, - "uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e", - "key": "databaseVersion", - "value": "001", - "type": "core", - "created_at": 1388318310829, - "created_by": 1, - "updated_at": 1388318310829, - "updated_by": 1 - }, { "id": 2, "uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5", diff --git a/core/test/utils/fixtures/export/export-003-mu.json b/core/test/utils/fixtures/export/export-003-mu.json index f0a9a171bc..384e9599be 100644 --- a/core/test/utils/fixtures/export/export-003-mu.json +++ b/core/test/utils/fixtures/export/export-003-mu.json @@ -235,17 +235,6 @@ } ], "settings": [ - { - "id": 1, - "uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e", - "key": "databaseVersion", - "value": "001", - "type": "core", - "created_at": 1388318310829, - "created_by": 1, - "updated_at": 1388318310829, - "updated_by": 1 - }, { "id": 2, "uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5", @@ -477,4 +466,4 @@ } ] } -} \ No newline at end of file +} diff --git a/core/test/utils/fixtures/export/export-003.json b/core/test/utils/fixtures/export/export-003.json index e9b4fab9df..86a0b01ca8 100644 --- a/core/test/utils/fixtures/export/export-003.json +++ b/core/test/utils/fixtures/export/export-003.json @@ -149,17 +149,6 @@ } ], "settings": [ - { - "id": 1, - "uuid": "f90aa810-4fa2-49fe-a39b-7c0d2ebb473e", - "key": "databaseVersion", - "value": "001", - "type": "core", - "created_at": 1388318310829, - "created_by": 1, - "updated_at": 1388318310829, - "updated_by": 1 - }, { "id": 2, "uuid": "95ce1c53-69b0-4f5f-be91-d3aeb39046b5", @@ -366,4 +355,4 @@ } ] } -} \ No newline at end of file +} diff --git a/index.js b/index.js index 795c36be20..aad6fb281d 100644 --- a/index.js +++ b/index.js @@ -22,15 +22,15 @@ ghost().then(function (ghostServer) { process.send({started: true}); } }); -}).catch(function (error) { - if (!(error instanceof errors.IgnitionError)) { - error = new errors.GhostError({err: error}); +}).catch(function (err) { + if (!errors.utils.isIgnitionError(err)) { + err = new errors.GhostError({err: err}); } if (process.send) { - process.send({started: false, error: error.message}); + process.send({started: false, error: err.message}); } - logging.error(error); + logging.error(err); process.exit(-1); });