Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 41 additions & 34 deletions src/plugins/ApplyUpdates/ApplyUpdates.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,62 @@
define([
'deepforge/updates/Updates',
'text!./metadata.json',
'plugin/PluginBase'
'plugin/ImportLibrary/ImportLibrary/ImportLibrary',
], function (
Updates,
pluginMetadata,
PluginBase
PluginBase,
) {
'use strict';

pluginMetadata = JSON.parse(pluginMetadata);

/**
* Initializes a new instance of ApplyUpdates.
* @class
* @augments {PluginBase}
* @classdesc This class represents the plugin ApplyUpdates.
* @constructor
*/
var ApplyUpdates = function () {
// Call base class' constructor.
const ApplyUpdates = function () {
PluginBase.call(this);
this.pluginMetadata = pluginMetadata;
};

/**
* Metadata associated with the plugin. Contains id, name, version, description, icon, configStructue etc.
* This is also available at the instance at this.pluginMetadata.
* @type {object}
*/
ApplyUpdates.metadata = pluginMetadata;

// Prototypical inheritance from PluginBase.
ApplyUpdates.prototype = Object.create(PluginBase.prototype);
ApplyUpdates.prototype.constructor = ApplyUpdates;

/**
* Main function for the plugin to execute. This will perform the execution.
* Notes:
* - Always log with the provided logger.[error,warning,info,debug].
* - Do NOT put any user interaction logic UI, etc. inside this method.
* - callback always has to be called even if error happened.
*
* @param {function(string, plugin.PluginResult)} callback - the result callback
*/
ApplyUpdates.prototype.main = async function (callback) {
// Retrieve the updates to apply
const config = this.getCurrentConfig();
const updateNames = config.updates || [];

if (!updateNames.length) {
if (!config.updates.length) {
this.result.setSuccess(true);
return callback(null, this.result);
}

// Apply each of the updates
const [libUpdates, migrations] = partition(
config.updates,
update => update.type === Updates.SEED
);
await this.applyLibraryUpdates(libUpdates);
await this.applyMigrations(migrations);
const updateDisplayNames = config.updates
.map(update => update.type === Updates.SEED ? `${update.name} (library)` : update.name)
.join(', ');

await this.save(`Applied project updates: ${updateDisplayNames}`);

this.result.setSuccess(true);
callback(null, this.result);
};

ApplyUpdates.prototype.applyLibraryUpdates = async function (updates) {
for (let i = 0; i < updates.length; i++) {
const {name} = updates[i];
const {branchInfo, rootHash, libraryData} = await this.createGMELibraryFromSeed(name);
await this.core.updateLibrary(this.rootNode, name, rootHash, libraryData);
await this.removeTemporaryBranch(branchInfo);
}
};

ApplyUpdates.prototype.applyMigrations = async function (migrations) {
const updateNames = migrations.map(migration => migration.name);
const updates = Updates.getUpdates(updateNames);

for (let i = 0, len = updates.length; i < len; i++) {
Expand All @@ -66,12 +68,17 @@ define([
await update.apply(this.core, this.rootNode, this.META);
}

// Save the project
await this.save(`Applied project updates: ${updateNames.join(",")}`);

this.result.setSuccess(true);
callback(null, this.result);
};

function partition(data, fn) {
const partitioned = [[], []];
data.forEach(datum => {
const partitionIndex = fn(datum) ? 0 : 1;
const partition = partitioned[partitionIndex];
partition.push(datum);
});
return partitioned;
}

return ApplyUpdates;
});
64 changes: 31 additions & 33 deletions src/plugins/ImportLibrary/ImportLibrary.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,38 +46,25 @@ define([
*
* @param {function(string, plugin.PluginResult)} callback - the result callback
*/
ImportLibrary.prototype.main = function (callback) {
ImportLibrary.prototype.main = async function (callback) {
const config = this.getCurrentConfig();
const libraryInfo = config.libraryInfo;

return this.addSeedToBranch(libraryInfo.seed)
.then(branchName => this.createGMELibraryFromBranch(branchName, libraryInfo))
.then(branchInfo => this.removeTemporaryBranch(branchInfo))
.then(() => this.updateMetaForLibrary(libraryInfo))
.then(() => this.addLibraryInitCode(libraryInfo))
.then(() => this.save(`Imported ${libraryInfo.name} library`))
.then(() => {
this.result.setSuccess(true);
callback(null, this.result);
})
.catch(err => {
this.logger.error(`Could not check the libraries: ${err}`);
callback(err, this.result);
});
const {branchInfo, rootHash, libraryData} = await this.createGMELibraryFromSeed(libraryInfo.seed);
// FIXME: libraryData isn't very good...
await this.core.addLibrary(this.rootNode, libraryInfo.name, rootHash, libraryData);
await this.removeTemporaryBranch(branchInfo);

await this.updateMetaForLibrary(libraryInfo);
await this.addLibraryInitCode(libraryInfo);
await this.save(`Imported ${libraryInfo.name} library`);
this.result.setSuccess(true);
callback(null, this.result);
};

ImportLibrary.prototype.getUniqueBranchName = function (basename) {
return this.project.getBranches()
.then(branches => {
let name = basename;
let i = 2;

while (branches[name]) {
name = `${basename}${i}`;
i++;
}
return name;
});
ImportLibrary.prototype.createGMELibraryFromSeed = async function (name) {
const branchName = await this.addSeedToBranch(name);
return await this.createGMELibraryFromBranch(branchName, name);
};

ImportLibrary.prototype.addSeedToBranch = async function (name) {
Expand All @@ -91,8 +78,19 @@ define([
return branch;
};

ImportLibrary.prototype.createGMELibraryFromBranch = async function (branchName, libraryInfo) {
const name = libraryInfo.name;
ImportLibrary.prototype.getUniqueBranchName = async function (basename) {
const branches = await this.project.getBranches();
let name = basename;
let i = 2;

while (branches[name]) {
name = `${basename}${i}`;
i++;
}
return name;
};

ImportLibrary.prototype.createGMELibraryFromBranch = async function (branchName) {
const libraryData = {
projectId: this.projectId,
branchName: branchName,
Expand All @@ -101,15 +99,15 @@ define([

// Get the rootHash and commitHash from the commit on the tmp branch
const commits = await this.project.getHistory(branchName, 1);
let commit = commits[0];
let rootHash = commit.root;
const commit = commits[0];
const rootHash = commit.root;

libraryData.commitHash = commit._id;
await this.core.addLibrary(this.rootNode, name, rootHash, libraryData);
return {
const branchInfo = {
name: branchName,
hash: commit._id
};
return {branchInfo, rootHash, libraryData};
};

ImportLibrary.prototype.removeTemporaryBranch = function (branch) {
Expand Down
26 changes: 8 additions & 18 deletions src/visualizers/panels/Sidebar/SidebarPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,30 +164,20 @@ define([
});
};

SidebarPanel.prototype.applyUpdates = function (updates) {
// Seed Updates should apply the
const seedUpdates = updates.filter(update => update.type === Updates.SEED);
const promises = seedUpdates.map(update => {
const {name, hash} = update;
return Q.ninvoke(this._client, 'updateLibrary', name, hash);
});

// Apply the migrations
SidebarPanel.prototype.applyUpdates = async function (updates) {
const pluginId = 'ApplyUpdates';
const migrations = updates
.filter(update => update.type === Updates.MIGRATION)
.map(update => update.name);

const context = this._client.getCurrentPluginContext(pluginId);
context.pluginConfig = {
updates: migrations
};

promises.push(
Q.ninvoke(this._client, 'runServerPlugin', pluginId, context)
);
if (migrations.length) {
const context = this._client.getCurrentPluginContext(pluginId);
context.pluginConfig = {
updates: updates
};

return Q.all(promises);
await Q.ninvoke(this._client, 'runServerPlugin', pluginId, context);
}
};

return SidebarPanel;
Expand Down