0
Fork 0
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:
Hannah Wolfe 2013-09-15 17:04:42 +01:00
parent 596c1dccd2
commit 8d038b8bf2
7 changed files with 125 additions and 239 deletions

View file

@ -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');

View file

@ -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();
}
};

View file

@ -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();
}
};

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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);
});
});