mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
One exporter to rule them all
closes #733 - Exporter will read meta data to determine the tables which are present and export all data from those tables - Exporter figures out which version to export, rather than requiring that information - deleted old exporters
This commit is contained in:
parent
596c1dccd2
commit
8d038b8bf2
7 changed files with 125 additions and 239 deletions
|
@ -273,15 +273,7 @@ adminControllers = {
|
|||
});
|
||||
},
|
||||
'export': function (req, res) {
|
||||
// Get current version from settings
|
||||
api.settings.read({ key: "databaseVersion" })
|
||||
.then(function (setting) {
|
||||
// Export the current versions data
|
||||
return dataExport(setting.value);
|
||||
}, function () {
|
||||
// If no setting, assume 001
|
||||
return dataExport("001");
|
||||
})
|
||||
return dataExport()
|
||||
.then(function (exportedData) {
|
||||
// Save the exported data to the file system for download
|
||||
var fileName = path.resolve(__dirname + '/../../server/data/export/exported-' + (new Date().getTime()) + '.json');
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
var _ = require("underscore"),
|
||||
when = require("when"),
|
||||
knex = require('../../models/base').Knex,
|
||||
Exporter001;
|
||||
|
||||
Exporter001 = function () {
|
||||
this.version = "001";
|
||||
};
|
||||
|
||||
Exporter001.prototype.exportData = function () {
|
||||
var self = this,
|
||||
tables = ['posts', 'users', 'roles', 'roles_users', 'permissions', 'permissions_roles', 'settings'],
|
||||
selectOps = _.map(tables, function (name) {
|
||||
return knex(name).select();
|
||||
});
|
||||
|
||||
return when.all(selectOps).then(function (tableData) {
|
||||
var exportData = {
|
||||
meta: {
|
||||
exported_on: new Date().getTime(),
|
||||
version: self.version
|
||||
},
|
||||
data: {
|
||||
// Filled below
|
||||
}
|
||||
};
|
||||
|
||||
_.each(tables, function (name, i) {
|
||||
exportData.data[name] = tableData[i];
|
||||
});
|
||||
|
||||
return when.resolve(exportData);
|
||||
}, function (err) {
|
||||
console.log("Error exporting data: " + err);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
// Make available for unit tests
|
||||
Exporter001: Exporter001,
|
||||
|
||||
exportData: function () {
|
||||
return new Exporter001().exportData();
|
||||
}
|
||||
};
|
|
@ -1,49 +0,0 @@
|
|||
var _ = require("underscore"),
|
||||
when = require("when"),
|
||||
knex = require('../../models/base').Knex,
|
||||
Exporter002;
|
||||
|
||||
Exporter002 = function () {
|
||||
this.version = "002";
|
||||
};
|
||||
|
||||
Exporter002.prototype.exportData = function () {
|
||||
var self = this,
|
||||
tables = [
|
||||
'posts', 'users', 'roles', 'roles_users', 'permissions',
|
||||
'permissions_roles', 'settings', 'tags', 'posts_tags',
|
||||
'custom_data', 'posts_custom_data'
|
||||
],
|
||||
selectOps = _.map(tables, function (name) {
|
||||
return knex(name).select();
|
||||
});
|
||||
|
||||
return when.all(selectOps).then(function (tableData) {
|
||||
var exportData = {
|
||||
meta: {
|
||||
exported_on: new Date().getTime(),
|
||||
version: self.version
|
||||
},
|
||||
data: {
|
||||
// Filled below
|
||||
}
|
||||
};
|
||||
|
||||
_.each(tables, function (name, i) {
|
||||
exportData.data[name] = tableData[i];
|
||||
});
|
||||
|
||||
return when.resolve(exportData);
|
||||
}, function (err) {
|
||||
console.log("Error exporting data: " + err);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
// Make available for unit tests
|
||||
Exporter002: Exporter002,
|
||||
|
||||
exportData: function () {
|
||||
return new Exporter002().exportData();
|
||||
}
|
||||
};
|
|
@ -1,22 +1,65 @@
|
|||
var when = require('when'),
|
||||
migration = require('../migration');
|
||||
_ = require('underscore'),
|
||||
migration = require('../migration'),
|
||||
client = require('../../models/base').client,
|
||||
knex = require('../../models/base').Knex,
|
||||
|
||||
module.exports = function (version) {
|
||||
var exporter;
|
||||
exporter;
|
||||
|
||||
if (version > migration.databaseVersion) {
|
||||
return when.reject("Your data version is ahead of the current Ghost version. Please upgrade in order to export.");
|
||||
function getTablesFromSqlite3() {
|
||||
return knex.Raw("select * from sqlite_master where type = 'table'").then(function (response) {
|
||||
return _.reject(_.pluck(response, 'tbl_name'), function (name) {
|
||||
return name === 'sqlite_sequence';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getTablesFromMySQL() {
|
||||
knex.Raw("show tables").then(function (response) {
|
||||
return _.flatten(_.map(response, function (entry) {
|
||||
return _.values(entry);
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
exporter = function () {
|
||||
var tablesToExport;
|
||||
|
||||
if (client === 'sqlite3') {
|
||||
tablesToExport = getTablesFromSqlite3();
|
||||
} else if (client === 'mysql') {
|
||||
tablesToExport = getTablesFromMySQL();
|
||||
} else {
|
||||
return when.reject("No exporter for database client " + client);
|
||||
}
|
||||
|
||||
try {
|
||||
exporter = require("./" + version);
|
||||
} catch (ignore) {
|
||||
// Zero effs given
|
||||
}
|
||||
return when.join(migration.getDatabaseVersion(), tablesToExport).then(function (results) {
|
||||
var version = results[0],
|
||||
tables = results[1],
|
||||
selectOps = _.map(tables, function (name) {
|
||||
return knex(name).select();
|
||||
});
|
||||
|
||||
if (!exporter) {
|
||||
return when.reject("No exporter found for data version " + version);
|
||||
}
|
||||
return when.all(selectOps).then(function (tableData) {
|
||||
var exportData = {
|
||||
meta: {
|
||||
exported_on: new Date().getTime(),
|
||||
version: version
|
||||
},
|
||||
data: {
|
||||
// Filled below
|
||||
}
|
||||
};
|
||||
|
||||
return exporter.exportData();
|
||||
_.each(tables, function (name, i) {
|
||||
exportData.data[name] = tableData[i];
|
||||
});
|
||||
|
||||
return when.resolve(exportData);
|
||||
}, function (err) {
|
||||
console.log("Error exporting data: " + err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = exporter;
|
|
@ -67,6 +67,7 @@ function setDatabaseVersion() {
|
|||
|
||||
|
||||
module.exports = {
|
||||
getDatabaseVersion: getDatabaseVersion,
|
||||
// Check for whether data is needed to be bootstrapped or not
|
||||
init: function () {
|
||||
var self = this;
|
||||
|
|
|
@ -10,6 +10,7 @@ var GhostBookshelf,
|
|||
// Initializes Bookshelf as its own instance, so we can modify the Models and not mess up
|
||||
// others' if they're using the library outside of ghost.
|
||||
GhostBookshelf = Bookshelf.Initialize('ghost', config[process.env.NODE_ENV || 'development'].database);
|
||||
GhostBookshelf.client = config[process.env.NODE_ENV].database.client;
|
||||
|
||||
GhostBookshelf.validator = new Validator();
|
||||
|
||||
|
|
|
@ -1,122 +1,65 @@
|
|||
///*globals describe, beforeEach, it*/
|
||||
//var testUtils = require('./testUtils'),
|
||||
// should = require('should'),
|
||||
// sinon = require('sinon'),
|
||||
// when = require('when'),
|
||||
// _ = require("underscore"),
|
||||
// errors = require('../../server/errorHandling'),
|
||||
//
|
||||
// // Stuff we are testing
|
||||
// migration = require('../../server/data/migration'),
|
||||
// exporter = require('../../server/data/export'),
|
||||
// Exporter001 = require('../../server/data/export/001'),
|
||||
// Exporter002 = require('../../server/data/export/002'),
|
||||
// Settings = require('../../server/models/settings').Settings;
|
||||
//
|
||||
//describe("Export", function () {
|
||||
//
|
||||
// should.exist(exporter);
|
||||
//
|
||||
// beforeEach(function (done) {
|
||||
// // clear database... we need to initialise it manually for each test
|
||||
// testUtils.clearData().then(function () {
|
||||
// done();
|
||||
// }, done);
|
||||
// });
|
||||
//
|
||||
// it("resolves 001", function (done) {
|
||||
// var exportStub = sinon.stub(Exporter001, "exportData", function () {
|
||||
// return when.resolve();
|
||||
// });
|
||||
//
|
||||
// exporter("001").then(function () {
|
||||
// exportStub.called.should.equal(true);
|
||||
//
|
||||
// exportStub.restore();
|
||||
//
|
||||
// done();
|
||||
// }).then(null, done);
|
||||
// });
|
||||
//
|
||||
// describe("001", function () {
|
||||
//
|
||||
// should.exist(Exporter001);
|
||||
//
|
||||
// it("exports data", function (done) {
|
||||
// // initialise database to version 001 - confusingly we have to set the max version to be one higher
|
||||
// // than the migration version we want
|
||||
// migration.migrateUpFromVersion('001', '002').then(function () {
|
||||
// return Settings.populateDefaults();
|
||||
// }).then(function () {
|
||||
// return exporter("001");
|
||||
// }).then(function (exportData) {
|
||||
// var tables = ['posts', 'users', 'roles', 'roles_users', 'permissions', 'permissions_roles', 'settings'];
|
||||
//
|
||||
// should.exist(exportData);
|
||||
//
|
||||
// should.exist(exportData.meta);
|
||||
// should.exist(exportData.data);
|
||||
//
|
||||
// exportData.meta.version.should.equal("001");
|
||||
// _.findWhere(exportData.data.settings, {key: "databaseVersion"}).value.should.equal("001");
|
||||
//
|
||||
// _.each(tables, function (name) {
|
||||
// should.exist(exportData.data[name]);
|
||||
// });
|
||||
// // 002 data should not be present
|
||||
// should.not.exist(exportData.data.tags);
|
||||
//
|
||||
// done();
|
||||
// }).then(null, done);
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// it("resolves 002", function (done) {
|
||||
// var exportStub = sinon.stub(Exporter002, "exportData", function () {
|
||||
// return when.resolve();
|
||||
// });
|
||||
//
|
||||
// exporter("002").then(function () {
|
||||
// exportStub.called.should.equal(true);
|
||||
//
|
||||
// exportStub.restore();
|
||||
//
|
||||
// done();
|
||||
// }).then(null, done);
|
||||
// });
|
||||
//
|
||||
// describe("002", function () {
|
||||
// this.timeout(5000);
|
||||
//
|
||||
// should.exist(Exporter001);
|
||||
//
|
||||
// it("exports data", function (done) {
|
||||
// // initialise database to version 001 - confusingly we have to set the max version to be one higher
|
||||
// // than the migration version we want
|
||||
// migration.migrateUpFromVersion('001', '003').then(function () {
|
||||
// return Settings.populateDefaults();
|
||||
// }).then(function () {
|
||||
// return exporter("002");
|
||||
// }).then(function (exportData) {
|
||||
// var tables = [
|
||||
// 'posts', 'users', 'roles', 'roles_users', 'permissions', 'permissions_roles',
|
||||
// 'settings', 'tags', 'posts_tags', 'custom_data', 'posts_custom_data'
|
||||
// ];
|
||||
//
|
||||
// should.exist(exportData);
|
||||
//
|
||||
// should.exist(exportData.meta);
|
||||
// should.exist(exportData.data);
|
||||
//
|
||||
// exportData.meta.version.should.equal("002");
|
||||
// _.findWhere(exportData.data.settings, {key: "databaseVersion"}).value.should.equal("002");
|
||||
//
|
||||
// _.each(tables, function (name) {
|
||||
// should.exist(exportData.data[name]);
|
||||
// });
|
||||
//
|
||||
// done();
|
||||
// }).then(null, done);
|
||||
// });
|
||||
// });
|
||||
//});
|
||||
/*globals describe, before, beforeEach, afterEach, it*/
|
||||
var testUtils = require('./testUtils'),
|
||||
should = require('should'),
|
||||
sinon = require('sinon'),
|
||||
when = require('when'),
|
||||
_ = require("underscore"),
|
||||
errors = require('../../server/errorHandling'),
|
||||
|
||||
// Stuff we are testing
|
||||
migration = require('../../server/data/migration'),
|
||||
exporter = require('../../server/data/export'),
|
||||
Settings = require('../../server/models/settings').Settings;
|
||||
|
||||
describe("Exporter", function () {
|
||||
|
||||
should.exist(exporter);
|
||||
|
||||
before(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
beforeEach(function (done) {
|
||||
this.timeout(5000);
|
||||
testUtils.initData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
afterEach(function (done) {
|
||||
testUtils.clearData().then(function () {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
it("exports data", function (done) {
|
||||
// Stub migrations to return 000 as the current database version
|
||||
var migrationStub = sinon.stub(migration, "getDatabaseVersion", function () {
|
||||
return when.resolve("000");
|
||||
});
|
||||
|
||||
exporter().then(function (exportData) {
|
||||
var tables = ['posts', 'users', 'roles', 'roles_users', 'permissions', 'permissions_roles', 'permissions_users',
|
||||
'settings', 'tags', 'posts_tags'];
|
||||
|
||||
should.exist(exportData);
|
||||
|
||||
should.exist(exportData.meta);
|
||||
should.exist(exportData.data);
|
||||
|
||||
exportData.meta.version.should.equal("000");
|
||||
_.findWhere(exportData.data.settings, {key: "databaseVersion"}).value.should.equal("000");
|
||||
|
||||
_.each(tables, function (name) {
|
||||
should.exist(exportData.data[name]);
|
||||
});
|
||||
// should not export sqlite data
|
||||
should.not.exist(exportData.data.sqlite_sequence);
|
||||
|
||||
migrationStub.restore();
|
||||
done();
|
||||
}).then(null, done);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue