Comparar commits
80 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 3676d4c340 | |||
| 16668468f4 | |||
| ffae88a168 | |||
| 25f5759c17 | |||
| 7a0eae386f | |||
| af5d74483a | |||
| 9bf7632aba | |||
| d7f3544bb3 | |||
| 19a7b2a8fa | |||
| aadd581189 | |||
| a5d00efd39 | |||
| a239c7bd44 | |||
| 5871b5058e | |||
| 3a8108b321 | |||
| b18a3b2747 | |||
| 884ba2557f | |||
| e2d3058de1 | |||
| 02739bfd62 | |||
| 89e2e387c7 | |||
| 0ac2b1b6ab | |||
| a36e8df404 | |||
| 93a89ddaa1 | |||
| 7281dcefc6 | |||
| bfc1f08c7e | |||
| ad08fce281 | |||
| bb2a67e3f6 | |||
| 3f0b7e4720 | |||
| 728c56261d | |||
| a3dd12386e | |||
| c017f9a1d7 | |||
| 6d95f21550 | |||
| 11cb9259d8 | |||
| 71f575c857 | |||
| cf4404eaf7 | |||
| 6ef0cb0bdc | |||
| e128cc408e | |||
| 1477421f1a | |||
| 671a8af458 | |||
| a4fcc73e9f | |||
| e88fb302d4 | |||
| ff1f29955a | |||
| 0b71ff6b9d | |||
| 4f3b6c5e39 | |||
| fe0c95116f | |||
| 4429cb11d4 | |||
| 56b20ab429 | |||
| 4d0f4c3609 | |||
| 209f46adb0 | |||
| 2ac374a56e | |||
| fc4c5db0ce | |||
| 1578886584 | |||
| 0927c2c270 | |||
| bd329bdfe3 | |||
| e3a499f409 | |||
| 63c78426d3 | |||
| 6ec2f69268 | |||
| 1ccd193ddd | |||
| a5d52dce33 | |||
| ca358ae7b9 | |||
| 0a1177c299 | |||
| 46bf346c5c | |||
| 8a94496e01 | |||
| d3cf339856 | |||
| 5c0c58c3be | |||
| ef607e0e76 | |||
| 305503ac7a | |||
| c76e62b976 | |||
| 554065ee11 | |||
| 7fba52ad97 | |||
| c56de24e7d | |||
| 6e16087fc3 | |||
| 8133acbb46 | |||
| d974cb8215 | |||
| 68021c1903 | |||
| 7178b89578 | |||
| 0935abe858 | |||
| 22225922e5 | |||
| 343f2ffa61 | |||
| 477d38d313 | |||
| 84e5377b8a |
@@ -33,3 +33,5 @@ node_modules
|
||||
tmp/
|
||||
test-tmp/
|
||||
blob-local-storage/
|
||||
src/seeds/nn/hash.txt
|
||||
src/seeds/pipeline/hash.txt
|
||||
|
||||
+13
-1
@@ -7,7 +7,13 @@
|
||||
**Notice**: DeepForge is still a work in progress and is also lacking significant documentation! That being said, any contributions and/or feedback is greatly appreciated (and feel free to always ask any questions on the gitter)!
|
||||
|
||||
# DeepForge
|
||||
DeepForge is an open-source visual development environment for deep learning. Currently, it supports Convolutional Neural Networks but we are planning on supporting additional deep learning classifiers such as RNNs and LSTMs. Additional features include real-time collaborative editing and version control.
|
||||
DeepForge is an open-source visual development environment for deep learning. Currently, it supports Convolutional Neural Networks, RNNs and LSTMs as well as the creation of custom layers. Additional features include:
|
||||
- Graphical architecture editor
|
||||
- Training/testing pipeline creation
|
||||
- Distributed pipeline execution
|
||||
- Real-time pipeline feedback
|
||||
- Collaborative editing
|
||||
- Automatic version control.
|
||||
|
||||
## Quick Start
|
||||
Simply run the following command to install deepforge with its dependencies:
|
||||
@@ -16,6 +22,12 @@ Simply run the following command to install deepforge with its dependencies:
|
||||
curl -o- https://raw.githubusercontent.com/dfst/deepforge/master/install.sh | bash
|
||||
```
|
||||
|
||||
Or, if you already have NodeJS (v6) installed, simply run
|
||||
|
||||
```
|
||||
npm install -g deepforge
|
||||
```
|
||||
|
||||
Next, start deepforge with `deepforge start`!
|
||||
|
||||
Finally, navigate to [http://localhost:8888](http://localhost:8888) to start using DeepForge! For more, detailed instructions, check out the [wiki](https://github.com/dfst/deepforge/wiki/Installation-Guide).
|
||||
|
||||
@@ -3,10 +3,16 @@
|
||||
|
||||
var gmeConfig = require('./config'),
|
||||
webgme = require('webgme'),
|
||||
path = require('path'),
|
||||
rm_rf = require('rimraf'),
|
||||
myServer;
|
||||
|
||||
webgme.addToRequireJsPaths(gmeConfig);
|
||||
|
||||
// Clear seed hash info
|
||||
['nn', 'pipeline'].map(lib => path.join(__dirname, 'src', 'seeds', lib, 'hash.txt'))
|
||||
.forEach(file => rm_rf.sync(file));
|
||||
|
||||
myServer = new webgme.standaloneServer(gmeConfig);
|
||||
myServer.start(function (err) {
|
||||
if (err) {
|
||||
|
||||
+2
-1
@@ -9,7 +9,8 @@
|
||||
"cache": {
|
||||
"useBlob": true,
|
||||
"dir": "~/.deepforge/worker/cache"
|
||||
}
|
||||
},
|
||||
"dir": "~/.deepforge/worker"
|
||||
},
|
||||
"mongo": {
|
||||
"dir": "~/.deepforge/data"
|
||||
|
||||
+142
-133
@@ -4,12 +4,12 @@ var Command = require('commander').Command,
|
||||
program = new Command(),
|
||||
childProcess = require('child_process'),
|
||||
rawSpawn = childProcess.spawn,
|
||||
Q = require('q'),
|
||||
execSync = childProcess.execSync,
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
version = require('../package.json').version,
|
||||
exists = require('exists-file'),
|
||||
forever = require('forever-monitor'),
|
||||
DEFAULT_CONFIG = require('./config.json'),
|
||||
merge = require('lodash.merge'),
|
||||
config,
|
||||
@@ -112,22 +112,12 @@ program
|
||||
.version('v' + version)
|
||||
.description('Command line interface for managing deepforge');
|
||||
|
||||
// start
|
||||
var start = function(main, opts) {
|
||||
var child = new forever.Monitor(main, opts);
|
||||
child.on('exit', function () {
|
||||
console.log('Exited after 3 failed restarts');
|
||||
});
|
||||
|
||||
child.start();
|
||||
};
|
||||
|
||||
var isLocalUri = function(protocol, uri) {
|
||||
return uri.indexOf(protocol + '://localhost') === 0 ||
|
||||
uri.indexOf(protocol + '://127.0.0.1') === 0;
|
||||
};
|
||||
|
||||
var checkMongo = function(args) {
|
||||
var checkMongo = function(args, notSilent) {
|
||||
// check the webgme config
|
||||
var gmeConfig = require('../config'),
|
||||
mongoUri = gmeConfig.mongo.uri;
|
||||
@@ -139,15 +129,26 @@ var checkMongo = function(args) {
|
||||
console.log('MongoDB is already running!');
|
||||
} catch (e) { // no pIds
|
||||
console.log('Starting MongoDB...');
|
||||
startMongo(args, true);
|
||||
var match = mongoUri.match(/:([0-9]+)/),
|
||||
port = '80';
|
||||
|
||||
if (match) {
|
||||
port = match[1];
|
||||
}
|
||||
|
||||
startMongo(args, port, !notSilent);
|
||||
}
|
||||
} else if (notSilent) {
|
||||
console.log(`Cannot start remote mongo locally: ${mongoUri}`);
|
||||
} else {
|
||||
console.log(`Using remote mongo: ${mongoUri}`);
|
||||
}
|
||||
};
|
||||
|
||||
var startMongo = function(args, silent) {
|
||||
var job = rawSpawn('mongod', ['--dbpath', p(config.mongo.dir)], {
|
||||
cwd: process.env.HOME
|
||||
});
|
||||
var startMongo = function(args, port, silent) {
|
||||
var opts = ['--dbpath', p(config.mongo.dir), '--port', port],
|
||||
job = rawSpawn('mongod', opts, {cwd: process.env.HOME});
|
||||
|
||||
if (!silent) {
|
||||
job.stdout.on('data',
|
||||
data => process.stdout.write(data.toString()));
|
||||
@@ -177,86 +178,95 @@ var startMongo = function(args, silent) {
|
||||
}
|
||||
});
|
||||
};
|
||||
var checkTorch = function() {
|
||||
return new Promise(_checkTorch)
|
||||
.catch(() => 'Torch installation failed');
|
||||
|
||||
var hasTorch = function() {
|
||||
var result = childProcess.spawnSync('th', ['--help']);
|
||||
return !result.error;
|
||||
};
|
||||
|
||||
var _checkTorch = function(resolve, reject) {
|
||||
var result = childProcess.spawnSync('th', ['--help']),
|
||||
tgtDir = p(config.torch.dir),
|
||||
gcl = `git clone https://github.com/torch/distro.git ${tgtDir} --recursive`;
|
||||
var installTorchExtras = function() {
|
||||
// Check if rnn is installed
|
||||
var result = childProcess.spawnSync('luarocks', ['list', '--porcelain']),
|
||||
pkgs = result.stdout.toString().split('\n')
|
||||
.map(line => line.match(/^[a-zA-Z0-9]+/g))
|
||||
.map(m => m && m[0]);
|
||||
|
||||
if (result.error) {
|
||||
if (pkgs.indexOf('rnn') === -1) {
|
||||
return spawn('luarocks', ['install', 'rnn']);
|
||||
} else {
|
||||
return Q();
|
||||
}
|
||||
};
|
||||
|
||||
var installTorch = function() {
|
||||
var tgtDir = p(config.torch.dir),
|
||||
args;
|
||||
|
||||
if (!hasTorch()) {
|
||||
// Try to install torch
|
||||
console.log(`Torch7 not found. Installing to ${tgtDir}...`);
|
||||
args = `clone https://github.com/torch/distro.git ${tgtDir} --recursive`.split(' ');
|
||||
|
||||
spawnMany([gcl],
|
||||
() => {
|
||||
process.chdir(tgtDir);
|
||||
spawnMany([
|
||||
'bash install-deps',
|
||||
'./install.sh',
|
||||
'luarocks install rnn'
|
||||
], () => {
|
||||
storeConfig('torch.dir', tgtDir);
|
||||
resolve(true);
|
||||
}, reject);
|
||||
},
|
||||
reject
|
||||
);
|
||||
return spawn('git', args)
|
||||
.then(code => {
|
||||
if (code !== 0) {
|
||||
if (code === 128) {
|
||||
console.error(`${tgtDir} is not empty. ` +
|
||||
'Please empty it or change the torch directory:\n' +
|
||||
'\n deepforge config torch.dir NEW/TORCH/PATH\n');
|
||||
|
||||
}
|
||||
|
||||
throw `Torch install Failed with exit code ${code}`;
|
||||
} else { // continue installation
|
||||
process.chdir(tgtDir);
|
||||
return spawn('bash', ['install-deps'])
|
||||
.then(() => spawn('bash', ['install.sh'], true))
|
||||
.then(() => {
|
||||
storeConfig('torch.dir', tgtDir);
|
||||
console.log('Installed torch. Please close and ' +
|
||||
're-open your terminal to use DeepForge w/ ' +
|
||||
'torch support!');
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resolve(false);
|
||||
return Q();
|
||||
}
|
||||
};
|
||||
|
||||
var spawnMany = function(cmds, succ, err) {
|
||||
var rawCmd,
|
||||
cmd,
|
||||
args,
|
||||
job;
|
||||
|
||||
if (cmds.length === 0) {
|
||||
return succ();
|
||||
}
|
||||
|
||||
rawCmd = cmds.shift();
|
||||
args = rawCmd.split(' ');
|
||||
cmd = args.shift();
|
||||
job = rawSpawn(cmd, args);
|
||||
job.stdout.on('data', data => process.stdout.write(data));
|
||||
job.stderr.on('data', data => process.stderr.write(data));
|
||||
job.on('close', code => {
|
||||
if (code) {
|
||||
console.log(`${rawCmd} failed w/ error code ${code}`);
|
||||
err(code, rawCmd);
|
||||
} else {
|
||||
spawnMany(cmds, succ, err);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var spawn = function(cmd, args, opts) {
|
||||
var promise,
|
||||
var deferred = Q.defer(),
|
||||
job,
|
||||
spawnOpts = typeof opts === 'object' ? opts : null,
|
||||
forwardStdin = opts === true,
|
||||
isOpen = true,
|
||||
err;
|
||||
|
||||
args = args || [];
|
||||
promise = new Promise((resolve, reject) => {
|
||||
var job = opts ? rawSpawn(cmd, args, opts) : rawSpawn(cmd, args);
|
||||
job.stdout.on('data', data => process.stdout.write(data));
|
||||
job.stderr.on('data', data => process.stderr.write(data));
|
||||
job.on('close', code => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(code);
|
||||
job = spawnOpts ? rawSpawn(cmd, args, spawnOpts) : rawSpawn(cmd, args);
|
||||
job.stdout.on('data', data => process.stdout.write(data));
|
||||
job.stderr.on('data', data => process.stderr.write(data));
|
||||
job.on('close', code => {
|
||||
isOpen = false;
|
||||
if (err) {
|
||||
deferred.reject(err, code);
|
||||
} else {
|
||||
deferred.resolve(code);
|
||||
}
|
||||
});
|
||||
job.on('error', e => err = e);
|
||||
|
||||
if (forwardStdin) {
|
||||
process.stdin.on('data', data => {
|
||||
if (isOpen) {
|
||||
job.stdin.write(data);
|
||||
}
|
||||
});
|
||||
job.on('error', e => err = e);
|
||||
});
|
||||
}
|
||||
|
||||
return promise;
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
program.command('start')
|
||||
@@ -266,44 +276,45 @@ program.command('start')
|
||||
.option('-w, --worker [url]', 'start a worker and connect to given url. Defaults to local deepforge')
|
||||
.option('-m, --mongo', 'start MongoDB')
|
||||
.action(args => {
|
||||
var main = path.join(__dirname, 'start-local.js'),
|
||||
opts;
|
||||
|
||||
opts = {
|
||||
max: 3,
|
||||
args: []
|
||||
};
|
||||
var main = path.join(__dirname, 'start-local.js');
|
||||
|
||||
if (args.port) {
|
||||
opts.env = {
|
||||
PORT: args.port
|
||||
};
|
||||
process.env.PORT = args.port;
|
||||
}
|
||||
|
||||
if (args.server) {
|
||||
checkMongo(args);
|
||||
main = path.join(__dirname, '..', 'app.js');
|
||||
start(main, opts);
|
||||
spawn('node', [main]);
|
||||
}
|
||||
|
||||
if (args.worker) {
|
||||
checkTorch().then(() => {
|
||||
main = path.join(__dirname, 'start-worker.js');
|
||||
if (args.worker !== true) {
|
||||
opts.args.push(args.worker);
|
||||
}
|
||||
start(main, opts);
|
||||
});
|
||||
if (hasTorch()) {
|
||||
installTorchExtras().then(() => {
|
||||
main = path.join(__dirname, 'start-worker.js');
|
||||
if (args.worker !== true) {
|
||||
spawn('node', [main, args.worker]);
|
||||
} else {
|
||||
spawn('node', [main]);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
installTorch();
|
||||
}
|
||||
}
|
||||
|
||||
if (args.mongo) {
|
||||
startMongo(args);
|
||||
checkMongo(args, true);
|
||||
}
|
||||
|
||||
if (!args.server && !args.worker && !args.mongo) {
|
||||
// Starting everything
|
||||
checkMongo(args);
|
||||
checkTorch().then(() => start(main, opts));
|
||||
if (hasTorch()) {
|
||||
installTorchExtras().then(() => spawn('node', [main]));
|
||||
} else {
|
||||
installTorch();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
@@ -348,34 +359,34 @@ program
|
||||
|
||||
if (args.torch || !args.server) {
|
||||
// Update torch
|
||||
checkTorch().then(justInstalled => {
|
||||
if (!justInstalled) {
|
||||
// Upgrade torch
|
||||
console.log('Upgrading torch...');
|
||||
console.log(`Checking for torch in ${config.torch.dir}`);
|
||||
// Verify that torch is installed in the config's location
|
||||
if (!exists.sync(path.join(config.torch.dir, 'update.sh'))) {
|
||||
// config is incorrect!
|
||||
console.log('Could not find torch installation. Please update the deepforge config with:');
|
||||
console.log('');
|
||||
console.log(' deepforge config torch.dir ~/path/to/torch/install');
|
||||
console.log('');
|
||||
return;
|
||||
}
|
||||
|
||||
spawn('bash', ['./update.sh'], {cwd: p(config.torch.dir)})
|
||||
.catch(err => console.log('Upgrade failed w/ error code: ' + err.code))
|
||||
.then(() => {
|
||||
console.log('About to update rnn package...');
|
||||
// Update rnn
|
||||
return spawn('luarocks', ['install', 'rnn']);
|
||||
})
|
||||
.then(() => {
|
||||
console.log('Upgrade successful!');
|
||||
})
|
||||
.catch(code => console.log('Upgrade failed w/ error code: ' + code));
|
||||
if (hasTorch()) {
|
||||
// Upgrade torch
|
||||
console.log('Upgrading torch...');
|
||||
console.log(`Checking for torch in ${config.torch.dir}`);
|
||||
// Verify that torch is installed in the config's location
|
||||
if (!exists.sync(path.join(config.torch.dir, 'update.sh'))) {
|
||||
// config is incorrect!
|
||||
console.log('Could not find torch installation. Please update the deepforge config with:');
|
||||
console.log('');
|
||||
console.log(' deepforge config torch.dir ~/path/to/torch/install');
|
||||
console.log('');
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
spawn('bash', ['./update.sh'], {cwd: p(config.torch.dir)})
|
||||
.catch(err => console.log('Upgrade failed w/ error code: ' + err.code))
|
||||
.then(() => {
|
||||
console.log('About to update rnn package...');
|
||||
// Update rnn
|
||||
return spawn('luarocks', ['install', 'rnn']);
|
||||
})
|
||||
.then(() => {
|
||||
console.log('Upgrade successful!');
|
||||
})
|
||||
.catch(code => console.log('Upgrade failed w/ error code: ' + code));
|
||||
} else {
|
||||
installTorch();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -400,11 +411,9 @@ program
|
||||
}
|
||||
|
||||
if (!opts.torch || opts.clean) { // uninstall deepforge
|
||||
spawnMany(
|
||||
['npm uninstall -g deepforge'],
|
||||
() => console.log('deepforge has been uninstalled!'),
|
||||
() => console.log('uninstall failed')
|
||||
);
|
||||
spawn('npm', ['uninstall', '-g', 'deepforge'])
|
||||
.then(() => console.log('deepforge has been uninstalled!'))
|
||||
.catch(() => console.log('uninstall failed'));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -440,8 +449,8 @@ program
|
||||
|
||||
module.exports = function(cmd) {
|
||||
var cmds = cmd.split(/\s+/).filter(w => !!w);
|
||||
cmds.unshift('node');
|
||||
cmds.unshift('./bin/deepforge');
|
||||
cmds.unshift('node');
|
||||
program.parse(cmds);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"DEEPFORGE_BLOB_DIR": "blob.dir",
|
||||
"DEEPFORGE_WORKER_CACHE": "worker.cache.dir",
|
||||
"DEEPFORGE_WORKER_DIR": "worker.dir",
|
||||
"DEEPFORGE_WORKER_USE_BLOB": "worker.cache.useBlob"
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ var spawn = require('child_process').spawn,
|
||||
gmeConfig = require(__dirname + '/../config');
|
||||
|
||||
// Set the cache to the blob
|
||||
console.log(gmeConfig);
|
||||
if (gmeConfig.blob.type === 'FS') {
|
||||
process.env.DEEPFORGE_WORKER_CACHE = path.resolve(gmeConfig.blob.fsDir + '/wg-content');
|
||||
}
|
||||
|
||||
+17
-4
@@ -8,8 +8,10 @@ var path = require('path'),
|
||||
projectConfig = require(__dirname + '/../config'),
|
||||
executorSrc = path.join(__dirname, '..', 'node_modules', 'webgme', 'src',
|
||||
'server', 'middleware', 'executor', 'worker'),
|
||||
workerPath = path.join(__dirname, '..', 'src', 'worker'),
|
||||
workerConfigPath = path.join(workerPath, 'config_' + Date.now() + '.json'),
|
||||
id = Date.now(),
|
||||
workerRootPath = process.env.DEEPFORGE_WORKER_DIR || path.join(__dirname, '..', 'src', 'worker'),
|
||||
workerPath = path.join(workerRootPath, `worker_${id}`),
|
||||
workerConfigPath = path.join(workerPath, 'config.json'),
|
||||
workerTmp = path.join(workerPath, 'tmp'),
|
||||
address,
|
||||
config = {};
|
||||
@@ -24,9 +26,20 @@ var createDir = function(dir) {
|
||||
}
|
||||
return false;
|
||||
};
|
||||
createDir(workerRootPath);
|
||||
createDir(workerPath);
|
||||
createDir(workerTmp);
|
||||
|
||||
// Create sym link to the node_modules
|
||||
var modules = path.join(workerRootPath, 'node_modules');
|
||||
try {
|
||||
fs.statSync(modules);
|
||||
} catch (e) {
|
||||
// Create dir
|
||||
childProcess.spawnSync('ln', ['-s', `${__dirname}/../node_modules`, modules]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check torch support
|
||||
var result = childProcess.spawnSync('th', ['--help']);
|
||||
if (result.error) {
|
||||
@@ -37,8 +50,8 @@ if (result.error) {
|
||||
}
|
||||
|
||||
var cleanUp = function() {
|
||||
console.log('removing config ', workerConfigPath);
|
||||
rm_rf.sync(workerConfigPath);
|
||||
console.log('removing worker directory ', workerPath);
|
||||
rm_rf.sync(workerPath);
|
||||
};
|
||||
|
||||
var startExecutor = function() {
|
||||
|
||||
@@ -12,10 +12,32 @@
|
||||
"LayerColors": {}
|
||||
},
|
||||
"BreadcrumbHeader": {
|
||||
"pathRule": "history"
|
||||
"pathRule": "history",
|
||||
"cachePrefix": "deepforge-header"
|
||||
},
|
||||
"FloatingActionButton": {
|
||||
"hideOnEmpty": true
|
||||
"hideOnEmpty": true,
|
||||
"pluginUIConfigs": {
|
||||
"GenerateArchitecture": {
|
||||
"icon": "description",
|
||||
"hotkey": "shift enter",
|
||||
"priority": -1
|
||||
},
|
||||
"ExecutePipeline": {
|
||||
"icon": "play_arrow",
|
||||
"hotkey": "shift enter",
|
||||
"color": "green",
|
||||
"priority": 1
|
||||
},
|
||||
"ImportTorch": {
|
||||
"icon": "import_export",
|
||||
"priority": -1
|
||||
},
|
||||
"GenerateExecFile": {
|
||||
"icon": "play_for_work",
|
||||
"priority": -1
|
||||
}
|
||||
}
|
||||
},
|
||||
"GenericUIProjectNavigatorController": {
|
||||
"rootMenuClass": "deepforge-logo",
|
||||
|
||||
@@ -19,7 +19,6 @@ config.plugin.allowBrowserExecution = true;
|
||||
config.plugin.allowServerExecution = true;
|
||||
|
||||
config.executor.enable = true;
|
||||
config.executor.clearOldDataAtStartUp = true;
|
||||
|
||||
config.visualization.extraCss.push('deepforge/styles/global.css');
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ var config = require('./config.default'),
|
||||
|
||||
// Turn up the worker polling rate
|
||||
config.executor.workerRefreshInterval = 150;
|
||||
config.executor.clearOldDataAtStartUp = true,
|
||||
|
||||
validateConfig(config);
|
||||
module.exports = config;
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = require('./config.default');
|
||||
var config = require('./config.default'),
|
||||
path = require('path');
|
||||
|
||||
config.server.port = 9001;
|
||||
config.mongo.uri = 'mongodb://127.0.0.1:27017/webgme_tests';
|
||||
config.blob.fsDir = path.join(__dirname, '..', 'test-tmp', 'blob');
|
||||
|
||||
module.exports = config;
|
||||
module.exports = config;
|
||||
|
||||
+22
-20
@@ -6,33 +6,35 @@
|
||||
var config = require('webgme/config/config.default'),
|
||||
validateConfig = require('webgme/config/validator');
|
||||
|
||||
|
||||
// The paths can be loaded from the webgme-setup.json
|
||||
config.plugin.basePaths.push('src/plugins');
|
||||
config.plugin.basePaths.push('node_modules/webgme-simple-nodes/src/plugins');
|
||||
config.visualization.layout.basePaths.push('node_modules/webgme-chflayout/src/layouts');
|
||||
config.visualization.decoratorPaths.push('src/decorators');
|
||||
config.visualization.decoratorPaths.push('node_modules/webgme-easydag/src/decorators');
|
||||
config.seedProjects.basePaths.push('src/seeds/nn');
|
||||
config.seedProjects.basePaths.push('src/seeds/devTests');
|
||||
config.seedProjects.basePaths.push('src/seeds/devUtilTests');
|
||||
config.seedProjects.basePaths.push('src/seeds/pipeline');
|
||||
config.seedProjects.basePaths.push('src/seeds/devPipelineTests');
|
||||
config.seedProjects.basePaths.push('src/seeds/project');
|
||||
config.seedProjects.basePaths.push('src/seeds/cifar10');
|
||||
config.seedProjects.basePaths.push('src/seeds/xor');
|
||||
config.plugin.basePaths.push(__dirname + '/../src/plugins');
|
||||
config.plugin.basePaths.push(__dirname + '/../node_modules/webgme-simple-nodes/src/plugins');
|
||||
config.visualization.layout.basePaths.push(__dirname + '/../node_modules/webgme-chflayout/src/layouts');
|
||||
config.visualization.decoratorPaths.push(__dirname + '/../src/decorators');
|
||||
config.visualization.decoratorPaths.push(__dirname + '/../node_modules/webgme-easydag/src/decorators');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/nn');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devTests');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devUtilTests');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/pipeline');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devPipelineTests');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/project');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/cifar10');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/xor');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devProject');
|
||||
|
||||
|
||||
|
||||
config.visualization.panelPaths.push('node_modules/webgme-fab/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push('node_modules/webgme-breadcrumbheader/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push('node_modules/webgme-autoviz/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push('node_modules/webgme-easydag/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push('src/visualizers/panels');
|
||||
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-fab/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-breadcrumbheader/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-autoviz/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-easydag/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push(__dirname + '/../src/visualizers/panels');
|
||||
|
||||
|
||||
config.rest.components['execution/logs'] = __dirname + '/../src/routers/JobLogsAPI/JobLogsAPI.js';
|
||||
|
||||
// Visualizer descriptors
|
||||
config.visualization.visualizerDescriptors.push('./src/visualizers/Visualizers.json');
|
||||
config.visualization.visualizerDescriptors.push(__dirname + '/../src/visualizers/Visualizers.json');
|
||||
// Add requirejs paths
|
||||
config.requirejsPaths = {
|
||||
'EllipseDecorator': 'node_modules/webgme-easydag/src/decorators/EllipseDecorator',
|
||||
|
||||
+15
-40
@@ -41,15 +41,9 @@ detect_profile() {
|
||||
}
|
||||
detect_profile
|
||||
|
||||
command -v node >/dev/null 2>&1 || {
|
||||
# No node! Install nvm
|
||||
echo >&2 "NodeJS is not found. Installing (using nvm)...";
|
||||
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash;
|
||||
source $DETECTED_PROFILE
|
||||
. $NVM_DIR/nvm.sh
|
||||
|
||||
set_node_version() {
|
||||
# Install nodejs v6.2.0
|
||||
echo "Installing nodejs v6.2.0"
|
||||
echo "Installing NodeJS v6.2.0"
|
||||
nvm install v6.2.0
|
||||
nvm alias default v6.2.0
|
||||
|
||||
@@ -58,40 +52,21 @@ command -v node >/dev/null 2>&1 || {
|
||||
}
|
||||
|
||||
command -v node >/dev/null 2>&1 || {
|
||||
# No mongod!
|
||||
echo >&2 "MongoDB is not found. Installing...";
|
||||
if [[ `uname` == "Darwin" ]]; then
|
||||
brew install mongodb
|
||||
elif [[ "$(uname)" == 'Linux' ]]; then
|
||||
# No node! Install nvm
|
||||
echo >&2 "NodeJS is not found. Installing (using nvm)...";
|
||||
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.1/install.sh | bash;
|
||||
source $DETECTED_PROFILE
|
||||
. $NVM_DIR/nvm.sh
|
||||
|
||||
if [[ -r /etc/os-release ]]; then
|
||||
# this will get the required information without dirtying any env state
|
||||
DIST_VERS="$( ( . /etc/os-release &>/dev/null
|
||||
echo "$ID $VERSION_ID") )"
|
||||
DISTRO="${DIST_VERS%% *}" # get our distro name
|
||||
VERSION="${DIST_VERS##* }" # get our version number
|
||||
elif [[ -r /etc/lsb-release ]]; then
|
||||
DIST_VERS="$( ( . /etc/lsb-release &>/dev/null
|
||||
echo "${DISTRIB_ID,,} $DISTRIB_RELEASE") )"
|
||||
DISTRO="${DIST_VERS%% *}" # get our distro name
|
||||
VERSION="${DIST_VERS##* }" # get our version number
|
||||
else # well, I'm out of ideas for now
|
||||
echo '==> Failed to determine distro and version.'
|
||||
exit 1
|
||||
fi
|
||||
set_node_version
|
||||
}
|
||||
|
||||
# Detect archlinux
|
||||
if [[ "$DISTRO" = "arch" ]]; then
|
||||
distribution="archlinux"
|
||||
sudo pacman -S mongodb
|
||||
# Detect Ubuntu
|
||||
elif [[ "$DISTRO" = "ubuntu" ]]; then
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
sudo apt-get install mongodb
|
||||
else
|
||||
NEEDS_MONGO=true
|
||||
fi
|
||||
fi
|
||||
# Check node version supports arrow fns and string templates
|
||||
node -e '() => console.log(`print "3": ${1+2}`)' >/dev/null 2>&1 || {
|
||||
echo "Unsupported version of NodeJS."
|
||||
echo ""
|
||||
echo "Please update NodeJS to version 4.x.x or later (6.x.x recommended)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo >&2 "Installing DeepForge...";
|
||||
|
||||
+7
-4
@@ -8,23 +8,25 @@
|
||||
"start-dev": "NODE_ENV=dev node app.js",
|
||||
"local": "node ./bin/start-local.js",
|
||||
"worker": "node ./bin/start-worker.js",
|
||||
"test": "node ./node_modules/mocha/bin/mocha --recursive test",
|
||||
"test": "mkdir ./test-tmp; node ./node_modules/mocha/bin/mocha --recursive test",
|
||||
"test-cover": "node node_modules/istanbul/lib/cli.js --hook-run-in-context cover node_modules/mocha/bin/_mocha -- -R spec test/**/*",
|
||||
"watch-test": "./node_modules/nodemon/bin/nodemon.js --exec 'node ./node_modules/mocha/bin/mocha --recursive test'",
|
||||
"build-nn": "node ./utils/nn-parser.js"
|
||||
},
|
||||
"version": "0.13.0",
|
||||
"version": "0.16.0",
|
||||
"dependencies": {
|
||||
"commander": "^2.9.0",
|
||||
"dotenv": "^2.0.0",
|
||||
"exists-file": "^2.1.0",
|
||||
"forever-monitor": "^1.7.0",
|
||||
"express": "^4.14.0",
|
||||
"lodash.difference": "^4.1.2",
|
||||
"lodash.merge": "^4.5.1",
|
||||
"nodemon": "^1.9.2",
|
||||
"q": "1.4.1",
|
||||
"rimraf": "^2.4.0",
|
||||
"webgme": "^2.0.0",
|
||||
"webgme-autoviz": "dfst/webgme-autoviz",
|
||||
"webgme-breadcrumbheader": "^2.1.0",
|
||||
"webgme-breadcrumbheader": "^2.1.1",
|
||||
"webgme-chflayout": "^2.0.0",
|
||||
"webgme-easydag": "dfst/webgme-easydag",
|
||||
"webgme-fab": "dfst/webgme-fab",
|
||||
@@ -34,6 +36,7 @@
|
||||
"chai": "^3.0.0",
|
||||
"jszip": "^2.5.0",
|
||||
"mocha": "^2.2.5",
|
||||
"istanbul": "^0.4.5",
|
||||
"mockery": "^1.7.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,27 @@ define({
|
||||
// DeepForge metadata creation in dist execution
|
||||
START_CMD: 'deepforge-cmd',
|
||||
|
||||
IMAGE: 'IMG',
|
||||
IMAGE: { // all prefixed w/ 'IMG' for simple upload detection
|
||||
PREFIX: 'IMG',
|
||||
BASIC: 'IMG-B',
|
||||
CREATE: 'IMG-C',
|
||||
UPDATE: 'IMG-U',
|
||||
NAME: 'IMAGE-N' // No upload required
|
||||
},
|
||||
|
||||
GRAPH_CREATE: 'GRAPH',
|
||||
GRAPH_PLOT: 'PLOT',
|
||||
GRAPH_CREATE_LINE: 'LINE',
|
||||
|
||||
// Code Generation Constants
|
||||
CTOR_ARGS_ATTR: 'ctor_arg_order'
|
||||
CTOR_ARGS_ATTR: 'ctor_arg_order',
|
||||
|
||||
// Operation types
|
||||
OP: {
|
||||
INPUT: 'Input',
|
||||
OUTPUT: 'Output'
|
||||
},
|
||||
|
||||
// Job stdout update
|
||||
STDOUT_UPDATE: 'stdout_update'
|
||||
});
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/* globals define */
|
||||
define([
|
||||
'q',
|
||||
'superagent'
|
||||
], function(
|
||||
Q,
|
||||
superagent
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
// Wrap the ability to read, update, and delete logs using the JobLogsAPI
|
||||
var JobLogsClient = function(params) {
|
||||
params = params || {};
|
||||
|
||||
this.logger = params.logger.fork('JobLogsClient');
|
||||
|
||||
// Get the server url
|
||||
this.token = params.token;
|
||||
this.origin = this._getServerUrl(params);
|
||||
this.relativeUrl = '/execution/logs';
|
||||
this.url = this.origin + this.relativeUrl;
|
||||
|
||||
this.logger.debug(`Setting url to ${this.url}`);
|
||||
|
||||
// Get the project, branch name
|
||||
if (!(params.branchName && params.projectId)) {
|
||||
throw Error('"branchName" and "projectId" required');
|
||||
}
|
||||
this.branch = params.branchName;
|
||||
this.project = params.projectId;
|
||||
this._modifiedJobs = [];
|
||||
|
||||
this.logger.debug(`Using <project>:<branch>: "${this.project}"/"${this.branch}"`);
|
||||
this.logger.info('ctor finished');
|
||||
};
|
||||
|
||||
JobLogsClient.prototype._getServerUrl = function(params) {
|
||||
if (typeof window !== 'undefined') {
|
||||
return window.location.origin;
|
||||
}
|
||||
|
||||
// If not in browser, set using the params
|
||||
var server = params.server || '127.0.0.1',
|
||||
port = params.port || '80',
|
||||
protocol = params.httpsecure ? 'https' : 'http'; // default is http
|
||||
|
||||
return params.origin || `${protocol}://${server}:${port}`;
|
||||
};
|
||||
|
||||
// This method could be optimized - it could make a log of requests
|
||||
JobLogsClient.prototype.fork = function(forkName) {
|
||||
var jobIds = this._modifiedJobs,
|
||||
deferred = Q.defer(),
|
||||
url = [
|
||||
this.url,
|
||||
'migrate',
|
||||
encodeURIComponent(this.project),
|
||||
encodeURIComponent(this.branch),
|
||||
encodeURIComponent(forkName)
|
||||
].join('/'),
|
||||
req = superagent.post(url);
|
||||
|
||||
this.logger.info(`migrating ${jobIds.length} jobs from ${this.branch} to ${forkName} in ${this.project}`);
|
||||
if (this.token) {
|
||||
req.set('Authorization', 'Bearer ' + this.token);
|
||||
}
|
||||
|
||||
req.send({jobs: jobIds})
|
||||
.end((err, res) => {
|
||||
if (err || res.status > 399) {
|
||||
return deferred.reject(err || res.status);
|
||||
}
|
||||
|
||||
return deferred.resolve(res);
|
||||
});
|
||||
|
||||
this.branch = forkName;
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
JobLogsClient.prototype.getUrl = function(jobId) {
|
||||
return [
|
||||
this.url,
|
||||
encodeURIComponent(this.project),
|
||||
encodeURIComponent(this.branch),
|
||||
encodeURIComponent(jobId)
|
||||
].join('/');
|
||||
};
|
||||
|
||||
JobLogsClient.prototype._logRequest = function(method, jobId, content) {
|
||||
var deferred = Q.defer(),
|
||||
req = superagent[method](this.getUrl(jobId));
|
||||
|
||||
this.logger.info(`sending ${method} request to ${this.getUrl(jobId)}`);
|
||||
if (this.token) {
|
||||
req.set('Authorization', 'Bearer ' + this.token);
|
||||
}
|
||||
|
||||
if (content) {
|
||||
req = req.send(content);
|
||||
}
|
||||
|
||||
req.end((err, res) => {
|
||||
if (err || res.status > 399) {
|
||||
return deferred.reject(err || res.status);
|
||||
}
|
||||
|
||||
return deferred.resolve(res);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
JobLogsClient.prototype.appendTo = function(jobId, text) {
|
||||
this._modifiedJobs.push(jobId);
|
||||
this.logger.info(`Appending logs to ${jobId}`);
|
||||
return this._logRequest('patch', jobId, {patch: text});
|
||||
};
|
||||
|
||||
JobLogsClient.prototype.getLog = function(jobId) {
|
||||
this.logger.info(`Getting logs for ${jobId}`);
|
||||
return this._logRequest('get', jobId)
|
||||
.then(res => res.text);
|
||||
};
|
||||
|
||||
JobLogsClient.prototype.deleteLog = function(jobId) {
|
||||
this.logger.info(`Deleting logs for ${jobId}`);
|
||||
return this._logRequest('delete', jobId);
|
||||
};
|
||||
|
||||
return JobLogsClient;
|
||||
});
|
||||
+51
-22
@@ -4,12 +4,14 @@ define([
|
||||
'panel/FloatingActionButton/styles/Materialize',
|
||||
'js/RegistryKeys',
|
||||
'js/Panels/MetaEditor/MetaEditorConstants',
|
||||
'js/Constants'
|
||||
'js/Constants',
|
||||
'q'
|
||||
], function(
|
||||
Materialize,
|
||||
REGISTRY_KEYS,
|
||||
META_CONSTANTS,
|
||||
CONSTANTS
|
||||
CONSTANTS,
|
||||
Q
|
||||
) {
|
||||
var DeepForge = {},
|
||||
placesTerritoryId,
|
||||
@@ -92,6 +94,7 @@ define([
|
||||
};
|
||||
|
||||
//////////////////// DeepForge places detection ////////////////////
|
||||
DeepForge.places = {};
|
||||
var TYPE_TO_CONTAINER = {
|
||||
|
||||
Architecture: 'MyArchitectures',
|
||||
@@ -107,10 +110,29 @@ define([
|
||||
PLACE_NAMES = Object.keys(TYPE_TO_CONTAINER).map(key => TYPE_TO_CONTAINER[key]);
|
||||
|
||||
// Add DeepForge directories
|
||||
var placePromises = {},
|
||||
setPlaceId = {},
|
||||
firstProject = true;
|
||||
|
||||
var getPlace = function(name) {
|
||||
return placePromises[name];
|
||||
};
|
||||
|
||||
var initializePlaces = function() {
|
||||
PLACE_NAMES.forEach(name => {
|
||||
var deferred = Q.defer();
|
||||
placePromises[name] = deferred.promise;
|
||||
setPlaceId[name] = deferred.resolve;
|
||||
});
|
||||
};
|
||||
|
||||
var updateDeepForgeNamespace = function() {
|
||||
var territory = {};
|
||||
|
||||
DeepForge.places = {};
|
||||
if (!firstProject) {
|
||||
initializePlaces();
|
||||
}
|
||||
firstProject = false;
|
||||
|
||||
// Create a territory
|
||||
if (placesTerritoryId) {
|
||||
@@ -137,13 +159,16 @@ define([
|
||||
nodes.forEach(node =>
|
||||
nodeIdsByName[node.getAttribute('name')] = node.getId());
|
||||
|
||||
PLACE_NAMES.forEach(name => DeepForge.places[name] = nodeIdsByName[name]);
|
||||
PLACE_NAMES.forEach(name => setPlaceId[name](nodeIdsByName[name]));
|
||||
|
||||
// Remove the territory
|
||||
client.removeUI(placesTerritoryId);
|
||||
placesTerritoryId = null;
|
||||
};
|
||||
|
||||
initializePlaces();
|
||||
PLACE_NAMES.forEach(name => DeepForge.places[name] = getPlace.bind(null, name));
|
||||
|
||||
//////////////////// DeepForge creation actions ////////////////////
|
||||
var instances = [
|
||||
'Architecture',
|
||||
@@ -156,8 +181,7 @@ define([
|
||||
];
|
||||
|
||||
var createNew = function(type, metasheetName) {
|
||||
var parentId,
|
||||
placeName = TYPE_TO_CONTAINER[type],
|
||||
var placeName = TYPE_TO_CONTAINER[type],
|
||||
newId,
|
||||
baseId,
|
||||
msg = `Created new ${type + (metasheetName ? ' prototype' : '')}`;
|
||||
@@ -167,19 +191,20 @@ define([
|
||||
.getId();
|
||||
|
||||
// Look up the parent container
|
||||
parentId = DeepForge.places[placeName];
|
||||
DeepForge.places[placeName]().then(parentId => {
|
||||
|
||||
client.startTransaction(msg);
|
||||
newId = createNamedNode(baseId, parentId, !!metasheetName);
|
||||
client.startTransaction(msg);
|
||||
newId = createNamedNode(baseId, parentId, !!metasheetName);
|
||||
|
||||
if (metasheetName) {
|
||||
addToMetaSheet(newId, metasheetName);
|
||||
}
|
||||
if (metasheetName) {
|
||||
addToMetaSheet(newId, metasheetName);
|
||||
}
|
||||
|
||||
client.completeTransaction();
|
||||
client.completeTransaction();
|
||||
|
||||
WebGMEGlobal.State.registerActiveObject(newId);
|
||||
return newId;
|
||||
WebGMEGlobal.State.registerActiveObject(newId);
|
||||
return newId;
|
||||
});
|
||||
};
|
||||
|
||||
var createCustomLayer = function(typeName) {
|
||||
@@ -200,16 +225,20 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
client.startTransaction(msg);
|
||||
return DeepForge.places.MyLayers()
|
||||
.then(id => {
|
||||
|
||||
newId = createNamedNode(baseId, DeepForge.places.MyLayers, true);
|
||||
addToMetaSheet(newId, 'CustomLayers');
|
||||
client.addMixin(newId, customLayerId);
|
||||
client.setRegistry(newId, REGISTRY_KEYS.IS_ABSTRACT, false);
|
||||
client.startTransaction(msg);
|
||||
|
||||
client.completeTransaction();
|
||||
newId = createNamedNode(baseId, id, true);
|
||||
addToMetaSheet(newId, 'CustomLayers');
|
||||
client.addMixin(newId, customLayerId);
|
||||
client.setRegistry(newId, REGISTRY_KEYS.IS_ABSTRACT, false);
|
||||
|
||||
WebGMEGlobal.State.registerActiveObject(newId);
|
||||
client.completeTransaction();
|
||||
|
||||
WebGMEGlobal.State.registerActiveObject(newId);
|
||||
});
|
||||
};
|
||||
|
||||
// Creating Artifacts
|
||||
|
||||
@@ -2,14 +2,16 @@
|
||||
// This is an 'executor' containing the implementations of all local operations
|
||||
// These are all primitives in DeepForge
|
||||
define([
|
||||
'deepforge/Constants'
|
||||
], function(
|
||||
CONSTANTS
|
||||
) {
|
||||
'use strict';
|
||||
var LocalExecutor = function() {
|
||||
};
|
||||
|
||||
// Should these be in lua?
|
||||
LocalExecutor.prototype.ArtifactLoader = function(node) {
|
||||
LocalExecutor.prototype[CONSTANTS.OP.INPUT] = function(node) {
|
||||
// Get the hash from the output node
|
||||
var hash;
|
||||
return this.core.loadChildren(node)
|
||||
@@ -18,13 +20,13 @@ define([
|
||||
var output = cntrs
|
||||
.find(cntr => {
|
||||
var metaNode = this.core.getMetaType(cntr),
|
||||
metaName = this.core.getAttribute(metaNode, 'name');
|
||||
metaName = this.getAttribute(metaNode, 'name');
|
||||
return metaName === 'Outputs';
|
||||
});
|
||||
return this.core.loadChildren(output);
|
||||
})
|
||||
.then(dataNodes => {
|
||||
hash = this.core.getAttribute(dataNodes[0], 'data');
|
||||
hash = this.getAttribute(dataNodes[0], 'data');
|
||||
return this.getOutputs(node);
|
||||
})
|
||||
.then(outputTuples => {
|
||||
@@ -46,7 +48,7 @@ define([
|
||||
var hash,
|
||||
typeId = this.core.getPointerPath(node, 'type'),
|
||||
type,
|
||||
artifactName = this.core.getAttribute(node, 'artifactName');
|
||||
artifactName = this.getAttribute(node, 'artifactName');
|
||||
|
||||
return this.core.loadByPath(this.rootNode, typeId)
|
||||
.then(_type => {
|
||||
@@ -56,25 +58,20 @@ define([
|
||||
.then(saveDir => this.core.loadChildren(saveDir))
|
||||
.then(artifacts => {
|
||||
return artifacts.find(artifact =>
|
||||
this.core.getAttribute(artifact, 'name') === artifactName &&
|
||||
this.getAttribute(artifact, 'name') === artifactName &&
|
||||
this.isMetaTypeOf(artifact, type));
|
||||
})
|
||||
.then(matchingArtifact => {
|
||||
hash = matchingArtifact && this.core.getAttribute(matchingArtifact, 'data');
|
||||
hash = matchingArtifact && this.getAttribute(matchingArtifact, 'data');
|
||||
// If no hash, just continue (the subsequent ops will receive 'nil')
|
||||
if (!hash) {
|
||||
return this.onOperationComplete(node);
|
||||
} else {
|
||||
return this.getOutputs(node)
|
||||
.then(outputPairs => {
|
||||
var outputs = outputPairs.map(pair => pair[2]),
|
||||
paths;
|
||||
|
||||
paths = outputs.map(output => this.core.getPath(output));
|
||||
var outputs = outputPairs.map(pair => pair[2]);
|
||||
// Get the 'data' hash and store it in the output data ports
|
||||
this.logger.info(`Loading blob data (${hash}) to ${paths.map(p => `"${p}"`)}`);
|
||||
|
||||
outputs.forEach(output => this.core.setAttribute(output, 'data', hash));
|
||||
outputs.forEach(output => this.setAttribute(output, 'data', hash));
|
||||
|
||||
this.onOperationComplete(node);
|
||||
});
|
||||
@@ -97,7 +94,7 @@ define([
|
||||
|
||||
if (containers.length > 1) {
|
||||
saveDir = containers.find(c =>
|
||||
this.core.getAttribute(c, 'name').toLowerCase().indexOf('artifacts') > -1
|
||||
this.getAttribute(c, 'name').toLowerCase().indexOf('artifacts') > -1
|
||||
) || containers[0];
|
||||
}
|
||||
|
||||
@@ -105,7 +102,7 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
LocalExecutor.prototype.Save = function(node) {
|
||||
LocalExecutor.prototype[CONSTANTS.OP.OUTPUT] = function(node) {
|
||||
var parentNode,
|
||||
currNameHashPairs;
|
||||
|
||||
@@ -119,8 +116,8 @@ define([
|
||||
.then(artifacts => {
|
||||
currNameHashPairs = artifacts
|
||||
.map(node => [
|
||||
this.core.getAttribute(node, 'name'),
|
||||
this.core.getAttribute(node, 'data')
|
||||
this.getAttribute(node, 'name'),
|
||||
this.getAttribute(node, 'data')
|
||||
]);
|
||||
return this.getInputs(node);
|
||||
})
|
||||
@@ -140,9 +137,9 @@ define([
|
||||
|
||||
// Remove nodes that already exist
|
||||
dataNodes = allDataNodes.filter(dataNode => {
|
||||
var hash = this.core.getAttribute(dataNode, 'data'),
|
||||
var hash = this.getAttribute(dataNode, 'data'),
|
||||
name = this.core.getOwnAttribute(node, 'saveName') ||
|
||||
this.core.getAttribute(dataNode, 'name');
|
||||
this.getAttribute(dataNode, 'name');
|
||||
|
||||
return !(currNameHashPairs
|
||||
.find(pair => pair[0] === name && pair[1] === hash));
|
||||
@@ -154,10 +151,10 @@ define([
|
||||
newName = this.core.getOwnAttribute(node, 'saveName');
|
||||
if (newName) {
|
||||
newNodes.forEach(node =>
|
||||
this.core.setAttribute(node, 'name', newName)
|
||||
this.setAttribute(node, 'name', newName)
|
||||
);
|
||||
}
|
||||
var hashes = dataNodes.map(n => this.core.getAttribute(n, 'data'));
|
||||
var hashes = dataNodes.map(n => this.getAttribute(n, 'data'));
|
||||
this.logger.info(`saving hashes: ${hashes.map(h => `"${h}"`)}`);
|
||||
} else if (allDataNodes.length === 0) {
|
||||
this.logger.warn('No data nodes found!');
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Audiowide';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Audiowide'), local('Audiowide-Regular'), url(https://fonts.gstatic.com/s/audiowide/v4/7pSgz2MbVvTCvvm7vukSHxJtnKITppOI_IvcXXDNrsc.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Audiowide';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Audiowide'), local('Audiowide-Regular'), url(https://fonts.gstatic.com/s/audiowide/v4/8XtYtNKEyyZh481XVWfVOltXRa8TVwTICgirnJhmVJw.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||
li.deepforge-logo {
|
||||
background-image: url(img/deepforge-logo.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
width: 100px;
|
||||
background-size: 95px;
|
||||
}
|
||||
|
||||
.deepforge-logo .item-label {
|
||||
font-family: 'Audiowide', cursive;
|
||||
li.deepforge-logo span {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
i.gme-icon {
|
||||
background-image: url(img/deepforge-icon.png);
|
||||
background-size: 15.20px 18px;
|
||||
}
|
||||
|
||||
.create-node text {
|
||||
|
||||
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 2.0 KiB |
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 3.3 KiB |
+60
-6
@@ -1,7 +1,13 @@
|
||||
/* globals define*/
|
||||
define([
|
||||
], function(
|
||||
) {
|
||||
(function(root, factory){
|
||||
if(typeof define === 'function' && define.amd) {
|
||||
define([], function(){
|
||||
return (root.utils = factory());
|
||||
});
|
||||
} else if(typeof module === 'object' && module.exports) {
|
||||
module.exports = (root.utils = factory());
|
||||
}
|
||||
}(this, function() {
|
||||
var isBoolean = txt => {
|
||||
return typeof txt === 'boolean' || (txt === 'false' || txt === 'true');
|
||||
};
|
||||
@@ -33,7 +39,55 @@ define([
|
||||
return schema;
|
||||
};
|
||||
|
||||
return {
|
||||
getSetterSchema: getSetterSchema
|
||||
var abbrWord = function(word) { // camelcase
|
||||
word = word.substring(0, 1).toUpperCase() + word.substring(1);
|
||||
return word.split(/[a-z]+/g).join('').toLowerCase();
|
||||
};
|
||||
});
|
||||
|
||||
var abbrPhrase = function(words) { // dashes, spaces, underscores, etc
|
||||
return words.map(word => word[0]).join('');
|
||||
};
|
||||
|
||||
var abbr = function(phrase) {
|
||||
var words = phrase.split(/[^a-zA-Z0-9]+/g);
|
||||
if (words.length === 1) {
|
||||
return abbrWord(phrase);
|
||||
} else {
|
||||
return abbrPhrase(words);
|
||||
}
|
||||
};
|
||||
|
||||
// Resolving stdout
|
||||
var resolveCarriageReturns = function(text) {
|
||||
// resolve \r
|
||||
var lines,
|
||||
chars,
|
||||
result,
|
||||
i = 0;
|
||||
|
||||
text = text.replace(/\u0000/g, '');
|
||||
lines = text.split('\n');
|
||||
for (var l = lines.length-1; l >= 0; l--) {
|
||||
i = 0;
|
||||
chars = lines[l].split('');
|
||||
result = [];
|
||||
|
||||
for (var c = 0; c < chars.length; c++) {
|
||||
if (chars[c] === '\r') {
|
||||
i = 0;
|
||||
}
|
||||
result[i] = chars[c];
|
||||
i++;
|
||||
}
|
||||
lines[l] = result.join('');
|
||||
}
|
||||
return lines;
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
getSetterSchema: getSetterSchema,
|
||||
resolveCarriageReturns: resolveCarriageReturns,
|
||||
abbr: abbr
|
||||
};
|
||||
}));
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/* globals define, WebGMEGlobal */
|
||||
// Mixin for executing jobs and pipelines
|
||||
define([
|
||||
'q',
|
||||
'executor/ExecutorClient',
|
||||
'panel/FloatingActionButton/styles/Materialize'
|
||||
], function(
|
||||
Q,
|
||||
ExecutorClient,
|
||||
Materialize
|
||||
) {
|
||||
|
||||
var Execute = function(client, logger) {
|
||||
this.client = this.client || client;
|
||||
this.logger = this.logger || logger;
|
||||
this._executor = new ExecutorClient({
|
||||
logger: this.logger.fork('ExecutorClient'),
|
||||
serverPort: WebGMEGlobal.gmeConfig.server.port,
|
||||
httpsecure: window.location.protocol === 'https:'
|
||||
});
|
||||
};
|
||||
|
||||
Execute.prototype.executeJob = function(node) {
|
||||
return this.runExecutionPlugin('ExecuteJob', {node: node});
|
||||
};
|
||||
|
||||
Execute.prototype.executePipeline = function(node) {
|
||||
return this.runExecutionPlugin('ExecutePipeline', {node: node});
|
||||
};
|
||||
|
||||
Execute.prototype.runExecutionPlugin = function(pluginId, opts) {
|
||||
var context = this.client.getCurrentPluginContext(pluginId),
|
||||
node = opts.node || this.client.getNode(this._currentNodeId),
|
||||
name = node.getAttribute('name'),
|
||||
method;
|
||||
|
||||
// Set the activeNode
|
||||
context.managerConfig.namespace = 'pipeline';
|
||||
context.managerConfig.activeNode = node.getId();
|
||||
method = opts.useSecondary ? 'runBrowserPlugin' : 'runServerPlugin';
|
||||
|
||||
if (method === 'runServerPlugin' &&
|
||||
this.client.getBranchStatus() !== this.client.CONSTANTS.BRANCH_STATUS.SYNC) {
|
||||
|
||||
Materialize.toast('Cannot execute operations when client is out-of-sync', 2000);
|
||||
return;
|
||||
}
|
||||
|
||||
this.client[method](pluginId, context, (err, result) => {
|
||||
var msg = err ? `${name} failed!` : `${name} executed successfully!`,
|
||||
duration = err ? 4000 : 2000;
|
||||
|
||||
// Check if it was canceled - if so, show that type of message
|
||||
if (result && result.messages.length) {
|
||||
msg = result.messages[0].message;
|
||||
duration = 4000;
|
||||
}
|
||||
|
||||
Materialize.toast(msg, duration);
|
||||
});
|
||||
};
|
||||
|
||||
Execute.prototype.isRunning = function(node) {
|
||||
var baseId,
|
||||
base,
|
||||
type;
|
||||
|
||||
node = node || this.client.getNode(this._currentNodeId);
|
||||
baseId = node.getBaseId();
|
||||
base = this.client.getNode(baseId);
|
||||
type = base.getAttribute('name');
|
||||
|
||||
if (type === 'Execution') {
|
||||
return node.getAttribute('status') === 'running';
|
||||
} else if (type === 'Job') {
|
||||
return this.isRunningJob(node);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Execute.prototype.isRunningJob = function(job) {
|
||||
var status = job.getAttribute('status');
|
||||
|
||||
return (status === 'running' || status === 'pending') &&
|
||||
job.getAttribute('secret') && job.getAttribute('jobId');
|
||||
};
|
||||
|
||||
Execute.prototype.silentStopJob = function(job) {
|
||||
var jobHash,
|
||||
secret;
|
||||
|
||||
job = job || this.client.getNode(this._currentNodeId);
|
||||
jobHash = job.getAttribute('jobId');
|
||||
secret = job.getAttribute('secret');
|
||||
if (!jobHash || !secret) {
|
||||
this.logger.error('Cannot stop job. Missing jobHash or secret');
|
||||
return;
|
||||
}
|
||||
|
||||
return this._executor.cancelJob(jobHash, secret)
|
||||
.then(() => this.logger.info(`${jobHash} has been cancelled!`))
|
||||
.fail(err => this.logger.error(`Job cancel failed: ${err}`));
|
||||
};
|
||||
|
||||
Execute.prototype.stopJob = function(job, silent) {
|
||||
var jobId;
|
||||
|
||||
job = job || this.client.getNode(this._currentNodeId);
|
||||
jobId = job.getId();
|
||||
|
||||
this.silentStopJob(job);
|
||||
|
||||
if (!silent) {
|
||||
this.client.startTransaction(`Stopping "${name}" job`);
|
||||
}
|
||||
|
||||
this.client.delAttributes(jobId, 'jobId');
|
||||
this.client.delAttributes(jobId, 'secret');
|
||||
this.client.setAttributes(jobId, 'status', 'canceled');
|
||||
|
||||
if (!silent) {
|
||||
this.client.completeTransaction();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Execute.prototype.loadChildren = function(id) {
|
||||
var deferred = Q.defer(),
|
||||
execNode = this.client.getNode(id || this._currentNodeId),
|
||||
jobIds = execNode.getChildrenIds(),
|
||||
jobsLoaded = !jobIds.length || this.client.getNode(jobIds[0]);
|
||||
|
||||
// May need to load the jobs...
|
||||
if (!jobsLoaded) {
|
||||
// Create a territory and load the nodes
|
||||
var territory = {},
|
||||
ui;
|
||||
|
||||
territory[id] = {children: 1};
|
||||
ui = this.client.addUI(this, () => {
|
||||
this.client.removeUI(ui);
|
||||
deferred.resolve();
|
||||
});
|
||||
this.client.updateTerritory(ui, territory);
|
||||
} else {
|
||||
deferred.resolve();
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
Execute.prototype.stopExecution = function(id, inTransaction) {
|
||||
var execNode = this.client.getNode(id || this._currentNodeId);
|
||||
|
||||
return this.loadChildren(id)
|
||||
.then(() => this._stopExecution(execNode, inTransaction));
|
||||
};
|
||||
|
||||
Execute.prototype.silentStopExecution = function(id) {
|
||||
var execNode = this.client.getNode(id || this._currentNodeId);
|
||||
|
||||
// Stop the execution w/o setting any attributes
|
||||
return this.loadChildren(id)
|
||||
.then(() => this._silentStopExecution(execNode));
|
||||
};
|
||||
|
||||
Execute.prototype._stopExecution = function(execNode, inTransaction) {
|
||||
var msg = `Canceling ${execNode.getAttribute('name')} execution`;
|
||||
|
||||
if (!inTransaction) {
|
||||
this.client.startTransaction(msg);
|
||||
}
|
||||
|
||||
this._silentStopExecution(execNode);
|
||||
this.client.setAttributes(execNode.getId(), 'status', 'canceled');
|
||||
|
||||
if (!inTransaction) {
|
||||
this.client.completeTransaction();
|
||||
}
|
||||
};
|
||||
|
||||
Execute.prototype._silentStopExecution = function(execNode) {
|
||||
var jobIds = execNode.getChildrenIds();
|
||||
|
||||
jobIds.map(id => this.client.getNode(id))
|
||||
.filter(job => this.isRunning(job)) // get running jobs
|
||||
.forEach(job => this.silentStopJob(job)); // stop them
|
||||
};
|
||||
|
||||
return Execute;
|
||||
});
|
||||
@@ -21,7 +21,7 @@ define([
|
||||
|
||||
RenameablePanel.OPTIONS = PanelBaseWithHeader.OPTIONS;
|
||||
RenameablePanel.prototype.initializeRenameable = function () {
|
||||
this.$panelHeaderTitle.on('dblclick', this.editTitle.bind(this));
|
||||
this.$panelHeaderTitle.on('click', this.editTitle.bind(this));
|
||||
};
|
||||
|
||||
RenameablePanel.prototype.currentNodeId = function () {
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
/*globals define, _*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
* @author brollb / https://github.com/brollb
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/Constants',
|
||||
'deepforge/Constants',
|
||||
'decorators/DcOpDecorator/EasyDAG/DcOpDecorator.EasyDAGWidget',
|
||||
'css!./ArtifactOpDecorator.EasyDAGWidget.css'
|
||||
], function (
|
||||
@@ -19,16 +15,17 @@ define([
|
||||
var ArtifactOpDecorator,
|
||||
DECORATOR_ID = 'ArtifactOpDecorator',
|
||||
CAST_OPTS = {
|
||||
ArtifactLoader: {
|
||||
ptr: 'artifact',
|
||||
metaTgt: false
|
||||
},
|
||||
ArtifactFinder: {
|
||||
ptr: 'type',
|
||||
metaTgt: true
|
||||
}
|
||||
};
|
||||
|
||||
CAST_OPTS[CONSTANTS.OP.INPUT] = {
|
||||
ptr: 'artifact',
|
||||
metaTgt: false
|
||||
};
|
||||
|
||||
// ArtifactOp nodes need to be able to...
|
||||
// - dynamically change their outputs (downcast)
|
||||
ArtifactOpDecorator = function (options) {
|
||||
@@ -74,7 +71,7 @@ define([
|
||||
};
|
||||
|
||||
ArtifactOpDecorator.prototype.getDisplayName = function() {
|
||||
var ptrName = this._node.baseName === 'ArtifactLoader' ? 'artifact' : 'type',
|
||||
var ptrName = this._node.baseName === CONSTANTS.OP.INPUT ? 'artifact' : 'type',
|
||||
id = this._node.pointers[ptrName],
|
||||
name = this.nameFor[id] || this._node.name;
|
||||
return name;
|
||||
@@ -91,7 +88,7 @@ define([
|
||||
ArtifactOpDecorator.prototype.updateTargetName = function(id, name) {
|
||||
DecoratorBase.prototype.updateTargetName.apply(this, arguments);
|
||||
// Update name
|
||||
var ptrName = this._node.baseName === 'ArtifactLoader' ? 'artifact' : 'type';
|
||||
var ptrName = this._node.baseName === CONSTANTS.OP.INPUT ? 'artifact' : 'type';
|
||||
if (this._node.pointers[ptrName] === id) {
|
||||
this._name = name;
|
||||
this.onResize();
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*globals define*/
|
||||
define([
|
||||
'decorators/EllipseDecorator/EasyDAG/AttributeField'
|
||||
], function(
|
||||
BaseAttributeField
|
||||
) {
|
||||
var AttributeField = function() {
|
||||
BaseAttributeField.apply(this, arguments);
|
||||
};
|
||||
|
||||
AttributeField.prototype = Object.create(BaseAttributeField.prototype);
|
||||
|
||||
AttributeField.prototype.onClick = function() {
|
||||
};
|
||||
|
||||
return AttributeField;
|
||||
});
|
||||
@@ -2,10 +2,16 @@
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
define([
|
||||
'deepforge/Constants',
|
||||
'decorators/EllipseDecorator/EasyDAG/EllipseDecorator.EasyDAGWidget',
|
||||
'./PointerField.RO',
|
||||
'./AttributeField.RO',
|
||||
'css!./JobDecorator.EasyDAGWidget.css'
|
||||
], function (
|
||||
EllipseDecorator
|
||||
CONSTANTS,
|
||||
EllipseDecorator,
|
||||
PointerField,
|
||||
AttributeField
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
@@ -42,18 +48,46 @@ define([
|
||||
_.extend(JobDecorator.prototype, EllipseDecorator.prototype);
|
||||
|
||||
JobDecorator.prototype.DECORATOR_ID = DECORATOR_ID;
|
||||
JobDecorator.prototype.AttributeField = AttributeField;
|
||||
JobDecorator.prototype.PointerField = PointerField;
|
||||
|
||||
JobDecorator.prototype.isInputOperation = function() {
|
||||
return this._node.name === CONSTANTS.OP.INPUT;
|
||||
};
|
||||
|
||||
JobDecorator.prototype.getDisplayName = function() {
|
||||
if (this.isInputOperation()) {
|
||||
var id = this._node.pointers.artifact;
|
||||
|
||||
// Try to look up the pointer name
|
||||
return this.nameFor[id] || this._node.name;
|
||||
}
|
||||
return this._node.name;
|
||||
};
|
||||
|
||||
JobDecorator.prototype.setAttributes = function() {
|
||||
EllipseDecorator.prototype.setAttributes.call(this);
|
||||
var attrs = this._node.attributes,
|
||||
status = attrs.status && attrs.status.value;
|
||||
status = attrs.status && attrs.status.value,
|
||||
opAttrs = Object.keys(this._node.opAttributes);
|
||||
|
||||
// Update the color based on the 'status' attr
|
||||
this.color = COLORS[status] || COLORS.fail;
|
||||
|
||||
// Set _attributes from opAttributes
|
||||
for (var i = opAttrs.length; i--;) {
|
||||
this._attributes[opAttrs[i]] = this._node.opAttributes[opAttrs[i]];
|
||||
}
|
||||
};
|
||||
|
||||
JobDecorator.prototype.updateTargetName = function() {
|
||||
EllipseDecorator.prototype.updateTargetName.apply(this, arguments);
|
||||
var name = this.getDisplayName();
|
||||
|
||||
if (name !== this.name) {
|
||||
this.name = name;
|
||||
this.onResize();
|
||||
}
|
||||
};
|
||||
|
||||
return JobDecorator;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*globals define*/
|
||||
define([
|
||||
'decorators/EllipseDecorator/EasyDAG/PointerField'
|
||||
], function(
|
||||
BasePointerField
|
||||
) {
|
||||
var PointerField = function() {
|
||||
BasePointerField.apply(this, arguments);
|
||||
};
|
||||
|
||||
PointerField.prototype = Object.create(BasePointerField.prototype);
|
||||
|
||||
PointerField.prototype.onClick = function() {
|
||||
};
|
||||
|
||||
// Remove the delete icon and adjust the text location
|
||||
PointerField.prototype.hasIcon = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
return PointerField;
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
/*globals define, $,_*/
|
||||
/*globals define, _*/
|
||||
/*jshint browser: true, camelcase: false*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/*globals define*/
|
||||
/*jshint node:true, browser:true*/
|
||||
|
||||
define([
|
||||
'text!./metadata.json',
|
||||
'module',
|
||||
'path',
|
||||
'fs',
|
||||
'q',
|
||||
'plugin/PluginBase'
|
||||
], function (
|
||||
pluginMetadata,
|
||||
module,
|
||||
path,
|
||||
fs,
|
||||
Q,
|
||||
PluginBase
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
pluginMetadata = JSON.parse(pluginMetadata);
|
||||
var __dirname = path.dirname(module.uri),
|
||||
SEEDS_DIR = path.join(__dirname, '..', '..', 'seeds');
|
||||
|
||||
/**
|
||||
* Initializes a new instance of CheckLibraries.
|
||||
* @class
|
||||
* @augments {PluginBase}
|
||||
* @classdesc This class represents the plugin CheckLibraries.
|
||||
* @constructor
|
||||
*/
|
||||
var CheckLibraries = function () {
|
||||
// Call base class' constructor.
|
||||
PluginBase.call(this);
|
||||
this.pluginMetadata = pluginMetadata;
|
||||
this.libraries = {};
|
||||
};
|
||||
|
||||
/**
|
||||
* 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}
|
||||
*/
|
||||
CheckLibraries.metadata = pluginMetadata;
|
||||
|
||||
// Prototypical inheritance from PluginBase.
|
||||
CheckLibraries.prototype = Object.create(PluginBase.prototype);
|
||||
CheckLibraries.prototype.constructor = CheckLibraries;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
CheckLibraries.prototype.main = function (callback) {
|
||||
var tuples;
|
||||
|
||||
return this.getAllLibraries()
|
||||
.then(libs => {
|
||||
tuples = libs.map(lib => { // map to [name, version, dir]
|
||||
var version,
|
||||
hash,
|
||||
data,
|
||||
versionPath = this.getSeedVersionPath(lib);
|
||||
|
||||
try {
|
||||
this.logger.info(`Checking for version info at ${versionPath}`);
|
||||
version = fs.readFileSync(versionPath, 'utf8');
|
||||
this.logger.debug(`${lib} version is ${version}`);
|
||||
data = fs.readFileSync(this.getSeedHashPath(lib), 'utf8').split(' ');
|
||||
if (data[1] === version) {
|
||||
hash = data[0];
|
||||
this.logger.debug(`${lib} hash is ${hash}`);
|
||||
}
|
||||
} catch (e) {
|
||||
if (!version) {
|
||||
this.logger.warn(`Could not find library version for ${lib}`);
|
||||
} else {
|
||||
this.logger.warn(`Could not find library hash for ${lib}`);
|
||||
}
|
||||
}
|
||||
|
||||
return [lib, version, hash];
|
||||
})
|
||||
.filter(tuple => {
|
||||
var projVersion = this.getLoadedVersion(tuple[0]),
|
||||
latest = tuple[1].replace(/\s+/g, '');
|
||||
|
||||
this.logger.info(`${tuple[0]} version info:\n${projVersion} ` +
|
||||
`(project)\n${latest} (latest)`);
|
||||
return latest !== projVersion;
|
||||
});
|
||||
|
||||
return Q.all(tuples.map(tuple => this.uploadSeed.apply(this, tuple)));
|
||||
})
|
||||
.then(hashes => {
|
||||
var name;
|
||||
|
||||
for (var i = hashes.length; i--;) {
|
||||
name = tuples[i][0];
|
||||
this.createMessage(this.libraries[name], `${name} ${hashes[i]}`);
|
||||
}
|
||||
|
||||
this.logger.info(`Found ${hashes.length} out of date libraries`);
|
||||
this.result.setSuccess(true);
|
||||
callback(null, this.result);
|
||||
})
|
||||
.fail(err => {
|
||||
this.logger.error(`Could not check the libraries: ${err}`);
|
||||
callback(err, this.result);
|
||||
});
|
||||
};
|
||||
|
||||
CheckLibraries.prototype.getSeedDir = function (name) {
|
||||
return path.join(SEEDS_DIR, name);
|
||||
};
|
||||
|
||||
CheckLibraries.prototype.getSeedDataPath = function (name) {
|
||||
return path.join(this.getSeedDir(name), name + '.webgmex');
|
||||
};
|
||||
|
||||
CheckLibraries.prototype.getSeedHashPath = function (name) {
|
||||
return path.join(this.getSeedDir(name), 'hash.txt');
|
||||
};
|
||||
|
||||
CheckLibraries.prototype.getSeedVersionPath = function (name) {
|
||||
return path.join(this.getSeedDir(name), 'version.txt');
|
||||
};
|
||||
|
||||
CheckLibraries.prototype.uploadSeed = function (name, version, hash) {
|
||||
if (!hash) { // Upload the seed
|
||||
// Get the data
|
||||
return Q.nfcall(fs.readFile, this.getSeedDataPath(name))
|
||||
.then(data => {
|
||||
this.logger.info(`Uploading new version of ${name} (${version})`);
|
||||
return this.blobClient.putFile(`${name}.webgmex`, data);
|
||||
})
|
||||
.then(newHash => { // Store the new hash
|
||||
this.logger.info(`Upload of ${name} finished!`);
|
||||
hash = newHash;
|
||||
return Q.nfcall(
|
||||
fs.writeFile,
|
||||
this.getSeedHashPath(name),
|
||||
`${hash} ${version}`
|
||||
);
|
||||
}).then(() => hash);
|
||||
}
|
||||
return hash;
|
||||
};
|
||||
|
||||
CheckLibraries.prototype.getAllLibraries = function () {
|
||||
var name,
|
||||
names = [];
|
||||
|
||||
return this.core.loadChildren(this.rootNode)
|
||||
.then(children => {
|
||||
for (var i = children.length; i--;) {
|
||||
if (this.core.isLibraryRoot(children[i])) {
|
||||
name = this.core.getAttribute(children[i], 'name');
|
||||
this.libraries[name] = children[i];
|
||||
names.push(name);
|
||||
}
|
||||
}
|
||||
if (names.length) {
|
||||
this.logger.debug(`Found libraries: ${names.join(', ')}`);
|
||||
} else {
|
||||
this.logger.debug('Found no libraries!');
|
||||
}
|
||||
return names;
|
||||
});
|
||||
};
|
||||
|
||||
CheckLibraries.prototype.getLoadedVersion = function (libName) {
|
||||
var node = this.libraries[libName],
|
||||
version = this.core.getAttribute(node, 'version'); // using library root hash
|
||||
|
||||
return version;
|
||||
};
|
||||
|
||||
return CheckLibraries;
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"id": "CheckLibraries",
|
||||
"name": "CheckLibraries",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"icon": {
|
||||
"class": "glyphicon glyphicon-cog",
|
||||
"src": ""
|
||||
},
|
||||
"disableServerSideExecution": false,
|
||||
"disableBrowserSideExecution": true,
|
||||
"writeAccessRequired": false,
|
||||
"configStructure": []
|
||||
}
|
||||
@@ -88,11 +88,9 @@ define([
|
||||
// Given a pipeline, copy all the operations to a custom job
|
||||
// - Copy the operations
|
||||
// - Wrap the operations in "Job" boxes which contain running info
|
||||
// - eg,
|
||||
// - 'debug' the given run (download all execution files)
|
||||
// - 'console' show console output (future feature)
|
||||
// - Update the references
|
||||
var tgtNode,
|
||||
execName,
|
||||
copies,
|
||||
opTuples, // [[op, index], [op, index], ...]
|
||||
dataMapping = {};
|
||||
@@ -107,17 +105,19 @@ define([
|
||||
base: this.META.Execution,
|
||||
parent: execDir
|
||||
});
|
||||
this.logger.debug(`New execution created w/ id: ${this.core.getPath(tgtNode)}`);
|
||||
|
||||
// Get a unique name
|
||||
this.logger.debug(`About to get a unique name starting w/ ${basename}`);
|
||||
return this.getUniqueExecName(basename);
|
||||
})
|
||||
.then(execName => {
|
||||
.then(_execName => {
|
||||
var isSnapshot = !this.getCurrentConfig().debug,
|
||||
originName = this.core.getAttribute(this.activeNode, 'name'),
|
||||
oId = this.core.getPath(this.activeNode),
|
||||
tgtId = this.core.getPath(tgtNode);
|
||||
|
||||
execName = _execName;
|
||||
this.logger.debug(`Configuring execution attributes (${execName})`);
|
||||
|
||||
// Set all the metadata for the new execution
|
||||
@@ -131,15 +131,9 @@ define([
|
||||
this.core.addMember(this.activeNode, 'executions', tgtNode);
|
||||
|
||||
this.logger.debug(`Creating tag "${execName}"`);
|
||||
return this.project.createTag(
|
||||
execName,
|
||||
this.currentHash
|
||||
);
|
||||
})
|
||||
.then(() => this.core.loadChildren(node))
|
||||
.then(children => {
|
||||
var execName = this.core.getAttribute(tgtNode, 'name');
|
||||
|
||||
if (!children.length) {
|
||||
this.logger.warn('No children in pipeline. Will proceed anyway');
|
||||
}
|
||||
@@ -170,6 +164,7 @@ define([
|
||||
this.logger.debug('Finished! Saving...');
|
||||
return this.save(`Created execution from ${name}`);
|
||||
})
|
||||
.then(() => this.project.createTag(execName, this.currentHash))
|
||||
.then(() => tgtNode); // return tgtNode
|
||||
};
|
||||
|
||||
@@ -192,6 +187,7 @@ define([
|
||||
})
|
||||
.then(execDir => {
|
||||
var cIds = this.core.getChildrenPaths(execDir);
|
||||
this.logger.debug(`Current executions are ${cIds.join(', ')}`);
|
||||
return Q.all(cIds.map(id => this.core.loadByPath(this.rootNode, id)));
|
||||
})
|
||||
.then(execs => {
|
||||
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -1,6 +1,13 @@
|
||||
-- Instantiate the deepforge object
|
||||
deepforge = {}
|
||||
|
||||
function deepforge.initialize()
|
||||
require 'nn'
|
||||
require 'rnn'
|
||||
require './classes/init'
|
||||
require './custom-layers'
|
||||
end
|
||||
|
||||
function deepforge.id()
|
||||
if __deepforge_id == nil then
|
||||
__deepforge_id = 0
|
||||
@@ -16,7 +23,7 @@ function deepforge._cmd(...)
|
||||
for i=1,n do
|
||||
cmd = cmd .. ' ' .. tostring(arg[i])
|
||||
end
|
||||
print(cmd)
|
||||
print(cmd .. ' ') -- guarantee ends w/ space
|
||||
end
|
||||
|
||||
-- Graph support
|
||||
@@ -46,7 +53,7 @@ function Graph:line(name, opts)
|
||||
end
|
||||
|
||||
-- Image support
|
||||
function deepforge.image(name, tensor)
|
||||
local function saveImage(name, tensor)
|
||||
require 'image'
|
||||
require 'paths'
|
||||
|
||||
@@ -59,7 +66,32 @@ function deepforge.image(name, tensor)
|
||||
end
|
||||
|
||||
image.save(path, tensor)
|
||||
deepforge._cmd("<%= IMAGE %>", name)
|
||||
end
|
||||
|
||||
function deepforge.image(name, tensor)
|
||||
saveImage(name, tensor)
|
||||
deepforge._cmd("<%= IMAGE.BASIC %>", deepforge.id(), name)
|
||||
end
|
||||
|
||||
Image = torch.class('deepforge.Image')
|
||||
function Image:__init(name, tensor)
|
||||
self.id = deepforge.id()
|
||||
self.name = name
|
||||
|
||||
if tensor ~= nil then
|
||||
saveImage(name, tensor)
|
||||
deepforge._cmd('<%= IMAGE.CREATE %>', self.id, self.name)
|
||||
end
|
||||
end
|
||||
|
||||
function Image:update(tensor)
|
||||
saveImage(self.name, tensor)
|
||||
deepforge._cmd('<%= IMAGE.UPDATE %>', self.id, self.name)
|
||||
end
|
||||
|
||||
function Image:title(name)
|
||||
self.name = name
|
||||
deepforge._cmd('<%= IMAGE.NAME %>', self.id, self.name)
|
||||
end
|
||||
|
||||
return deepforge
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
-- load custom layers
|
||||
require './custom-layers'
|
||||
|
||||
-- load custom class definitions
|
||||
require './classes'
|
||||
-- load custom layers and classes
|
||||
deepforge.initialize()
|
||||
|
||||
-- input data<% inputs.forEach(function(pair) { var input = pair[0], isNil = pair[1];%>
|
||||
<%= isNil ? 'local ' : ''%><%= input %> = <% if (isNil) { %>nil<% } else { %>require './inputs/<%= input %>'<%}}); %>
|
||||
local <%= input %> = <% if (isNil) { %>nil<% } else { %>require './inputs/<%= input %>'<%}}); %>
|
||||
|
||||
-- load references<% pointers.forEach(function(pair) { var pointer = pair[0], isNil = pair[1];%>
|
||||
<%= isNil ? 'local ' : ''%><%= pointer %> = <% if (isNil) { %>nil<% } else { %>require './pointers/<%= pointer %>'<%}}); %>
|
||||
attributes = require './attributes'
|
||||
local <%= pointer %> = <% if (isNil) { %>nil<% } else { %>require './pointers/<%= pointer %>'<%}}); %>
|
||||
local attributes = require './attributes'
|
||||
|
||||
-- main operation code for <%= name %>
|
||||
<%= code %>
|
||||
|
||||
@@ -12,7 +12,7 @@ var spawn = require('child_process').spawn,
|
||||
|
||||
// Get the BlobClient...
|
||||
var COMMAND_PREFIX = '<%= START_CMD %>',
|
||||
IMAGE = '<%= IMAGE %>',
|
||||
IMAGE = '<%= IMAGE.PREFIX %>',
|
||||
requirejs = require('webgme').requirejs,
|
||||
remainingImageCount = 0,
|
||||
exitCode = null;
|
||||
@@ -80,7 +80,7 @@ requirejs([
|
||||
|
||||
var uploadImage = function(line) {
|
||||
var args = line.split(/\s+/),
|
||||
name = args.slice(2).join(' ').replace(/\s+$/, ''),
|
||||
name = args.slice(3).join(' ').replace(/\s+$/, ''),
|
||||
filename = 'metadata/' + name + '.png';
|
||||
|
||||
// Upload the image from metadata/
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
define([
|
||||
'plugin/CreateExecution/CreateExecution/CreateExecution',
|
||||
'plugin/ExecuteJob/ExecuteJob/ExecuteJob',
|
||||
'deepforge/JobLogsClient',
|
||||
'common/storage/constants',
|
||||
'common/core/constants',
|
||||
'q',
|
||||
@@ -12,6 +13,7 @@ define([
|
||||
], function (
|
||||
CreateExecution,
|
||||
ExecuteJob,
|
||||
JobLogsClient,
|
||||
STORAGE_CONSTANTS,
|
||||
CONSTANTS,
|
||||
Q,
|
||||
@@ -34,6 +36,11 @@ define([
|
||||
this.pluginMetadata = pluginMetadata;
|
||||
|
||||
this._currentSave = Q();
|
||||
this.changes = {};
|
||||
this.currentChanges = {}; // read-only changes being applied
|
||||
this.creations = {};
|
||||
this.deletions = [];
|
||||
this.createIdToMetadataId = {};
|
||||
this.initRun();
|
||||
};
|
||||
|
||||
@@ -94,17 +101,14 @@ define([
|
||||
* @param {function(string, plugin.PluginResult)} callback - the result callback
|
||||
*/
|
||||
ExecutePipeline.prototype.main = function (callback) {
|
||||
// This will probably need to execute the operations, too, because the
|
||||
// inputs for the next operation cannot be created until the inputs have
|
||||
// been generated
|
||||
var startPromise;
|
||||
|
||||
this.initRun();
|
||||
var startPromise;
|
||||
if (this.core.isTypeOf(this.activeNode, this.META.Pipeline)) {
|
||||
// If starting with a pipeline, we will create an Execution first
|
||||
startPromise = this.createExecution(this.activeNode)
|
||||
.then(execNode => {
|
||||
this.logger.debug(`Finished creating execution "${this.core.getAttribute(execNode, 'name')}"`);
|
||||
this.logger.debug(`Finished creating execution "${this.getAttribute(execNode, 'name')}"`);
|
||||
this.activeNode = execNode;
|
||||
});
|
||||
} else if (this.core.isTypeOf(this.activeNode, this.META.Execution)) {
|
||||
@@ -114,6 +118,13 @@ define([
|
||||
return callback('Current node is not a Pipeline or Execution!', this.result);
|
||||
}
|
||||
|
||||
// Get the gmeConfig...
|
||||
this.logManager = new JobLogsClient({
|
||||
logger: this.logger,
|
||||
port: this.gmeConfig.server.port,
|
||||
branchName: this.branchName,
|
||||
projectId: this.projectId
|
||||
});
|
||||
this._callback = callback;
|
||||
this.currentForkName = null;
|
||||
|
||||
@@ -123,7 +134,7 @@ define([
|
||||
var children = subtree
|
||||
.filter(n => this.core.getParent(n) === this.activeNode);
|
||||
|
||||
this.pipelineName = this.core.getAttribute(this.activeNode, 'name');
|
||||
this.pipelineName = this.getAttribute(this.activeNode, 'name');
|
||||
this.logger.debug(`Loaded subtree of ${this.pipelineName}. About to build cache`);
|
||||
this.buildCache(subtree);
|
||||
this.logger.debug('Parsing execution for job inter-dependencies');
|
||||
@@ -142,19 +153,46 @@ define([
|
||||
// before continuing
|
||||
this._currentSave = this._currentSave
|
||||
.then(() => this.updateForkName(this.pipelineName))
|
||||
.then(() => this.applyModelChanges())
|
||||
.then(() => CreateExecution.prototype.save.call(this, msg))
|
||||
.then(result => {
|
||||
var msg;
|
||||
if (result.status === STORAGE_CONSTANTS.FORKED) {
|
||||
this.currentForkName = result.forkName;
|
||||
this.logManager.fork(result.forkName);
|
||||
msg = `"${this.pipelineName}" execution has forked to "${result.forkName}"`;
|
||||
this.sendNotification(msg);
|
||||
} else if (result.status === STORAGE_CONSTANTS.MERGED) {
|
||||
this.logger.debug('Merged changes. About to update plugin nodes');
|
||||
return this.updateNodes();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return this._currentSave;
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.updateNodes = function (hash) {
|
||||
var result = ExecuteJob.prototype.updateNodes.call(this, hash);
|
||||
return result.then(() => this.updateCache());
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.updateCache = function () {
|
||||
var nodeIds = Object.keys(this.nodes),
|
||||
nodes = nodeIds.map(id => this.core.loadByPath(this.rootNode, id));
|
||||
|
||||
this.logger.debug(`updating node cache (${nodeIds.length} nodes)`);
|
||||
return Q.all(nodes).then(nodes => {
|
||||
for (var i = nodeIds.length; i--;) {
|
||||
this.nodes[nodeIds[i]] = nodes[i];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.isExecutionCanceled = function () {
|
||||
return this.getAttribute(this.activeNode, 'status') === 'canceled';
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.isInputData = function (node) {
|
||||
var prnt = this.core.getParent(node);
|
||||
return this.core.isTypeOf(prnt, this.META.Inputs);
|
||||
@@ -174,13 +212,15 @@ define([
|
||||
nodes.filter(node => this.core.isTypeOf(node, this.META.Job))
|
||||
.forEach(node => {
|
||||
this.recordOldMetadata(node);
|
||||
this.core.setAttribute(node, 'status', 'pending');
|
||||
this.setAttribute(node, 'status', 'pending');
|
||||
});
|
||||
|
||||
// Set the status of the execution to 'running'
|
||||
this.core.setAttribute(this.activeNode, 'status', 'running');
|
||||
this.setAttribute(this.activeNode, 'status', 'running');
|
||||
this.logger.info('Setting all jobs status to "pending"');
|
||||
this.logger.debug(`Making a commit from ${this.currentHash}`);
|
||||
this.setAttribute(this.activeNode, 'startTime', Date.now());
|
||||
this.core.delAttribute(this.activeNode, 'endTime');
|
||||
return this.save(`Initializing ${this.pipelineName} for execution`);
|
||||
};
|
||||
|
||||
@@ -271,24 +311,24 @@ define([
|
||||
ExecutePipeline.prototype.onOperationFail = function(node, err) {
|
||||
var job = this.core.getParent(node),
|
||||
id = this.core.getPath(node),
|
||||
name = this.core.getAttribute(node, 'name');
|
||||
name = this.getAttribute(node, 'name');
|
||||
|
||||
this.logger.debug(`Operation ${name} (${id}) failed: ${err}`);
|
||||
this.core.setAttribute(job, 'status', 'fail');
|
||||
this.setAttribute(job, 'status', 'fail');
|
||||
this.clearOldMetadata(job);
|
||||
this.onPipelineComplete(err);
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.onOperationCanceled = function(op) {
|
||||
var job = this.core.getParent(op);
|
||||
this.core.setAttribute(job, 'status', 'canceled');
|
||||
this.setAttribute(job, 'status', 'canceled');
|
||||
this.runningJobs--;
|
||||
this.logger.debug(`${this.core.getAttribute(job, 'name')} has been canceled`);
|
||||
this.logger.debug(`${this.getAttribute(job, 'name')} has been canceled`);
|
||||
this.onPipelineComplete();
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.onPipelineComplete = function(err) {
|
||||
var name = this.core.getAttribute(this.activeNode, 'name'),
|
||||
var name = this.getAttribute(this.activeNode, 'name'),
|
||||
msg = `"${this.pipelineName}" `;
|
||||
|
||||
if (err) {
|
||||
@@ -318,18 +358,56 @@ define([
|
||||
msg += 'finished!';
|
||||
}
|
||||
|
||||
this.logger.debug(`Pipeline "${name}" complete!`);
|
||||
this.core.setAttribute(this.activeNode, 'status',
|
||||
(this.pipelineError ? 'failed' : (this.canceled ? 'canceled' : 'success')));
|
||||
this.isDeleted().then(isDeleted => {
|
||||
if (!isDeleted) {
|
||||
|
||||
this._finished = true;
|
||||
this.resultMsg(msg);
|
||||
this.save('Pipeline execution finished')
|
||||
.then(() => {
|
||||
this.logger.debug(`Pipeline "${name}" complete!`);
|
||||
this.setAttribute(this.activeNode, 'endTime', Date.now());
|
||||
this.setAttribute(this.activeNode, 'status',
|
||||
(this.pipelineError ? 'failed' :
|
||||
(this.canceled ? 'canceled' : 'success')
|
||||
)
|
||||
);
|
||||
|
||||
this._finished = true;
|
||||
this.resultMsg(msg);
|
||||
this.save('Pipeline execution finished')
|
||||
.then(() => {
|
||||
this.result.setSuccess(!this.pipelineError);
|
||||
this._callback(this.pipelineError || null, this.result);
|
||||
})
|
||||
.fail(e => this.logger.error(e));
|
||||
} else { // deleted!
|
||||
this.logger.debug('Execution has been deleted!');
|
||||
this.result.setSuccess(!this.pipelineError);
|
||||
this._callback(this.pipelineError || null, this.result);
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.isDeleted = function () {
|
||||
var activeId = this.core.getPath(this.activeNode);
|
||||
|
||||
// Check if the current execution has been deleted
|
||||
return this.project.getBranchHash(this.branchName)
|
||||
.then(hash => this.updateNodes(hash))
|
||||
.then(() => this.core.loadByPath(this.rootNode, activeId))
|
||||
.then(node => {
|
||||
var deleted = node === null,
|
||||
msg = `Verified that execution is ${deleted ? '' : 'not '}deleted`;
|
||||
|
||||
this.logger.debug(msg);
|
||||
return deleted;
|
||||
})
|
||||
.fail(e => this.logger.error(e));
|
||||
.fail(err => this.logger.error(err));
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.onPipelineDeleted = function () {
|
||||
var msg = `${this.pipelineName} has been deleted`;
|
||||
this.resultMsg(msg);
|
||||
this.result.setSuccess(true);
|
||||
this._callback(null, this.result);
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.executeReadyOperations = function () {
|
||||
@@ -362,7 +440,7 @@ define([
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.onOperationComplete = function (opNode) {
|
||||
var name = this.core.getAttribute(opNode, 'name'),
|
||||
var name = this.getAttribute(opNode, 'name'),
|
||||
nextPortIds = this.getOperationOutputIds(opNode),
|
||||
jNode = this.core.getParent(opNode),
|
||||
resultPorts,
|
||||
@@ -372,7 +450,7 @@ define([
|
||||
// Set the operation to 'success'!
|
||||
this.clearOldMetadata(jNode);
|
||||
this.runningJobs--;
|
||||
this.core.setAttribute(jNode, 'status', 'success');
|
||||
this.setAttribute(jNode, 'status', 'success');
|
||||
this.logger.info(`Setting ${jobId} status to "success"`);
|
||||
this.logger.info(`There are now ${this.runningJobs} running jobs`);
|
||||
this.logger.debug(`Making a commit from ${this.currentHash}`);
|
||||
@@ -391,11 +469,11 @@ define([
|
||||
.forEach(pair => { // [ resultPort, nextPort ]
|
||||
var result = pair[0],
|
||||
next = pair[1],
|
||||
hash = this.core.getAttribute(result, 'data');
|
||||
hash = this.getAttribute(result, 'data');
|
||||
|
||||
this.logger.info(`forwarding data (${hash}) from ${this.core.getPath(result)} ` +
|
||||
`to ${this.core.getPath(next)}`);
|
||||
this.core.setAttribute(next, 'data', hash);
|
||||
this.setAttribute(next, 'data', hash);
|
||||
this.logger.info(`Setting ${jobId} data to ${hash}`);
|
||||
});
|
||||
|
||||
|
||||
@@ -5,12 +5,14 @@ define([
|
||||
'SimpleNodes/SimpleNodes',
|
||||
'SimpleNodes/Constants',
|
||||
'deepforge/layer-args',
|
||||
'deepforge/utils',
|
||||
'underscore',
|
||||
'text!./metadata.json'
|
||||
], function (
|
||||
PluginBase,
|
||||
Constants,
|
||||
createLayerDict,
|
||||
utils,
|
||||
_,
|
||||
metadata
|
||||
) {
|
||||
@@ -36,11 +38,15 @@ define([
|
||||
GenerateArchitecture.prototype = Object.create(PluginBase.prototype);
|
||||
GenerateArchitecture.prototype.constructor = GenerateArchitecture;
|
||||
|
||||
GenerateArchitecture.prototype.getTemplateSettings = function () {
|
||||
return null;
|
||||
};
|
||||
|
||||
GenerateArchitecture.prototype.main = function () {
|
||||
this.addCustomLayersToMeta();
|
||||
this.LayerDict = createLayerDict(this.core, this.META);
|
||||
this.uniqueId = 2;
|
||||
this.varnames = {};
|
||||
this.varnames = {net: true};
|
||||
return PluginBase.prototype.main.apply(this, arguments);
|
||||
};
|
||||
|
||||
@@ -208,18 +214,13 @@ define([
|
||||
};
|
||||
};
|
||||
|
||||
GenerateArchitecture.abbr = function (word) {
|
||||
word = word.substring(0, 1).toUpperCase() + word.substring(1);
|
||||
return word.split(/[a-z]+/g).join('').toLowerCase();
|
||||
};
|
||||
|
||||
GenerateArchitecture.prototype.getValue = function (arg, layer) {
|
||||
var content = layer[arg];
|
||||
|
||||
if (typeof content === 'object') { // layer as arg
|
||||
if (content[Constants.CHILDREN].length) {
|
||||
// Generate the code for the children of layer[arg]
|
||||
var name = this.getVarName(GenerateArchitecture.abbr(arg)),
|
||||
var name = this.getVarName(utils.abbr(arg)),
|
||||
layers;
|
||||
|
||||
this.logger.debug(`Adding layer arg for ${arg} (${layer.name})`);
|
||||
@@ -246,17 +247,27 @@ define([
|
||||
base = layer[Constants.BASE],
|
||||
desc,
|
||||
fn,
|
||||
layerCode;
|
||||
layerCode,
|
||||
args,
|
||||
i;
|
||||
|
||||
this.logger.debug(`Creating arg string for ${layer.name}`);
|
||||
layerCode = '(' + this.LayerDict[layer.name].args
|
||||
.map(arg => this.getValue(arg.name, layer))
|
||||
.filter(GenerateArchitecture.isSet)
|
||||
args = this.LayerDict[layer.name].args
|
||||
.map(arg => this.getValue(arg.name, layer));
|
||||
|
||||
for (i = args.length; i--;) {
|
||||
if (GenerateArchitecture.isSet(args[i])) {
|
||||
break;
|
||||
}
|
||||
args.pop();
|
||||
}
|
||||
|
||||
layerCode = '(' + args.map(arg => GenerateArchitecture.isSet(arg) ? arg : 'nil')
|
||||
.join(', ') + ')';
|
||||
|
||||
// Add any setters
|
||||
// For each setter, check if it has been changed (and needs to be set)
|
||||
for (var i = setterNames.length; i--;) {
|
||||
for (i = setterNames.length; i--;) {
|
||||
desc = setters[setterNames[i]];
|
||||
if (desc.setterType === 'const') {
|
||||
// if the value is not the default, add the given fn
|
||||
|
||||
@@ -49,6 +49,8 @@ define([
|
||||
return callback('Torch code not provided.', this.result);
|
||||
}
|
||||
|
||||
this.addCustomLayersToMeta();
|
||||
|
||||
this.blobClient.getMetadata(srcHash)
|
||||
.then(mdata => { // Create the new model
|
||||
// If the current node is an architecture, assume we are just extending it
|
||||
@@ -90,6 +92,22 @@ define([
|
||||
);
|
||||
};
|
||||
|
||||
ImportTorch.prototype.addCustomLayersToMeta = function () {
|
||||
// Add custom layers to the metamodel
|
||||
var metanodes = this.core.getAllMetaNodes(this.rootNode),
|
||||
name;
|
||||
|
||||
Object.keys(metanodes).map(id => metanodes[id])
|
||||
.filter(node => this.core.isTypeOf(node, this.META.Layer))
|
||||
.forEach(layer => {
|
||||
name = this.core.getAttribute(layer, 'name');
|
||||
if (!this.META[name]) {
|
||||
this.logger.debug(`Adding ${name} to the meta`);
|
||||
this.META[name] = layer;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Create the 'nn' shim and add it to the global context
|
||||
ImportTorch.prototype.loadNNMock = function () {
|
||||
// This needs a refactor...
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*globals define*/
|
||||
/*jshint node:true, browser:true*/
|
||||
|
||||
define([
|
||||
'text!./metadata.json',
|
||||
'child_process',
|
||||
'path',
|
||||
'q',
|
||||
'fs',
|
||||
'module',
|
||||
'plugin/PluginBase'
|
||||
], function (
|
||||
pluginMetadata,
|
||||
childProcess,
|
||||
path,
|
||||
Q,
|
||||
fs,
|
||||
module,
|
||||
PluginBase
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
pluginMetadata = JSON.parse(pluginMetadata);
|
||||
var SEEDS_DIR = path.join(path.dirname(module.uri), '..', '..', 'seeds');
|
||||
|
||||
/**
|
||||
* Initializes a new instance of UpdateLibrarySeed.
|
||||
* @class
|
||||
* @augments {PluginBase}
|
||||
* @classdesc This class represents the plugin UpdateLibrarySeed.
|
||||
* @constructor
|
||||
*/
|
||||
var UpdateLibrarySeed = function () {
|
||||
// Call base class' constructor.
|
||||
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}
|
||||
*/
|
||||
UpdateLibrarySeed.metadata = pluginMetadata;
|
||||
|
||||
// Prototypical inheritance from PluginBase.
|
||||
UpdateLibrarySeed.prototype = Object.create(PluginBase.prototype);
|
||||
UpdateLibrarySeed.prototype.constructor = UpdateLibrarySeed;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
UpdateLibrarySeed.prototype.main = function (callback) {
|
||||
// get the root hash
|
||||
var name = this.projectName,
|
||||
version;
|
||||
|
||||
// get the name and validate
|
||||
return this.getLibraryVersion()
|
||||
.then(vers => {
|
||||
version = vers;
|
||||
return this.checkForLibName(name);
|
||||
})
|
||||
.then(valid => {
|
||||
if (!valid) {
|
||||
var err = `Invalid library name "${name}"`;
|
||||
this.logger.error(err);
|
||||
return callback(err, this.result);
|
||||
}
|
||||
return this.updateSeed(name);
|
||||
})
|
||||
.then(() => this.recordVersion(name, version))
|
||||
.then(() => {
|
||||
this.logger.info(`Finished updating library seed for ${name}`);
|
||||
this.result.setSuccess(true);
|
||||
callback(null, this.result);
|
||||
})
|
||||
.fail(err => callback(err, this.result));
|
||||
};
|
||||
|
||||
UpdateLibrarySeed.prototype.getLibraryVersion = function () {
|
||||
var version,
|
||||
config = this.getCurrentConfig(),
|
||||
vnames = ['major', 'minor', 'patch'],
|
||||
bumpIndex,
|
||||
newVersion;
|
||||
|
||||
version = (this.core.getAttribute(this.rootNode, 'version') || '0.0.0')
|
||||
.split('.').map(num => parseInt(num));
|
||||
bumpIndex = vnames.indexOf(config.releaseType);
|
||||
version[bumpIndex]++;
|
||||
|
||||
newVersion = version.join('.');
|
||||
this.core.setAttribute(this.rootNode, 'version', newVersion);
|
||||
return this.save(`Bumped version to ${newVersion}`).then(() => newVersion);
|
||||
};
|
||||
|
||||
UpdateLibrarySeed.prototype.checkForLibName = function (name) {
|
||||
// check for the library name from the fs
|
||||
return Q.nfcall(fs.readdir, SEEDS_DIR).then(seeds => seeds.indexOf(name) !== -1);
|
||||
};
|
||||
|
||||
UpdateLibrarySeed.prototype.updateSeed = function (seedName) {
|
||||
var deferred = Q.defer(),
|
||||
err,
|
||||
job = childProcess.spawn('webgme', ['new', 'seed', seedName], {
|
||||
cwd: path.dirname(module.uri)
|
||||
});
|
||||
|
||||
this.logger.info(`Updating ${seedName} seed`);
|
||||
job.on('error', _err => {
|
||||
err = _err;
|
||||
});
|
||||
|
||||
job.on('exit', code => {
|
||||
if (!code) {
|
||||
deferred.resolve();
|
||||
} else {
|
||||
deferred.reject(err || code);
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
UpdateLibrarySeed.prototype.recordVersion = function (seed, version) {
|
||||
var versionPath = path.join(SEEDS_DIR, seed, 'version.txt');
|
||||
this.logger.info(`Updating ${seed} version (${version})`);
|
||||
return Q.nfcall(fs.writeFile, versionPath, version);
|
||||
};
|
||||
|
||||
return UpdateLibrarySeed;
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"id": "UpdateLibrarySeed",
|
||||
"name": "UpdateLibrarySeed",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"icon": {
|
||||
"class": "glyphicon glyphicon-cog",
|
||||
"src": ""
|
||||
},
|
||||
"disableServerSideExecution": false,
|
||||
"disableBrowserSideExecution": true,
|
||||
"writeAccessRequired": false,
|
||||
"configStructure": [
|
||||
{
|
||||
"name": "releaseType",
|
||||
"displayName": "Release Type",
|
||||
"description": "Specify major, minor or patch release",
|
||||
"value": "minor",
|
||||
"valueItems": [
|
||||
"major",
|
||||
"minor",
|
||||
"patch"
|
||||
],
|
||||
"valueType": "string",
|
||||
"readOnly": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
var path = require('path'),
|
||||
Q = require('q'),
|
||||
fs = require('fs'),
|
||||
exists = require('exists-file'),
|
||||
utils = require('../../common/utils'),
|
||||
NO_LOG_FOUND = '';
|
||||
|
||||
var JobLogManager = function(logger, config) {
|
||||
this.rootDir = path.join(config.blob.fsDir, 'log-storage');
|
||||
this.logger = logger.fork('JobLogManager');
|
||||
this._onCopyFinished = {};
|
||||
};
|
||||
|
||||
JobLogManager.prototype._getFilePath = function(jInfo) {
|
||||
this.logger.debug(`getting file path for ${jInfo.job} in ${jInfo.project} on ${jInfo.branch}`);
|
||||
var jobId = jInfo.job.replace(/\//g, '_'),
|
||||
filename = `${jobId}.txt`;
|
||||
|
||||
return path.join(this.rootDir, jInfo.project, jInfo.branch, filename);
|
||||
};
|
||||
|
||||
JobLogManager.prototype.exists = function(jobInfo) {
|
||||
var filename = this._getFilePath(jobInfo);
|
||||
return Q.nfcall(exists, filename);
|
||||
};
|
||||
|
||||
JobLogManager.prototype.mkdirIfNeeded = function(dir) {
|
||||
return Q.nfcall(exists, dir).then(exist => {
|
||||
if (!exist) {
|
||||
this.logger.debug('making dir:', dir);
|
||||
return Q.nfcall(fs.mkdir, dir)
|
||||
.catch(() => this.logger.debug(`dir already created: ${dir}`));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
JobLogManager.prototype._copyFile = function(src, dst) {
|
||||
return Q.nfcall(exists, src).then(exists => {
|
||||
if (!exists) {
|
||||
this.logger.warn(`Cannot copy file from ${src}. File doesn't exist!`);
|
||||
return;
|
||||
}
|
||||
|
||||
return this.mkdirIfNeeded(path.dirname(dst)).then(() => {
|
||||
var deferred = Q.defer(),
|
||||
stream = fs.createReadStream(src).pipe(fs.createWriteStream(dst));
|
||||
|
||||
stream.on('error', deferred.reject);
|
||||
stream.on('finish', deferred.resolve);
|
||||
|
||||
return deferred.promise;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Copy one branch info to the next
|
||||
// Could optimize this to symlink until data appended...
|
||||
JobLogManager.prototype.migrate = function(migrationInfo, jobIds) {
|
||||
// Recursively copy the srcBranch dir to the dstBranch dir
|
||||
// Should probably use streams...
|
||||
// Need to block appends to the given files so they are not written
|
||||
// to until they have finished copying...
|
||||
// TODO
|
||||
var jobs,
|
||||
src,
|
||||
dst,
|
||||
i;
|
||||
|
||||
for (i = jobIds.length; i--;) {
|
||||
this._onCopyFinished[jobIds[i]] = [];
|
||||
}
|
||||
|
||||
// Copy the job files and evaluate each of the finish functions
|
||||
this.logger.info('migrating from ' + migrationInfo.srcBranch + ' to '+ migrationInfo.dstBranch);
|
||||
return Q.all(jobIds.map(jobId => {
|
||||
src = this._getFilePath({
|
||||
project: migrationInfo.project,
|
||||
branch: migrationInfo.srcBranch,
|
||||
job: jobId
|
||||
});
|
||||
dst = this._getFilePath({
|
||||
project: migrationInfo.project,
|
||||
branch: migrationInfo.dstBranch,
|
||||
job: jobId
|
||||
});
|
||||
return this._copyFile(src, dst).then(() => {
|
||||
jobs = this._onCopyFinished[jobId];
|
||||
for (var j = jobs.length; j--;) {
|
||||
jobs[j]();
|
||||
}
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
JobLogManager.prototype._appendTo = function(filename, logs) {
|
||||
return Q.nfcall(exists, filename).then(exists => {
|
||||
var promise = Q().then(() => '');
|
||||
if (exists) {
|
||||
promise = Q.nfcall(fs.readFile, filename, 'utf8');
|
||||
}
|
||||
|
||||
return promise.then(content => {
|
||||
// This could be optimized to not re-read/write the whole file each time...
|
||||
var lines = utils.resolveCarriageReturns(content + logs);
|
||||
return Q.nfcall(fs.writeFile, filename, lines.join('\n'));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
JobLogManager.prototype.appendTo = function(jobInfo, logs) {
|
||||
var filename = this._getFilePath(jobInfo),
|
||||
branchDirname = path.dirname(filename),
|
||||
projDirname = path.dirname(branchDirname);
|
||||
|
||||
this.logger.info(`Appending content to ${filename}`);
|
||||
// Make directory if needed
|
||||
return this.mkdirIfNeeded(this.rootDir)
|
||||
.then(() => this.mkdirIfNeeded(projDirname))
|
||||
.then(() => this.mkdirIfNeeded(branchDirname))
|
||||
.then(() => this._appendTo(filename, logs));
|
||||
};
|
||||
|
||||
JobLogManager.prototype.getLog = function(jobInfo) {
|
||||
var filename = this._getFilePath(jobInfo);
|
||||
|
||||
this.logger.info(`Getting log content from ${filename}`);
|
||||
return this.exists(jobInfo)
|
||||
.then(exists => {
|
||||
if (exists) {
|
||||
return Q.nfcall(fs.readFile, filename);
|
||||
}
|
||||
return NO_LOG_FOUND;
|
||||
});
|
||||
};
|
||||
|
||||
JobLogManager.prototype.delete = function(jobInfo) {
|
||||
var filename = this._getFilePath(jobInfo);
|
||||
|
||||
return this.exists(jobInfo)
|
||||
.then(exists => {
|
||||
if (exists) {
|
||||
this.logger.debug(`Removing file ${filename}`);
|
||||
return Q.nfcall(fs.unlink, filename);
|
||||
}
|
||||
this.logger.info(`${filename} doesn't exist. No need to delete...`);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = JobLogManager;
|
||||
@@ -0,0 +1,93 @@
|
||||
/*jshint node:true*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var express = require('express'),
|
||||
JobLogManager = require('./JobLogManager'),
|
||||
router = express.Router();
|
||||
|
||||
/**
|
||||
* Called when the server is created but before it starts to listening to incoming requests.
|
||||
* N.B. gmeAuth, safeStorage and workerManager are not ready to use until the start function is called.
|
||||
* (However inside an incoming request they are all ensured to have been initialized.)
|
||||
*
|
||||
* @param {object} middlewareOpts - Passed by the webgme server.
|
||||
* @param {GmeConfig} middlewareOpts.gmeConfig - GME config parameters.
|
||||
* @param {GmeLogger} middlewareOpts.logger - logger
|
||||
* @param {function} middlewareOpts.ensureAuthenticated - Ensures the user is authenticated.
|
||||
* @param {function} middlewareOpts.getUserId - If authenticated retrieves the userId from the request.
|
||||
* @param {object} middlewareOpts.gmeAuth - Authorization module.
|
||||
* @param {object} middlewareOpts.safeStorage - Accesses the storage and emits events (PROJECT_CREATED, COMMIT..).
|
||||
* @param {object} middlewareOpts.workerManager - Spawns and keeps track of "worker" sub-processes.
|
||||
*/
|
||||
function initialize(middlewareOpts) {
|
||||
var logger = middlewareOpts.logger.fork('JobLogsAPI'),
|
||||
ensureAuthenticated = middlewareOpts.ensureAuthenticated,
|
||||
gmeConfig = middlewareOpts.gmeConfig,
|
||||
logManager = new JobLogManager(logger, gmeConfig);
|
||||
|
||||
logger.debug('initializing ...');
|
||||
|
||||
// Ensure authenticated can be used only after this rule.
|
||||
router.use('*', function (req, res, next) {
|
||||
// This header ensures that any failures with authentication won't redirect.
|
||||
res.setHeader('X-WebGME-Media-Type', 'webgme.v1');
|
||||
next();
|
||||
});
|
||||
|
||||
// Use ensureAuthenticated if the routes require authentication. (Can be set explicitly for each route.)
|
||||
router.use('*', ensureAuthenticated);
|
||||
|
||||
router.get('/:project/:branch/:job', function (req, res/*, next*/) {
|
||||
// Retrieve the job logs for the given job
|
||||
logManager.getLog(req.params).then(log => {
|
||||
res.set('Content-Type', 'text/plain');
|
||||
res.send(log);
|
||||
});
|
||||
});
|
||||
|
||||
router.patch('/:project/:branch/:job', function (req, res/*, next*/) {
|
||||
var logs = req.body.patch;
|
||||
logger.info(`Received append request for ${req.params.job} in ${req.params.project}`);
|
||||
logManager.appendTo(req.params, logs)
|
||||
.then(() => res.send('Append successful'))
|
||||
.catch(err => logger.error(`Append failed: ${err}`));
|
||||
});
|
||||
|
||||
router.delete('/:project/:branch/:job', function (req, res/*, next*/) {
|
||||
logManager.delete(req.params).then(() => res.send('delete successful'));
|
||||
});
|
||||
|
||||
router.post('/migrate/:project/:srcBranch/:dstBranch', function (req, res/*, next*/) {
|
||||
var jobs = req.body.jobs;
|
||||
logManager.migrate(req.params, jobs)
|
||||
.then(() => res.send('migration successful'))
|
||||
.fail(err => logger.error(err));
|
||||
});
|
||||
|
||||
logger.debug('ready');
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the server starts listening.
|
||||
* @param {function} callback
|
||||
*/
|
||||
function start(callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the server stopped listening.
|
||||
* @param {function} callback
|
||||
*/
|
||||
function stop(callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
initialize: initialize,
|
||||
router: router,
|
||||
start: start,
|
||||
stop: stop
|
||||
};
|
||||
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
@@ -0,0 +1 @@
|
||||
0.2.0
|
||||
Arquivo binário não exibido.
@@ -0,0 +1 @@
|
||||
0.3.0
|
||||
Arquivo binário não exibido.
@@ -117,7 +117,7 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
TextEditorControl.prototype.saveTextFor.call(this, id, text);
|
||||
TextEditorControl.prototype.saveTextFor.call(this, id, text, true);
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'js/Constants'
|
||||
'js/Constants',
|
||||
'deepforge/utils'
|
||||
], function (
|
||||
CONSTANTS
|
||||
CONSTANTS,
|
||||
utils
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
@@ -27,6 +29,9 @@ define([
|
||||
this._lineToExec = {};
|
||||
this._pipelineNames = {};
|
||||
|
||||
this.abbrToId = {};
|
||||
this.abbrFor = {};
|
||||
|
||||
this._initWidgetEventHandlers();
|
||||
|
||||
this._logger.debug('ctor finished');
|
||||
@@ -38,14 +43,36 @@ define([
|
||||
|
||||
ExecutionIndexControl.prototype.setExecutionDisplayed = function (id, bool) {
|
||||
var lines = this._linesForExecution[id] || [],
|
||||
action = bool ? 'addNode' : 'removeNode';
|
||||
|
||||
// If removing, just get the ids
|
||||
lines = bool ? lines : lines.map(line => line.id);
|
||||
otherLines,
|
||||
wasMultiLine = this.displayedExecCount() > 1,
|
||||
isMultiLine;
|
||||
|
||||
this._logger.info(`setting execution ${id} to ${bool ? 'displayed' : 'hidden'}`);
|
||||
this.displayedExecutions[id] = bool;
|
||||
|
||||
// If we just crossed the multi line threshold, then update all the lines
|
||||
isMultiLine = this.displayedExecCount() > 1;
|
||||
if (isMultiLine !== wasMultiLine) {
|
||||
// Refresh the other lines visible
|
||||
otherLines = Object.keys(this.displayedExecutions)
|
||||
.filter(eId => this.displayedExecutions[eId] && (eId !== id))
|
||||
.map(id => this._linesForExecution[id] || [])
|
||||
.reduce((l1, l2) => l1.concat(l2), []);
|
||||
|
||||
this._updateLines(otherLines, false);
|
||||
this._updateLines(otherLines, true);
|
||||
}
|
||||
|
||||
this._updateLines(lines, bool);
|
||||
};
|
||||
|
||||
ExecutionIndexControl.prototype._updateLines = function (lines, added) {
|
||||
var action = added ? 'addNode' : 'removeNode';
|
||||
|
||||
// If removing, just get the ids
|
||||
lines = !added ? lines : lines.map(line => this._getObjectDescriptor(line))
|
||||
.filter(line => !!line);
|
||||
|
||||
// update the given lines
|
||||
for (var i = lines.length; i--;) {
|
||||
this._widget[action](lines[i]);
|
||||
@@ -83,6 +110,28 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
ExecutionIndexControl.prototype.getUniqAbbreviation = function(desc) {
|
||||
// Get a unique abbreviation for the given execution
|
||||
var base = utils.abbr(desc.name).toLowerCase(),
|
||||
abbr = base,
|
||||
oldAbbr = this.abbrFor[desc.id],
|
||||
i = 2;
|
||||
|
||||
// Make sure it is unique!
|
||||
while (this.abbrToId[abbr] && this.abbrToId[abbr] !== desc.id) {
|
||||
abbr = base + i;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (oldAbbr !== undefined) { // updating abbr
|
||||
delete this.abbrToId[oldAbbr];
|
||||
}
|
||||
|
||||
this.abbrToId[abbr] = desc.id;
|
||||
this.abbrFor[desc.id] = abbr;
|
||||
return abbr;
|
||||
};
|
||||
|
||||
// This next function retrieves the relevant node information for the widget
|
||||
ExecutionIndexControl.prototype._getObjectDescriptor = function (nodeId) {
|
||||
var node = this._client.getNode(nodeId),
|
||||
@@ -105,10 +154,16 @@ define([
|
||||
desc.originTime = node.getAttribute('createdAt');
|
||||
desc.originId = node.getPointer('origin').to;
|
||||
desc.pipelineName = this._pipelineNames[desc.originId];
|
||||
desc.startTime = node.getAttribute('startTime');
|
||||
desc.endTime = node.getAttribute('endTime');
|
||||
this._logger.debug(`Looking up pipeline name for ${desc.name}: ${desc.pipelineName}`);
|
||||
// Add the (unique) abbreviation of the execution!
|
||||
desc.abbr = this.getUniqAbbreviation(desc);
|
||||
|
||||
// Create a territory for this origin and update it!
|
||||
this._selfPatterns[desc.originId] = {children: 0};
|
||||
if (desc.originId) {
|
||||
this._selfPatterns[desc.originId] = {children: 0};
|
||||
}
|
||||
setTimeout(() => this._client.updateTerritory(this._territoryId, this._selfPatterns), 0);
|
||||
} else if (type === 'Line') {
|
||||
desc = this.getLineDesc(node);
|
||||
@@ -147,7 +202,6 @@ define([
|
||||
|
||||
desc = {
|
||||
id: id,
|
||||
//execName: execName,
|
||||
execId: execId,
|
||||
lineName: node.getAttribute('name'),
|
||||
name: node.getAttribute('name'),
|
||||
@@ -155,12 +209,23 @@ define([
|
||||
points: points
|
||||
};
|
||||
|
||||
// Update records
|
||||
if (!this._linesForExecution[execId]) {
|
||||
this._linesForExecution[execId] = [];
|
||||
if (!this._lineToExec[id]) {
|
||||
// Update records
|
||||
if (!this._linesForExecution[execId]) {
|
||||
this._linesForExecution[execId] = [];
|
||||
}
|
||||
this._linesForExecution[execId].push(id);
|
||||
this._lineToExec[id] = execId;
|
||||
}
|
||||
|
||||
// If there are multiple executions, add the exec's abbr
|
||||
var displayedCnt = this.displayedExecCount(),
|
||||
execAbbr;
|
||||
|
||||
if (displayedCnt > 1) {
|
||||
execAbbr = this.abbrFor[execId] || this._getObjectDescriptor(execId).abbr;
|
||||
desc.name = `${desc.name} (${execAbbr})`;
|
||||
}
|
||||
this._linesForExecution[execId].push(desc);
|
||||
this._lineToExec[id] = execId;
|
||||
|
||||
return desc;
|
||||
};
|
||||
@@ -235,18 +300,25 @@ define([
|
||||
};
|
||||
|
||||
ExecutionIndexControl.prototype._onUnload = function (id) {
|
||||
var execId = this._lineToExec[id];
|
||||
var execId = this._lineToExec[id],
|
||||
abbr;
|
||||
|
||||
if (execId) { // it is a line
|
||||
delete this._lineToExec[id];
|
||||
for (var k = this._linesForExecution[execId].length; k--;) {
|
||||
if (this._linesForExecution[execId][k].id === id) {
|
||||
if (this._linesForExecution[execId][k] === id) {
|
||||
this._linesForExecution[execId].splice(k, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.abbrFor[id]) {
|
||||
abbr = this.abbrFor[id];
|
||||
delete this.abbrFor[id];
|
||||
delete this.abbrToId[abbr];
|
||||
}
|
||||
|
||||
this._widget.removeNode(id);
|
||||
};
|
||||
|
||||
@@ -255,6 +327,12 @@ define([
|
||||
return this.displayedExecutions[line.execId];
|
||||
};
|
||||
|
||||
ExecutionIndexControl.prototype.displayedExecCount = function () {
|
||||
return Object.keys(this.displayedExecutions)
|
||||
.map(id => this.displayedExecutions[id])
|
||||
.filter(shown => shown).length;
|
||||
};
|
||||
|
||||
ExecutionIndexControl.prototype._stateActiveObjectChanged = function (model, activeObjectId) {
|
||||
if (this._currentNodeId === activeObjectId) {
|
||||
// The same node selected as before - do not trigger
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
/*globals define, WebGMEGlobal */
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Tue May 24 2016 10:15:19 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/Constants',
|
||||
'deepforge/Constants',
|
||||
'panels/EasyDAG/EasyDAGControl',
|
||||
'deepforge/viz/PipelineControl',
|
||||
'underscore'
|
||||
], function (
|
||||
GME_CONSTANTS,
|
||||
CONSTANTS,
|
||||
EasyDAGControl,
|
||||
PipelineControl,
|
||||
@@ -62,7 +61,7 @@ define([
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.etype === CONSTANTS.TERRITORY_EVENT_UNLOAD) {
|
||||
if (event.etype === GME_CONSTANTS.TERRITORY_EVENT_UNLOAD) {
|
||||
this.originId = null;
|
||||
this._widget.onOriginDeleted();
|
||||
} else {
|
||||
@@ -90,6 +89,65 @@ define([
|
||||
};
|
||||
};
|
||||
|
||||
ExecutionViewControl.prototype._getObjectDescriptor = function(id) {
|
||||
var desc = PipelineControl.prototype._getObjectDescriptor.call(this, id),
|
||||
childrenIds,
|
||||
node,
|
||||
opId;
|
||||
|
||||
// If it is a job, add the operation attributes
|
||||
if (this.hasMetaName(id, 'Job')) {
|
||||
node = this._client.getNode(id);
|
||||
childrenIds = node.getChildrenIds();
|
||||
opId = childrenIds.find(id => this.hasMetaName(id, 'Operation'));
|
||||
|
||||
desc.opAttributes = {};
|
||||
if (opId) {
|
||||
var opNode = this._client.getNode(opId),
|
||||
attrs,
|
||||
allAttrs = {},
|
||||
hiddenAttrs = [
|
||||
CONSTANTS.LINE_OFFSET,
|
||||
'code',
|
||||
'name'
|
||||
],
|
||||
i;
|
||||
|
||||
opNode.getValidAttributeNames().concat(opNode.getAttributeNames())
|
||||
.forEach(attr => allAttrs[attr] = true);
|
||||
|
||||
// Remove skip values
|
||||
hiddenAttrs.forEach(attr => delete allAttrs[attr]);
|
||||
|
||||
attrs = Object.keys(allAttrs);
|
||||
for (i = attrs.length; i--;) {
|
||||
desc.opAttributes[attrs[i]] = {
|
||||
name: attrs[i],
|
||||
value: opNode.getAttribute(attrs[i]),
|
||||
type: 'string'
|
||||
};
|
||||
}
|
||||
|
||||
// Pointers
|
||||
var allPtrs = {},
|
||||
ptrs;
|
||||
|
||||
opNode.getValidPointerNames().concat(opNode.getPointerNames())
|
||||
.filter(ptr => ptr !== 'base')
|
||||
.forEach(ptr => allPtrs[ptr] = true);
|
||||
|
||||
ptrs = Object.keys(allPtrs);
|
||||
for (i = ptrs.length; i--;) {
|
||||
desc.pointers[ptrs[i]] = opNode.getPointer(ptrs[i]).to;
|
||||
}
|
||||
|
||||
} else {
|
||||
this.logger.error(`Job "${desc.name}" (${id}) is missing an operation!`);
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
};
|
||||
|
||||
ExecutionViewControl.prototype._onLoad = function(id) {
|
||||
var desc = this._getObjectDescriptor(id);
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/* globals define */
|
||||
// A notification widget which filters out stdout update notifications
|
||||
define([
|
||||
'deepforge/Constants',
|
||||
'js/Widgets/Notification/NotificationWidget'
|
||||
], function(
|
||||
CONSTANTS,
|
||||
GmeNotificationWidget
|
||||
) {
|
||||
var NotificationWidget = function() {
|
||||
GmeNotificationWidget.apply(this, arguments);
|
||||
};
|
||||
|
||||
NotificationWidget.prototype = Object.create(GmeNotificationWidget.prototype);
|
||||
|
||||
NotificationWidget.prototype.isUserNotication = function(data) {
|
||||
return data.message.indexOf(CONSTANTS.STDOUT_UPDATE) === -1;
|
||||
};
|
||||
|
||||
NotificationWidget.prototype._refreshNotifications = function(eventData) {
|
||||
|
||||
if (this.isUserNotication(eventData)) {
|
||||
GmeNotificationWidget.prototype._refreshNotifications.call(this, eventData);
|
||||
}
|
||||
};
|
||||
|
||||
return NotificationWidget;
|
||||
});
|
||||
@@ -1,8 +1,5 @@
|
||||
/*globals define, _, WebGMEGlobal, $ */
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* @author rkereskenyi / https://github.com/rkereskenyi
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/PanelBase/PanelBase',
|
||||
@@ -10,13 +7,15 @@ define([
|
||||
'js/Widgets/BranchStatus/BranchStatusWidget',
|
||||
'js/Widgets/BranchSelector/BranchSelectorWidget',
|
||||
'js/Widgets/KeyboardManager/KeyboardManagerWidget',
|
||||
'js/Widgets/Notification/NotificationWidget'
|
||||
], function (PanelBase,
|
||||
NetworkStatusWidget,
|
||||
BranchStatusWidget,
|
||||
BranchSelectorWidget,
|
||||
KeyboardManagerWidget,
|
||||
NotificationWidget) {
|
||||
'./FilteredNotificationWidget'
|
||||
], function (
|
||||
PanelBase,
|
||||
NetworkStatusWidget,
|
||||
BranchStatusWidget,
|
||||
BranchSelectorWidget,
|
||||
KeyboardManagerWidget,
|
||||
NotificationWidget
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*globals DeepForge, define, $, WebGMEGlobal*/
|
||||
/*globals define, $, WebGMEGlobal*/
|
||||
// These are actions defined for specific meta types. They are evaluated from
|
||||
// the context of the ForgeActionButton
|
||||
define([
|
||||
@@ -9,7 +9,8 @@ define([
|
||||
], function(
|
||||
Materialize,
|
||||
Q,
|
||||
REGISTRY_KEYS
|
||||
REGISTRY_KEYS,
|
||||
DeepForge
|
||||
) {
|
||||
var FILE_UPLOAD_INPUT = $('<input type="file" />');
|
||||
|
||||
@@ -138,18 +139,19 @@ define([
|
||||
}
|
||||
];
|
||||
|
||||
var makeRestartButton = function(name, pluginId) {
|
||||
var makeRestartButton = function(name, pluginId, hotkeys) {
|
||||
return {
|
||||
name: 'Restart ' + name,
|
||||
icon: 'replay',
|
||||
priority: 1000,
|
||||
color: 'red',
|
||||
hotkey: hotkeys && 'shift enter',
|
||||
filter: function() {
|
||||
// Only show if stopped!
|
||||
return !this.isRunning();
|
||||
},
|
||||
action: function(event) {
|
||||
this.runExecutionPlugin(pluginId, event.shiftKey);
|
||||
this.runExecutionPlugin(pluginId, {useSecondary: event.shiftKey});
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -239,28 +241,18 @@ define([
|
||||
}
|
||||
],
|
||||
Execution: [
|
||||
makeRestartButton('Execution', 'ExecutePipeline'),
|
||||
makeRestartButton('Execution', 'ExecutePipeline', true),
|
||||
// Stop execution button
|
||||
{
|
||||
name: 'Stop Running Execution',
|
||||
icon: 'stop',
|
||||
priority: 1001,
|
||||
hotkey: 'shift enter',
|
||||
filter: function() {
|
||||
return this.isRunning();
|
||||
},
|
||||
action: function() {
|
||||
// Stop every running job
|
||||
var execNode = this.client.getNode(this._currentNodeId),
|
||||
jobIds = execNode.getChildrenIds(),
|
||||
msg = `Canceling ${execNode.getAttribute('name')} execution`;
|
||||
|
||||
this.client.startTransaction(msg);
|
||||
jobIds.map(id => this.client.getNode(id))
|
||||
.filter(job => this.isRunning(job)) // get running jobs
|
||||
.forEach(job => this.stopJob(job)); // stop them
|
||||
|
||||
this.client.setAttributes(execNode.getId(), 'status', 'canceled');
|
||||
this.client.completeTransaction();
|
||||
this.stopExecution();
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@@ -1,53 +1,46 @@
|
||||
/*globals DeepForge, $, WebGMEGlobal, window, define, _ */
|
||||
/*globals $, window, define, _ */
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'panel/FloatingActionButton/styles/Materialize',
|
||||
'blob/BlobClient',
|
||||
'executor/ExecutorClient',
|
||||
'js/Constants',
|
||||
'panel/FloatingActionButton/FloatingActionButton',
|
||||
'deepforge/viz/PipelineControl',
|
||||
'deepforge/viz/NodePrompter',
|
||||
'deepforge/viz/Execute',
|
||||
'./Actions',
|
||||
'widgets/EasyDAG/AddNodeDialog',
|
||||
'js/RegistryKeys',
|
||||
'js/Panels/MetaEditor/MetaEditorConstants',
|
||||
'q',
|
||||
'text!./PluginConfig.json',
|
||||
'deepforge/globals'
|
||||
], function (
|
||||
Materialize,
|
||||
BlobClient,
|
||||
ExecutorClient,
|
||||
CONSTANTS,
|
||||
PluginButton,
|
||||
PipelineControl,
|
||||
NodePrompter,
|
||||
Execute,
|
||||
ACTIONS,
|
||||
AddNodeDialog,
|
||||
REGISTRY_KEYS,
|
||||
META_CONSTANTS,
|
||||
Q,
|
||||
PluginConfig
|
||||
DeepForge
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var NEW_OPERATION_ID = '__NEW_OPERATION__';
|
||||
var ForgeActionButton= function (layoutManager, params) {
|
||||
PluginButton.call(this, layoutManager, params);
|
||||
this._pluginConfig = JSON.parse(PluginConfig);
|
||||
this._executor = new ExecutorClient({
|
||||
logger: this.logger.fork('ExecutorClient'),
|
||||
serverPort: WebGMEGlobal.gmeConfig.server.port,
|
||||
httpsecure: window.location.protocol === 'https:'
|
||||
});
|
||||
this._client = this.client;
|
||||
this._actions = [];
|
||||
this._blobClient = new BlobClient({
|
||||
logger: this.logger.fork('BlobClient')
|
||||
});
|
||||
|
||||
Execute.call(this, this.client, this.logger);
|
||||
this.initializeKeyListener();
|
||||
this.logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
@@ -55,9 +48,46 @@ define([
|
||||
_.extend(
|
||||
ForgeActionButton.prototype,
|
||||
PluginButton.prototype,
|
||||
Execute.prototype,
|
||||
PipelineControl.prototype
|
||||
);
|
||||
|
||||
ForgeActionButton.prototype.initializeKeyListener = function() {
|
||||
// add key listener to parent?
|
||||
this.oldOnKeyDown = document.body.onkeydown;
|
||||
document.onkeydown = event => {
|
||||
var keys = String.fromCharCode(event.which) || '',
|
||||
names = Object.keys(this.buttons),
|
||||
btn,
|
||||
name;
|
||||
|
||||
// Simple button detection
|
||||
if (event.which === 13) {
|
||||
keys = 'enter';
|
||||
}
|
||||
if (event.shiftKey) {
|
||||
keys = 'shift ' + keys;
|
||||
}
|
||||
|
||||
for (var i = names.length; i--;) {
|
||||
name = names[i];
|
||||
btn = this.buttons[name];
|
||||
if (btn.hotkey && btn.hotkey === keys) {
|
||||
btn.action.call(this, event);
|
||||
}
|
||||
}
|
||||
if (this.oldOnKeyDown) {
|
||||
this.oldOnKeyDown(event);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.destroy = function() {
|
||||
PluginButton.prototype.destroy.call(this);
|
||||
PipelineControl.prototype.destroy.call(this);
|
||||
document.body.onclick = this.oldOnKeyDown;
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.findActionsFor = function(nodeId) {
|
||||
var node = this.client.getNode(nodeId),
|
||||
base = this.client.getNode(node.getMetaTypeId()),
|
||||
@@ -330,74 +360,5 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.runExecutionPlugin = function(pluginId, useSecondary) {
|
||||
var context = this.client.getCurrentPluginContext(pluginId),
|
||||
name = this.client.getNode(this._currentNodeId).getAttribute('name'),
|
||||
method;
|
||||
|
||||
context.managerConfig.namespace = 'pipeline';
|
||||
method = useSecondary ? 'runBrowserPlugin' : 'runServerPlugin';
|
||||
this.client[method](pluginId, context, (err, result) => {
|
||||
var msg = err ? `${name} failed!` : `${name} executed successfully!`,
|
||||
duration = err ? 4000 : 2000;
|
||||
|
||||
// Check if it was canceled - if so, show that type of message
|
||||
if (result) {
|
||||
msg = result.messages[0].message;
|
||||
duration = 4000;
|
||||
}
|
||||
|
||||
Materialize.toast(msg, duration);
|
||||
});
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.isRunning = function(node) {
|
||||
var baseId,
|
||||
base,
|
||||
type;
|
||||
|
||||
node = node || this.client.getNode(this._currentNodeId);
|
||||
baseId = node.getBaseId();
|
||||
base = this.client.getNode(baseId);
|
||||
type = base.getAttribute('name');
|
||||
|
||||
if (type === 'Execution') {
|
||||
return node.getAttribute('status') === 'running';
|
||||
} else if (type === 'Job') {
|
||||
return this.isRunningJob(node);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.isRunningJob = function(job) {
|
||||
var status = job.getAttribute('status');
|
||||
|
||||
return (status === 'running' || status === 'pending') &&
|
||||
job.getAttribute('secret') && job.getAttribute('jobId');
|
||||
};
|
||||
|
||||
ForgeActionButton.prototype.stopJob = function(job) {
|
||||
var jobHash,
|
||||
jobId,
|
||||
secret;
|
||||
|
||||
job = job || this.client.getNode(this._currentNodeId);
|
||||
jobId = job.getId();
|
||||
jobHash = job.getAttribute('jobId');
|
||||
secret = job.getAttribute('secret');
|
||||
if (!jobHash || !secret) {
|
||||
this.logger.error('Cannot stop job. Missing jobHash or secret');
|
||||
return;
|
||||
}
|
||||
|
||||
this.client.delAttributes(jobId, 'jobId');
|
||||
this.client.delAttributes(jobId, 'secret');
|
||||
this.client.setAttributes(jobId, 'status', 'canceled');
|
||||
|
||||
return this._executor.cancelJob(jobHash, secret)
|
||||
.then(() => this.logger.info(`${jobHash} has been cancelled!`))
|
||||
.fail(err => this.logger.error(`Job cancel failed: ${err}`));
|
||||
};
|
||||
|
||||
return ForgeActionButton;
|
||||
});
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"GenerateArchitecture": {
|
||||
"icon": "description",
|
||||
"priority": -1
|
||||
},
|
||||
"ExecutePipeline": {
|
||||
"icon": "play_arrow",
|
||||
"color": "green",
|
||||
"priority": 1
|
||||
},
|
||||
"ImportTorch": {
|
||||
"icon": "import_export",
|
||||
"priority": -1
|
||||
},
|
||||
"GenerateExecFile": {
|
||||
"icon": "play_for_work",
|
||||
"priority": -1
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,9 @@ define([
|
||||
|
||||
// The OperationCodeEditor should receive the
|
||||
if (!this.readOnly) {
|
||||
// Pass a reference to the panel
|
||||
this._panels[0].control.currentJobId = nodeId;
|
||||
|
||||
// Get the operation base node id and pass it to OpCodeEditor selObjChanged
|
||||
if (this._territoryId) {
|
||||
this._client.removeUI(this._territoryId);
|
||||
|
||||
@@ -32,6 +32,8 @@ define([
|
||||
LayerEditorControl.prototype._getObjectDescriptor = function (nodeId) {
|
||||
var desc = TextEditorControl.prototype._getObjectDescriptor.call(this, nodeId),
|
||||
node = this._client.getNode(nodeId),
|
||||
baseId = node.getBaseId(),
|
||||
base = this._client.getNode(baseId),
|
||||
hasCode = node.getValidAttributeNames().indexOf('code') > -1,
|
||||
template;
|
||||
|
||||
@@ -50,7 +52,16 @@ define([
|
||||
}
|
||||
|
||||
if (template) {
|
||||
desc.text = _.template(template)(desc);
|
||||
var baseTorchType = 'nn.Module';
|
||||
// If the base type is 'Criterion', set the base type to nn.Criterion
|
||||
if (base.getAttribute('name') === 'Criterion') {
|
||||
baseTorchType = 'nn.Criterion';
|
||||
}
|
||||
|
||||
desc.text = _.template(template)({
|
||||
name: desc.name,
|
||||
baseTorchType: baseTorchType
|
||||
});
|
||||
}
|
||||
return desc;
|
||||
};
|
||||
@@ -82,7 +93,7 @@ define([
|
||||
|
||||
this._client.startTransaction(msg);
|
||||
|
||||
TextEditorControl.prototype.saveTextFor.call(this, id, text);
|
||||
TextEditorControl.prototype.saveTextFor.call(this, id, text, true);
|
||||
this._client.setAttributes(id, 'name', layerSchema.name);
|
||||
|
||||
this._logger.debug(`Setting ctor args to ${ctorAttrs.join(',')}`);
|
||||
|
||||
@@ -2,9 +2,18 @@
|
||||
/*jshint browser: true*/
|
||||
|
||||
// This is a read-only view of the 'stdout' attribute for a Job node
|
||||
// if the job is running, get the logs from the log-storage
|
||||
define([
|
||||
'q',
|
||||
'deepforge/JobLogsClient',
|
||||
'js/Constants',
|
||||
'deepforge/Constants',
|
||||
'panels/TextEditor/TextEditorControl'
|
||||
], function (
|
||||
Q,
|
||||
JobLogsClient,
|
||||
GME_CONSTANTS,
|
||||
CONSTANTS,
|
||||
TextEditorControl
|
||||
) {
|
||||
|
||||
@@ -19,11 +28,68 @@ define([
|
||||
|
||||
_.extend(LogViewerControl.prototype, TextEditorControl.prototype);
|
||||
|
||||
LogViewerControl.prototype.getFullDescriptor = function (id) {
|
||||
var desc = LogViewerControl.prototype._getObjectDescriptor.call(this, id);
|
||||
|
||||
return this._getRunningLogs(id).then(text => {
|
||||
// Use attribute or running log if none
|
||||
desc.text = desc.text || text;
|
||||
return desc;
|
||||
});
|
||||
};
|
||||
|
||||
LogViewerControl.prototype.getUpdatedJobId = function (msg) {
|
||||
// verify that it is the given notification type
|
||||
if (msg.indexOf(CONSTANTS.STDOUT_UPDATE) !== -1) {
|
||||
return msg.replace(/^[^\/]*\//, '');
|
||||
}
|
||||
};
|
||||
|
||||
LogViewerControl.prototype.selectedObjectChanged = function (id) {
|
||||
TextEditorControl.prototype.selectedObjectChanged.call(this, id);
|
||||
// Listen for notifications about updated logs
|
||||
this.removeNotificationHandler();
|
||||
this.notificationHandler = (sender, data) => {
|
||||
var nodeId = this.getUpdatedJobId(data.message);
|
||||
if (nodeId === id) {
|
||||
this._onUpdate(id);
|
||||
}
|
||||
};
|
||||
this._client.addEventListener(GME_CONSTANTS.CLIENT.NOTIFICATION, this.notificationHandler);
|
||||
};
|
||||
|
||||
LogViewerControl.prototype.removeNotificationHandler = function () {
|
||||
// Remove the notifications listener
|
||||
if (this.notificationHandler) {
|
||||
this._client.removeEventListener();
|
||||
this.notificationHandler = null;
|
||||
}
|
||||
};
|
||||
|
||||
LogViewerControl.prototype.destroy = function () {
|
||||
TextEditorControl.prototype.destroy.call(this);
|
||||
this.removeNotificationHandler();
|
||||
};
|
||||
|
||||
LogViewerControl.prototype._onLoad = function (id) {
|
||||
this.getFullDescriptor(id).then(desc => this._widget.addNode(desc));
|
||||
};
|
||||
|
||||
LogViewerControl.prototype._onUpdate = function (id) {
|
||||
if (id === this._currentNodeId) {
|
||||
TextEditorControl.prototype._onUpdate.call(this, id);
|
||||
this.getFullDescriptor(id).then(desc => this._widget.updateNode(desc));
|
||||
}
|
||||
};
|
||||
|
||||
LogViewerControl.prototype._getRunningLogs = function (id) {
|
||||
var logManager = new JobLogsClient({
|
||||
logger: this._logger,
|
||||
projectId: this._client.getActiveProjectId(),
|
||||
branchName: this._client.getActiveBranchName()
|
||||
});
|
||||
|
||||
return logManager.getLog(id);
|
||||
};
|
||||
|
||||
return LogViewerControl;
|
||||
});
|
||||
|
||||
@@ -4,14 +4,12 @@
|
||||
define([
|
||||
'blob/BlobClient',
|
||||
'js/Constants',
|
||||
'js/Utils/GMEConcepts',
|
||||
'js/NodePropertyNames',
|
||||
'q',
|
||||
'deepforge/globals'
|
||||
], function (
|
||||
BlobClient,
|
||||
CONSTANTS,
|
||||
GMEConcepts,
|
||||
nodePropertyNames,
|
||||
Q,
|
||||
DeepForge
|
||||
) {
|
||||
|
||||
@@ -22,15 +20,11 @@ define([
|
||||
MainViewControl = function (options) {
|
||||
|
||||
this._logger = options.logger.fork('Control');
|
||||
|
||||
this._client = options.client;
|
||||
|
||||
// Initialize core collections and variables
|
||||
this._widget = options.widget;
|
||||
|
||||
this._currentNodeId = null;
|
||||
this._embedded = options.embedded;
|
||||
|
||||
this.territory = {};
|
||||
this.ui = {};
|
||||
this._blobClient = new BlobClient({
|
||||
@@ -67,12 +61,33 @@ define([
|
||||
};
|
||||
|
||||
this._widget.toggleEmbeddedPanel = () => this.toggleEmbeddedPanel();
|
||||
this._widget.updateLibraries = this.updateLibraries.bind(this);
|
||||
this._widget.checkLibUpdates = this.checkLibUpdates.bind(this);
|
||||
this._widget.getProjectName = this.getProjectName.bind(this);
|
||||
};
|
||||
|
||||
MainViewControl.prototype.getProjectName = function () {
|
||||
return this._client.getActiveProjectId().split('+')[1];
|
||||
};
|
||||
|
||||
MainViewControl.prototype.checkLibUpdates = function () {
|
||||
var pluginId = 'CheckLibraries',
|
||||
context = this._client.getCurrentPluginContext(pluginId);
|
||||
|
||||
return Q.ninvoke(this._client, 'runServerPlugin', pluginId, context)
|
||||
.then(res => {
|
||||
return res.messages.map(msg => msg.message.split(' '));
|
||||
});
|
||||
};
|
||||
|
||||
MainViewControl.prototype.updateLibraries = function (libraries) {
|
||||
var promises = libraries
|
||||
.map(lib => Q.ninvoke(this._client, 'updateLibrary', lib[0], lib[1]));
|
||||
|
||||
return Q.all(promises);
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer content update callbacks * * * * * * * */
|
||||
// One major concept here is with managing the territory. The territory
|
||||
// defines the parts of the project that the visualizer is interested in
|
||||
// (this allows the browser to then only load those relevant parts).
|
||||
MainViewControl.prototype.selectedObjectChanged = function (nodeId) {
|
||||
this._logger.debug('activeObject nodeId \'' + nodeId + '\'');
|
||||
|
||||
@@ -94,9 +109,11 @@ define([
|
||||
|
||||
// Update the territory
|
||||
this.territory[type] = {};
|
||||
this.territory[type][DeepForge.places[dirname]] = {children: 1};
|
||||
this.ui[type] = this._client.addUI(this, this.handleEvents.bind(this, type));
|
||||
this._client.updateTerritory(this.ui[type], this.territory[type]);
|
||||
DeepForge.places[dirname]().then(id => {
|
||||
this.territory[type][id] = {children: 1};
|
||||
this.ui[type] = this._client.addUI(this, this.handleEvents.bind(this, type));
|
||||
this._client.updateTerritory(this.ui[type], this.territory[type]);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -73,7 +73,8 @@ define([
|
||||
this.control.toggleEmbeddedPanel = this.toggleEmbeddedPanel.bind(this);
|
||||
var selectedObjectChanged = this.control.selectedObjectChanged;
|
||||
this.control.selectedObjectChanged = id => {
|
||||
this.embeddedPanel.control.selectedObjectChanged(this.getEmbeddedNode());
|
||||
this.getEmbeddedNode().then(nodeId =>
|
||||
this.embeddedPanel.control.selectedObjectChanged(nodeId));
|
||||
selectedObjectChanged.call(this.control, id);
|
||||
};
|
||||
|
||||
@@ -82,7 +83,11 @@ define([
|
||||
};
|
||||
|
||||
MainViewPanel.prototype.getEmbeddedNode = function() {
|
||||
return this.nextPanelIndex === 1 ? DeepForge.places.MyPipelines : DeepForge.places.MyExecutions;
|
||||
if (this.nextPanelIndex === 1) {
|
||||
return DeepForge.places.MyPipelines();
|
||||
} else {
|
||||
return DeepForge.places.MyExecutions();
|
||||
}
|
||||
};
|
||||
|
||||
MainViewPanel.prototype.toggleEmbeddedPanel = function (silent) {
|
||||
@@ -102,7 +107,8 @@ define([
|
||||
// Call on Resize and selectedObjectChanged
|
||||
this.onResize(this.width, this.height);
|
||||
if (!silent) {
|
||||
this.embeddedPanel.control.selectedObjectChanged(this.getEmbeddedNode());
|
||||
this.getEmbeddedNode().then(nodeId =>
|
||||
this.embeddedPanel.control.selectedObjectChanged(nodeId));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
define([
|
||||
'panels/TextEditor/TextEditorControl',
|
||||
'deepforge/viz/OperationControl',
|
||||
'deepforge/viz/Execute',
|
||||
'deepforge/Constants',
|
||||
'underscore'
|
||||
], function (
|
||||
TextEditorControl,
|
||||
OperationControl,
|
||||
Execute,
|
||||
CONSTANTS,
|
||||
_
|
||||
) {
|
||||
@@ -20,17 +22,21 @@ define([
|
||||
OperationCodeEditorControl = function (options) {
|
||||
options.attributeName = 'code';
|
||||
TextEditorControl.call(this, options);
|
||||
Execute.call(this, this._client, this._logger);
|
||||
this.currentJobId = null;
|
||||
};
|
||||
|
||||
_.extend(
|
||||
OperationCodeEditorControl.prototype,
|
||||
OperationControl.prototype,
|
||||
TextEditorControl.prototype
|
||||
TextEditorControl.prototype,
|
||||
Execute.prototype
|
||||
);
|
||||
|
||||
OperationCodeEditorControl.prototype._initWidgetEventHandlers = function () {
|
||||
TextEditorControl.prototype._initWidgetEventHandlers.call(this);
|
||||
this._widget.getOperationAttributes = this.getOperationAttributes.bind(this);
|
||||
this._widget.executeOrStopJob = this.executeOrStopJob.bind(this);
|
||||
};
|
||||
|
||||
OperationCodeEditorControl.prototype.TERRITORY_RULE = {children: 3};
|
||||
@@ -78,6 +84,19 @@ define([
|
||||
return attrs;
|
||||
};
|
||||
|
||||
OperationCodeEditorControl.prototype.executeOrStopJob = function () {
|
||||
var job;
|
||||
|
||||
if (this.currentJobId) { // Only if nested in a job
|
||||
job = this._client.getNode(this.currentJobId);
|
||||
if (this.isRunning(job)) {
|
||||
this.stopJob(job);
|
||||
} else {
|
||||
this.executeJob(job);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Line offset handling
|
||||
OperationCodeEditorControl.prototype.offsetNodeChanged = function (id) {
|
||||
// Create a territory for this node
|
||||
|
||||
+24
@@ -9,6 +9,7 @@ define([
|
||||
this._widget.allDataTypeIds = this.allDataTypeIds.bind(this);
|
||||
this._widget.allValidReferences = this.allValidReferences.bind(this);
|
||||
this._widget.addRefTo = this.addRefTo.bind(this);
|
||||
this._widget.setRefType = this.setRefType.bind(this);
|
||||
this._widget.changePtrName = this.changePtrName.bind(this);
|
||||
this._widget.removePtr = this.removePtr.bind(this);
|
||||
this._widget.getCreationNode = this.getCreationNode.bind(this);
|
||||
@@ -138,6 +139,29 @@ define([
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.setRefType = function(ref, targetId) {
|
||||
var meta = this._client.getPointerMeta(this._currentNodeId, ref),
|
||||
msg = `Setting ${ref} reference type to ${targetId}`;
|
||||
|
||||
if (!meta) {
|
||||
this.logger.debug(`No meta found for ${ref}. Creating a new reference to ${targetId}`);
|
||||
meta = {
|
||||
min: 1,
|
||||
max: 1,
|
||||
items: []
|
||||
};
|
||||
}
|
||||
|
||||
meta.items.push({
|
||||
id: targetId,
|
||||
max: 1
|
||||
});
|
||||
|
||||
this._client.startTransaction(msg);
|
||||
this._client.setPointerMeta(this._currentNodeId, ref, meta);
|
||||
this._client.completeTransaction();
|
||||
};
|
||||
|
||||
OperationInterfaceEditorEvents.prototype.changePtrName = function(from, to) {
|
||||
var opNode = this._client.getNode(this._currentNodeId),
|
||||
name = opNode.getAttribute('name'),
|
||||
|
||||
+18
-7
@@ -255,13 +255,23 @@ define([
|
||||
};
|
||||
|
||||
OperationInterfaceEditorControl.prototype.getPtrDescriptor = function(name) {
|
||||
var targetId = this._client.getPointerMeta(this._currentNodeId, name)
|
||||
.items[0].id,
|
||||
target = this._client.getNode(targetId),
|
||||
decManager = this._client.decoratorManager,
|
||||
Decorator = decManager.getDecoratorForWidget('OpIntPtrDecorator', 'EasyDAG'),
|
||||
var Decorator = this._client.decoratorManager.getDecoratorForWidget('OpIntPtrDecorator', 'EasyDAG'),
|
||||
id = 'ptr_'+name,
|
||||
used = this.isUsedInput(name);
|
||||
used = this.isUsedInput(name),
|
||||
ptrMeta = this._client.getPointerMeta(this._currentNodeId, name),
|
||||
targetId,
|
||||
target,
|
||||
baseName;
|
||||
|
||||
if (!ptrMeta || ptrMeta.items.length === 0) {
|
||||
// No known type
|
||||
this._logger.error(`No known target type for "${name}" reference`);
|
||||
baseName = null;
|
||||
} else {
|
||||
targetId = ptrMeta.items[0].id;
|
||||
target = this._client.getNode(targetId);
|
||||
baseName = target.getAttribute('name');
|
||||
}
|
||||
|
||||
if (used === null) {
|
||||
used = this._usage[id] !== undefined ? this._usage[id] : true;
|
||||
@@ -270,7 +280,8 @@ define([
|
||||
return {
|
||||
id: id,
|
||||
isPointer: true,
|
||||
baseName: target.getAttribute('name'),
|
||||
baseName: baseName,
|
||||
isUnknown: !baseName,
|
||||
Decorator: Decorator,
|
||||
used: used,
|
||||
attributes: {},
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'deepforge/Constants',
|
||||
'js/Constants',
|
||||
'panels/EasyDAG/EasyDAGControl',
|
||||
'deepforge/viz/PipelineControl',
|
||||
'deepforge/viz/Execute',
|
||||
'deepforge/globals',
|
||||
'common/core/coreQ',
|
||||
'common/storage/constants',
|
||||
@@ -12,8 +14,10 @@ define([
|
||||
'underscore'
|
||||
], function (
|
||||
CONSTANTS,
|
||||
GME_CONSTANTS,
|
||||
EasyDAGControl,
|
||||
PipelineControl,
|
||||
Execute,
|
||||
DeepForge,
|
||||
Core,
|
||||
STORAGE_CONSTANTS,
|
||||
@@ -29,26 +33,28 @@ define([
|
||||
DST: 'dst'
|
||||
},
|
||||
DECORATORS = {
|
||||
ArtifactLoader: 'ArtifactOpDecorator',
|
||||
ArtifactFinder: 'ArtifactOpDecorator'
|
||||
},
|
||||
WIDGET_NAME = 'EasyDAG';
|
||||
|
||||
DECORATORS[CONSTANTS.OP.INPUT] = 'ArtifactOpDecorator';
|
||||
|
||||
PipelineEditorControl = function (options) {
|
||||
EasyDAGControl.call(this, options);
|
||||
Execute.call(this, this._client, this._logger);
|
||||
this.addedIds = {};
|
||||
this.executionTerritory = {};
|
||||
this.executionUI = null;
|
||||
this.invalidated = {};
|
||||
this._widget.deleteNode = id => {
|
||||
this._deleteNode(id);
|
||||
};
|
||||
this._widget.deleteExecution = this.deleteExecution.bind(this);
|
||||
this._widget.isArchitecturePtr = this.isArchitecturePtr.bind(this);
|
||||
};
|
||||
|
||||
_.extend(
|
||||
PipelineEditorControl.prototype,
|
||||
EasyDAGControl.prototype,
|
||||
PipelineControl.prototype
|
||||
PipelineControl.prototype,
|
||||
Execute.prototype
|
||||
);
|
||||
|
||||
PipelineEditorControl.prototype._getValidInitialNodes =
|
||||
@@ -126,7 +132,7 @@ define([
|
||||
// Add arch/artifact dir to the territory
|
||||
// loading more than necessary.... can restrict it in the future
|
||||
// if perf is a problem
|
||||
this._territories[CONSTANTS.PROJECT_ROOT_ID] = {children: 2};
|
||||
this._territories[GME_CONSTANTS.PROJECT_ROOT_ID] = {children: 2};
|
||||
|
||||
this._client.updateTerritory(this._territoryId, this._territories);
|
||||
};
|
||||
@@ -498,7 +504,7 @@ define([
|
||||
|
||||
PipelineEditorControl.prototype._getTargetDirs = function (typeIds) {
|
||||
// Find the directories containing these types
|
||||
return this._client.getNode(CONSTANTS.PROJECT_ROOT_ID).getChildrenIds()
|
||||
return this._client.getNode(GME_CONSTANTS.PROJECT_ROOT_ID).getChildrenIds()
|
||||
// No referencing data meta types
|
||||
.filter(id => {
|
||||
var cMeta = this._client.getChildrenMeta(id),
|
||||
@@ -543,11 +549,11 @@ define([
|
||||
// Handle events related to the associated executions
|
||||
for (var i = events.length; i--;) {
|
||||
event = events[i];
|
||||
if (event.etype === CONSTANTS.TERRITORY_EVENT_LOAD) {
|
||||
if (event.etype === GME_CONSTANTS.TERRITORY_EVENT_LOAD) {
|
||||
this.onExecLoad(event.eid);
|
||||
} else if (event.etype === CONSTANTS.TERRITORY_EVENT_UPDATE) {
|
||||
} else if (event.etype === GME_CONSTANTS.TERRITORY_EVENT_UPDATE) {
|
||||
this.onExecUpdate(event.eid);
|
||||
} else if (event.etype === CONSTANTS.TERRITORY_EVENT_UNLOAD) {
|
||||
} else if (event.etype === GME_CONSTANTS.TERRITORY_EVENT_UNLOAD) {
|
||||
this.onExecUnload(event.eid);
|
||||
}
|
||||
}
|
||||
@@ -595,6 +601,42 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype._deleteTag = function (tagName) {
|
||||
// Check if the tag exists and delete it if so!
|
||||
var projectId = this._client.getActiveProjectId();
|
||||
|
||||
this._client.deleteTag(projectId, tagName, err => {
|
||||
if (err) {
|
||||
this.logger.error(`Tag deletion failed: ${err}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.deleteExecution = function (id) {
|
||||
var node = this._client.getNode(id),
|
||||
name = '',
|
||||
msg;
|
||||
|
||||
if (node) {
|
||||
name = node && node.getAttribute('name');
|
||||
}
|
||||
|
||||
msg = `Deleted ${name} (${id}) execution`;
|
||||
|
||||
// Stop the execution w/o setting any attributes on the execution
|
||||
this._client.startTransaction(msg);
|
||||
this._deleteTag(name); // Remove execution tag
|
||||
if (this.isRunning(node)) {
|
||||
this.silentStopExecution(id, true).then(() => {
|
||||
this._client.delMoreNodes([id]);
|
||||
this._client.completeTransaction();
|
||||
});
|
||||
} else {
|
||||
this._client.delMoreNodes([id]);
|
||||
this._client.completeTransaction();
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.updateThumbnail = function (svg) {
|
||||
var node = this._client.getNode(this._currentNodeId),
|
||||
name,
|
||||
@@ -641,7 +683,19 @@ define([
|
||||
} else {
|
||||
return EasyDAGControl.prototype._getValidTargetsFor.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorControl.prototype.isArchitecturePtr = function (id, ptr) {
|
||||
var ptrMeta = this._client.getPointerMeta(id, ptr),
|
||||
targets;
|
||||
|
||||
// Check if ptr of the given id is referencing an architecture
|
||||
if (ptrMeta.items) {
|
||||
targets = ptrMeta.items.map(item => this._client.getNode(item.id));
|
||||
return !!targets.find(node => node.getAttribute('name') === 'Architecture');
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
return PipelineEditorControl;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*globals define, $, _, WebGMEGlobal*/
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* Generated by VisualizerGenerator 1.7.0 from webgme on Thu May 19 2016 14:04:47 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
define(['js/PanelBase/PanelBaseWithHeader',
|
||||
define([
|
||||
'js/PanelBase/PanelBaseWithHeader',
|
||||
'js/PanelManager/IActivePanel',
|
||||
'widgets/PipelineEditor/PipelineEditorWidget',
|
||||
'./PipelineEditorControl'
|
||||
], function (PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
PipelineEditorWidget,
|
||||
PipelineEditorControl) {
|
||||
], function (
|
||||
PanelBaseWithHeader,
|
||||
IActivePanel,
|
||||
PipelineEditorWidget,
|
||||
PipelineEditorControl
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var PipelineEditorPanel;
|
||||
@@ -62,7 +62,7 @@ define(['js/PanelBase/PanelBaseWithHeader',
|
||||
});
|
||||
|
||||
// Editable pipeline name
|
||||
this.$panelHeaderTitle.on('dblclick', () => this.editTitle());
|
||||
this.$panelHeaderTitle.on('click', () => this.editTitle());
|
||||
|
||||
this.onActivate();
|
||||
};
|
||||
|
||||
@@ -33,12 +33,33 @@ define([
|
||||
this._widget.deletePipeline = id => {
|
||||
var node = this._client.getNode(id),
|
||||
name = node.getAttribute('name'),
|
||||
msg = `Deleting pipeline "${name}"`;
|
||||
msg = `Deleting pipeline "${name}"`,
|
||||
delTerritory = {},
|
||||
delUI,
|
||||
ids = [id];
|
||||
|
||||
// Change the current active object
|
||||
this._client.startTransaction(msg);
|
||||
this._client.delMoreNodes([id]);
|
||||
this._client.completeTransaction();
|
||||
// Delete all associated executions
|
||||
ids = node.getMemberIds('executions');
|
||||
for (var i = ids.length; i--;) {
|
||||
delTerritory[ids[i]] = {children: 0};
|
||||
}
|
||||
|
||||
delUI = this._client.addUI(this, events => {
|
||||
var ids = [id];
|
||||
|
||||
for (i = events.length; i--;) {
|
||||
if (events[i].eid && events[i].etype === CONSTANTS.TERRITORY_EVENT_LOAD) {
|
||||
ids.push(events[i].eid);
|
||||
}
|
||||
}
|
||||
|
||||
this._client.startTransaction(msg);
|
||||
this._client.delMoreNodes(ids);
|
||||
this._client.completeTransaction();
|
||||
|
||||
this._client.removeUI(delUI);
|
||||
});
|
||||
this._client.updateTerritory(delUI, delTerritory);
|
||||
};
|
||||
|
||||
this._widget.setName = (id, name) => {
|
||||
|
||||
@@ -47,8 +47,18 @@ define([
|
||||
this._widget.setName = this.setName.bind(this);
|
||||
};
|
||||
|
||||
TextEditorControl.prototype.saveTextFor = function (id, text) {
|
||||
TextEditorControl.prototype.saveTextFor = function (id, text, inTransaction) {
|
||||
var node = this._client.getNode(this._currentNodeId),
|
||||
name = node.getAttribute('name'),
|
||||
msg = `Updating ${this.ATTRIBUTE_NAME} of ${name} (${id})`;
|
||||
|
||||
if (!inTransaction) {
|
||||
this._client.startTransaction(msg);
|
||||
}
|
||||
this._client.setAttributes(id, this.ATTRIBUTE_NAME, text);
|
||||
if (!inTransaction) {
|
||||
this._client.completeTransaction();
|
||||
}
|
||||
};
|
||||
|
||||
TextEditorControl.prototype.setName = function (name) {
|
||||
@@ -125,6 +135,7 @@ define([
|
||||
desc.name = nodeObj.getAttribute(nodePropertyNames.Attributes.name);
|
||||
desc.parentId = nodeObj.getParentId(); // used by the 'up' button in the toolbar
|
||||
desc.text = nodeObj.getAttribute(this.ATTRIBUTE_NAME);
|
||||
desc.ownText = nodeObj.getOwnAttribute(this.ATTRIBUTE_NAME);
|
||||
}
|
||||
|
||||
return desc;
|
||||
|
||||
@@ -25,6 +25,7 @@ define([
|
||||
_.extend(DeserializeEditorWidget.prototype, SerializeEditorWidget.prototype);
|
||||
|
||||
DeserializeEditorWidget.prototype.getHeader = function(desc) {
|
||||
this._name = desc.name;
|
||||
return [
|
||||
`-- The deserialization function for ${desc.name}`,
|
||||
'-- Globals:',
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<td>Name</td>
|
||||
<td>Creation Date</td>
|
||||
<td>Origin Pipeline</td>
|
||||
<td>Duration</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="execs-content">
|
||||
|
||||
@@ -23,6 +23,7 @@ define([
|
||||
|
||||
this.nodes = {};
|
||||
this.graphs = {};
|
||||
this.checkedIds = [];
|
||||
this._initialize();
|
||||
|
||||
this._logger.debug('ctor finished');
|
||||
@@ -97,6 +98,8 @@ define([
|
||||
|
||||
// Adding/Removing/Updating items
|
||||
ExecutionIndexWidget.prototype.addNode = function (desc) {
|
||||
var isFirstNode = Object.keys(this.nodes).length === 0;
|
||||
|
||||
if (desc.type === 'Execution') {
|
||||
// Add node to a table of nodes
|
||||
this.addExecLine(desc);
|
||||
@@ -105,6 +108,10 @@ define([
|
||||
desc.type = 'line';
|
||||
this.lineGraph.addNode(desc);
|
||||
}
|
||||
|
||||
if (isFirstNode) {
|
||||
this.updateTimes();
|
||||
}
|
||||
};
|
||||
|
||||
ExecutionIndexWidget.prototype.updatePipelineName = function (execId, name) {
|
||||
@@ -120,6 +127,7 @@ define([
|
||||
fields,
|
||||
pipeline,
|
||||
name,
|
||||
duration = $('<div>'),
|
||||
td;
|
||||
|
||||
pipeline = $('<a>', {
|
||||
@@ -127,13 +135,15 @@ define([
|
||||
'data-id': desc.originId
|
||||
}).text(desc.pipelineName || 'view pipeline');
|
||||
|
||||
name = $('<a>', {class: 'node-nav', 'data-id': desc.id}).text(desc.name);
|
||||
name = $('<a>', {class: 'node-nav', 'data-id': desc.id})
|
||||
.text(desc.name);
|
||||
|
||||
fields = [
|
||||
checkBox,
|
||||
name,
|
||||
Utils.getDisplayTime(desc.originTime),
|
||||
pipeline
|
||||
pipeline,
|
||||
duration
|
||||
];
|
||||
|
||||
for (var i = 0; i < fields.length; i++) {
|
||||
@@ -152,11 +162,61 @@ define([
|
||||
|
||||
this.nodes[desc.id] = {
|
||||
statusClass: statusClass,
|
||||
desc: desc,
|
||||
$el: row,
|
||||
$checkbox: checkBox[0],
|
||||
$pipeline: pipeline,
|
||||
$duration: duration,
|
||||
$name: name
|
||||
};
|
||||
this.updateTime(desc.id, true);
|
||||
};
|
||||
|
||||
ExecutionIndexWidget.prototype.getDurationText = function (duration) {
|
||||
var hours,
|
||||
min,
|
||||
sec;
|
||||
|
||||
sec = duration/1000;
|
||||
hours = Math.floor(sec/3600);
|
||||
sec = sec%3600;
|
||||
min = Math.floor(sec/60);
|
||||
sec = Math.floor(sec%60);
|
||||
|
||||
return `${hours}:${min}:${sec}`;
|
||||
};
|
||||
|
||||
ExecutionIndexWidget.prototype.updateTime = function (id, force) {
|
||||
var desc = this.nodes[id].desc,
|
||||
duration = 'unknown';
|
||||
|
||||
if (desc.status === 'running') {
|
||||
if (desc.startTime) {
|
||||
duration = this.getDurationText(Date.now() - desc.startTime);
|
||||
}
|
||||
this.nodes[id].$duration.text(duration);
|
||||
return true;
|
||||
} else if (force) {
|
||||
if (desc.endTime && desc.startTime) {
|
||||
duration = this.getDurationText(desc.endTime - desc.startTime);
|
||||
}
|
||||
this.nodes[id].$duration.text(duration);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
ExecutionIndexWidget.prototype.updateTimes = function () {
|
||||
var nodeIds = Object.keys(this.nodes),
|
||||
updated = false;
|
||||
|
||||
for (var i = nodeIds.length; i--;) {
|
||||
updated = this.updateTime(nodeIds[i]) || updated;
|
||||
}
|
||||
|
||||
if (updated) { // if there are still nodes, call again!
|
||||
setTimeout(this.updateTimes.bind(this), 1000);
|
||||
}
|
||||
};
|
||||
|
||||
ExecutionIndexWidget.prototype.removeNode = function (id) {
|
||||
@@ -185,8 +245,46 @@ define([
|
||||
|
||||
};
|
||||
|
||||
ExecutionIndexWidget.prototype.toggleAbbreviations = function (show, ids) {
|
||||
var node,
|
||||
desc,
|
||||
name;
|
||||
|
||||
ids = ids || this.checkedIds;
|
||||
for (var i = ids.length; i--;) {
|
||||
node = this.nodes[ids[i]];
|
||||
desc = node.desc;
|
||||
name = show ? `${desc.name} (${desc.abbr})` : desc.name;
|
||||
node.$name.text(name);
|
||||
}
|
||||
};
|
||||
|
||||
ExecutionIndexWidget.prototype.setSelect = function (id, checked) {
|
||||
var wasChecked = this.checkedIds.length > 1,
|
||||
isChecked;
|
||||
|
||||
this.nodes[id].$checkbox.checked = checked;
|
||||
|
||||
// If multiple are checked, display the abbreviation
|
||||
if (checked) {
|
||||
this.checkedIds.push(id);
|
||||
} else {
|
||||
var k = this.checkedIds.indexOf(id);
|
||||
if (k !== -1) {
|
||||
this.checkedIds.splice(k, 1);
|
||||
}
|
||||
}
|
||||
|
||||
isChecked = this.checkedIds.length > 1;
|
||||
if (isChecked !== wasChecked) {
|
||||
this.toggleAbbreviations(isChecked);
|
||||
}
|
||||
|
||||
// Update the given node
|
||||
if (!checked || isChecked) {
|
||||
this.toggleAbbreviations(checked, [id]);
|
||||
}
|
||||
|
||||
this.setExecutionDisplayed(id, checked);
|
||||
};
|
||||
|
||||
@@ -205,6 +303,7 @@ define([
|
||||
this._logger.debug(`setting execution ${desc.id} to ${desc.status}`);
|
||||
|
||||
node.statusClass = Utils.ClassForJobStatus[desc.status];
|
||||
node.desc = desc;
|
||||
} else if (desc.type === 'line') {
|
||||
this.lineGraph.updateNode(desc);
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
define([
|
||||
'widgets/EasyDAG/SelectionManager',
|
||||
'widgets/EasyDAG/Buttons',
|
||||
'deepforge/Constants',
|
||||
'underscore'
|
||||
], function(
|
||||
EasyDAGSelectionManager,
|
||||
Buttons,
|
||||
CONSTANTS,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
@@ -18,16 +20,19 @@ define([
|
||||
_.extend(SelectionManager.prototype, EasyDAGSelectionManager.prototype);
|
||||
|
||||
SelectionManager.prototype.createActionButtons = function(width/*, height*/) {
|
||||
// Add 'watch' and 'jumpToDef' buttons
|
||||
// TODO
|
||||
new Buttons.Enter({
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
icon: 'monitor',
|
||||
x: width,
|
||||
y: 0
|
||||
});
|
||||
var jobName = this.selectedItem.desc.name;
|
||||
|
||||
// Check if it is an Input or Output job
|
||||
if (jobName !== CONSTANTS.OP.INPUT && jobName !== CONSTANTS.OP.OUTPUT) {
|
||||
new Buttons.Enter({
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
icon: 'monitor',
|
||||
x: width,
|
||||
y: 0
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return SelectionManager;
|
||||
|
||||
@@ -82,7 +82,6 @@ define([
|
||||
|
||||
ImageViewerWidget.prototype.updateImage = function (url) {
|
||||
url = url || NO_IMAGE_URL;
|
||||
this.zoom = 1;
|
||||
this.$image.attr('src', url);
|
||||
};
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ define([
|
||||
.axisLabel(this.options.xAxis);
|
||||
}
|
||||
|
||||
chart.yAxis.tickFormat(d3.format('.02f'));
|
||||
if (this.options.yAxis) {
|
||||
chart.yAxis
|
||||
.axisLabel(this.options.yAxis);
|
||||
@@ -68,7 +69,9 @@ define([
|
||||
};
|
||||
|
||||
LineGraphWidget.prototype.getData = function () {
|
||||
return Object.keys(this.lineData).map(id => this.lineData[id]);
|
||||
return Object.keys(this.lineData)
|
||||
.map(id => this.lineData[id])
|
||||
.filter(data => data.values.length !== 0); // hide empty lines
|
||||
};
|
||||
|
||||
// Adding/Removing/Updating items
|
||||
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -1 +1 @@
|
||||
{"version":3,"sources":["build/nv.d3.css"],"names":[],"mappings":"AAqBA,oBAfA,oBAgBI,KAAM,KAmXN,gBAAiB,WAhFrB,kBA+DA,uBAnWA,oBAfA,oBAmYI,gBAAiB,WAmErB,UAAW,UAJX,mBAvcA,eAsbA,uBA8BA,uCACI,eAAgB,KA+DpB,WA7QA,aAoRI,QAAS,MAST,sBAAuB,KAEvB,mBAAoB,KAtiBxB,eAEI,QAAS,EAuCb,2BA4JA,0DACI,QAAS,EAjMb,oBAEI,OAAQ,KACR,eAAgB,IAIpB,2BACI,eAAgB,IAGpB,gCACI,eAAgB,EAGpB,oBAEI,OAAQ,QAIZ,0BACI,0BACA,eAAgB,IAGpB,mCACI,YAAa,IAGjB,sCACA,uCACA,uCACI,YAAa,OAOjB,oBACI,aAAc,IAEd,WAAY,aAAa,MAAM,OAC/B,gBAAiB,aAAa,MAAM,OACpC,mBAAoB,aAAa,MAAM,OAG3C,0BACI,aAAc,EAGlB,2BACI,KAAM,QAGV,oBACI,KAAM,YAGV,2BACI,KAAM,cAKV,sCAFA,mCACA,6CAEI,eAAgB,EAEhB,WAAY,aAAa,MAAM,OAC/B,gBAAiB,aAAa,MAAM,OACpC,mBAAoB,aAAa,MAAM,OAK3C,8CACA,4CAHA,yCACA,mDAGI,aAAc,EAGlB,sCACA,6CACI,YAAa,IACb,KAAM,cACN,OAAQ,YAIZ,yBACE,aAAc,GAGhB,+BAIA,6BAHE,aAAc,EAOhB,6BACE,OAAQ,KAGV,uBACE,aAAc,MAGhB,gBAAkB,KAAM,KAAK,WAC7B,4BAA8B,aAAc,GAC5C,kCAAoC,aAAc,EAClD,2BAA6B,OAAQ,KAAM,aAAc,IACzD,mCAAqC,OAAQ,KAAM,KAAM,KAAM,aAAc,MAC7E,+BAAiC,OAAQ,KAAM,aAAc,MAC7D,8BAAgC,OAAQ,KAAM,aAAc,KAC5D,gCAAkC,KAAM,KACxC,gCAAkC,KAAM,KACxC,gCAAkC,KAAM,KACxC,0BAA4B,UAAW,KAAM,YAAa,IAC1D,6BAA+B,KAAM,KAGrC,0BACI,KAAM,QACN,aAAc,GAElB,gCACI,aAAc,GAGlB,2CACI,aAAc,IAGlB,iDACI,aAAc,IAGlB,yDACI,OAAQ,QACR,KAAM,QAGV,yDACI,OAAQ,QACR,KAAM,QAGV,wDACI,WAAY,aAAa,MAAM,OAAQ,eAAe,MAAM,OAC5D,gBAAiB,aAAa,MAAM,OAAQ,eAAe,MAAM,OACjE,mBAAoB,aAAa,MAAM,OAAQ,eAAe,MAAM,OAIxE,uCACI,OAAQ,KAIZ,eACE,OAAQ,KACR,aAAc,MAEhB,eACE,OAAQ,KACR,eAAgB,GAElB,oBACE,aAAc,EAOhB,4BACI,aAAa,EACb,aAAa,EAGjB,8BACI,aAAa,EACb,aAAa,EAGjB,qDACI,aAAa,EACb,eAAe,EAQnB,kCACI,aAAc,IAGlB,wCACI,aAAc,EAElB,8BACI,KAAM,KAGV,8BACI,OAAQ,KAGZ,oDACI,aAAc,EACd,eAAgB,EAGpB,sDACI,aAAc,aACd,eAAgB,aAIpB,6CACI,WAAY,aAAa,MAAM,OAAQ,eAAe,MAAM,OAC5D,gBAAiB,aAAa,MAAM,OAAQ,eAAe,MAAM,OACjE,mBAAoB,aAAa,MAAM,OAAQ,eAAe,MAAM,OAKxE,iCADA,4CAEI,aAAc,IACd,aAAc,cACd,eAAgB,cAIpB,2BACI,OAAQ,KACR,eAAgB,EAChB,KAAM,KACN,aAAc,EAKlB,oBACI,OAAQ,UAUZ,aAEI,oBAAqB,KAErB,gBAAiB,KACjB,iBAAkB,KAClB,YAAa,KAEb,MAAM,KACN,OAAO,KAMX,0BAA2B,2BACvB,gBAAiB,EAAE,IAAI,KAAK,eAC5B,mBAAoB,EAAE,IAAI,KAAK,eAC/B,WAAY,EAAE,IAAI,KAAK,eAEvB,sBAAuB,IACvB,mBAAoB,IACpB,cAAe,IAInB,WACI,KAAM,IAAO,KAAK,MAGtB,aACI,KAAM,IAAK,KAAK,MAGpB,qBACI,KAAM,KACN,aAAc,EAGlB,gBACI,UAAW,KACX,YAAa,IAQjB,kBACI,aAAc,KAIlB,uBACI,KAAM,KACN,OAAQ,KAQZ,4BACI,OAAQ,QAGZ,qCACI,aAAc,EAIlB,wBACI,aAAc,YAGlB,+BACI,OAAQ,KACR,aAAc,GACd,KAAM,KACN,aAAc,GAOlB,aACE,WACE,aAAc,EACd,aAAc,GAIlB,oCACI,aAAc,IAGlB,0CACI,aAAc,IAGlB,6CACI,OAAQ,QAGZ,6CACI,OAAQ,QAIZ,uBACI,KAAM,KACN,OAAQ,KACR,eAAgB,GAIpB,uBACI,KAAM,KACN,eAAgB,GAGpB,4CAEI,KAAM,KACN,aAAc,GACd,OAAQ,KACR,gBAAiB,WAGrB,qCACI,aAAc,EACjB,aAAc,IAIf,8BACE,KAAM,KACN,OAAQ,KACR,aAAc,EACd,eAAgB,EAChB,iBAAkB,EAAG,EAUvB,2BACI,UAAW,KACX,KAAM,qBAGV,4BACI,OAAQ,KACR,aAAc,EAGlB,kBAhBI,WAAY,aAAa,MAAM,OAAQ,aAAa,MAAM,OAAQ,eAAe,MAAM,OACvF,gBAAiB,aAAa,MAAM,OAAQ,aAAa,MAAM,OAAQ,eAAe,MAAM,OAC5F,mBAAoB,aAAa,MAAM,OAAQ,aAAa,MAAM,OAAQ,eAAe,MAAM,OAe/F,OAAQ,KACR,aAAc,IACd,eAAgB,EAIhB,aAAc,GAElB,yBACI,aAAc,EAKlB,4BACI,aAAc,EACd,eAAgB,EAIpB,iCACI,aAAc,KACd,eAAgB,GAGpB,kCACI,aAAc,EAWlB,wBACI,KAAM,KAOV,2CACI,OAAQ,KACR,aAAc,MAGlB,uBACA,yBACI,eAAgB,IA4LpB,+BAvIA,WAwII,eAAe,KA1LnB,oBACI,aAAc,EACd,eAAgB,EAGpB,kCACA,kCACI,aAAc,EACd,UAAW,KACX,YAAa,IAGjB,kCACI,OAAQ,KAGZ,oCACI,OAAQ,QACR,KAAM,QAGV,oCACI,OAAQ,QACR,KAAM,QAGV,wCACI,YAAa,IACb,UAAW,MAsEf,cAsCA,wBACI,YAAa,IA1GjB,kCACI,aAAc,GACd,eAAgB,EAChB,WAAY,aAAa,MAAM,OAAQ,eAAe,MAAM,OAC5D,gBAAiB,aAAa,MAAM,OAAQ,eAAe,MAAM,OACjE,mBAAoB,aAAa,MAAM,OAAQ,eAAe,MAAM,OAGxE,wCACI,aAAc,GAIlB,0CACI,eAAgB,EAChB,aAAc,EAIlB,WACI,SAAU,SAEV,MAAO,cACP,QAAS,IAET,QAAS,MAGT,YAAa,MACb,UAAW,KACX,WAAY,KAGZ,YAAa,OAGb,oBAAqB,KAErB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KAIb,WAAY,qBACZ,OAAQ,IAAI,MAAM,eAClB,cAAe,IAqBnB,cAgBA,aACI,OAAQ,EAER,WAAY,OAlChB,4BAA6B,6BACzB,WAAY,QAAQ,KAAK,OACzB,gBAAiB,QAAQ,KAAK,OAC9B,mBAAoB,QAAQ,KAAK,OAEjC,iBAAkB,MAClB,sBAAuB,MACvB,yBAA0B,MAG9B,uBACA,uBACI,QAAS,IAGb,cAEI,QAAS,IAAI,KACb,YAAa,KAEb,iBAAkB,sBAClB,MAAO,cAGP,cAAe,IAAI,MAAM,QAEzB,sBAAuB,IAAI,IAAI,EAAE,EACjC,mBAAoB,IAAI,IAAI,EAAE,EAC9B,cAAe,IAAI,IAAI,EAAE,EAG7B,aAEI,QAAS,IAAI,KAIjB,gBACI,QAAS,aACT,OAAQ,IAAI,EAGhB,iBACI,OAAQ,IACR,eAAe,EAInB,oBACI,QAAS,IAAI,IAAI,IAAI,EACrB,eAAgB,OAMpB,8BACI,YAAa,IAEjB,0BACI,WAAY,MACZ,YAAa,IAGjB,4BACI,MAAO,QAGX,iCACI,QAAS,IAAI,IAAI,IAAI,EACrB,oBAAqB,MACrB,oBAAqB,IACrB,iBAAkB,MAClB,iBAAkB,IAGtB,2CAGI,eAAgB,OAIhB,MAAO,KACP,OAAQ,KACR,OAAQ,IAAI,MAAM,KAGtB,mBACI,QAAS,IACT,WAAY,OAGhB,2BACI,eAAgB,KAChB,QAAS,KAUb,wBACI,OAAQ"}
|
||||
{"version":3,"sources":["build/nv.d3.css"],"names":[],"mappings":"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"}
|
||||
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -27,6 +27,8 @@ define([
|
||||
this._el.addClass('log-viewer');
|
||||
this.editor.setTheme('ace/theme/twilight');
|
||||
this.editor.setShowPrintMargin(false);
|
||||
this.editor.renderer.setScrollMargin(0, 75);
|
||||
this.addKeyListeners();
|
||||
|
||||
// Override the textlayer to add support for ansi colors
|
||||
this.customizeAce();
|
||||
@@ -34,6 +36,24 @@ define([
|
||||
|
||||
_.extend(LogViewerWidget.prototype, TextEditorWidget.prototype);
|
||||
|
||||
LogViewerWidget.prototype.addKeyListeners = function() {
|
||||
// Need to add key listeners to the container itself since ace is in read-only mode
|
||||
this._el.on('keydown', event => {
|
||||
// ctrl-alt-pagedown -> EOF
|
||||
if (event.key === 'PageDown' && event.altKey && (event.ctrlKey || event.metaKey)) {
|
||||
this.editor.gotoLine(Infinity);
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
// ctrl-alt-pagedown -> beginning of file
|
||||
if (event.key === 'PageUp' && event.altKey && (event.ctrlKey || event.metaKey)) {
|
||||
this.editor.gotoLine(0);
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
LogViewerWidget.prototype.getHeader = function(desc) {
|
||||
return `Console logging for Operation "${desc.name}":\n`;
|
||||
};
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'panel/FloatingActionButton/styles/Materialize',
|
||||
'deepforge/globals',
|
||||
'text!./NavBar.html',
|
||||
'text!./ListItem.ejs',
|
||||
'underscore',
|
||||
'css!./styles/MainViewWidget.css'
|
||||
], function (
|
||||
Materialize,
|
||||
DeepForge,
|
||||
NavBarHTML,
|
||||
ListItem,
|
||||
@@ -24,12 +26,12 @@ define([
|
||||
];
|
||||
|
||||
MainViewWidget = function (logger, container) {
|
||||
this._logger = logger.fork('Widget');
|
||||
this.logger = logger.fork('Widget');
|
||||
this.$el = container;
|
||||
this.$el.addClass(WIDGET_CLASS);
|
||||
this.toggleIndex = 0;
|
||||
this.initialize();
|
||||
this._logger.debug('ctor finished');
|
||||
this.logger.debug('ctor finished');
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.initialize = function () {
|
||||
@@ -66,6 +68,51 @@ define([
|
||||
this.$nav.on('click', '.dl-node', this.onDownloadNodeClick.bind(this));
|
||||
|
||||
this.htmlFor = {};
|
||||
|
||||
setTimeout(() => this.checkLibraries(), 100);
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.checkLibraries = function () {
|
||||
|
||||
this.checkLibUpdates()
|
||||
.then(updates => {
|
||||
if (updates.length) { // prompt about updates
|
||||
var names = updates.map(update => update[0]),
|
||||
projName = this.getProjectName(),
|
||||
content = $('<span>'),
|
||||
msg = `${projName} is out of date. Click to update.`;
|
||||
|
||||
this.logger.info(`Updates available for ${names.join(', ')}`);
|
||||
|
||||
if (names.indexOf('nn') !== -1) {
|
||||
msg = 'Newer nn library available. Click to update';
|
||||
} else if (names.indexOf('pipeline') !== -1) {
|
||||
msg = 'Execution updates available. Click to update';
|
||||
}
|
||||
|
||||
content.text(msg);
|
||||
content.on('click', () => {
|
||||
// Remove the toast
|
||||
content.parent().fadeOut();
|
||||
|
||||
// Create updating notification
|
||||
msg = 'Updating execution library...';
|
||||
if (names.indexOf('nn') !== -1) {
|
||||
msg = 'Updating nn library...';
|
||||
}
|
||||
|
||||
content.text(msg);
|
||||
Materialize.toast(content, 8000);
|
||||
this.updateLibraries(updates).then(() => {
|
||||
content.parent().remove();
|
||||
Materialize.toast('Update complete!', 2000);
|
||||
});
|
||||
});
|
||||
|
||||
Materialize.toast(content, 8000);
|
||||
}
|
||||
})
|
||||
.fail(err => Materialize.toast(`Library update check failed: ${err}`, 2000));
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.width = function () {
|
||||
@@ -189,11 +236,11 @@ define([
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.onActivate = function () {
|
||||
this._logger.debug('MainViewWidget has been activated');
|
||||
this.logger.debug('MainViewWidget has been activated');
|
||||
};
|
||||
|
||||
MainViewWidget.prototype.onDeactivate = function () {
|
||||
this._logger.debug('MainViewWidget has been deactivated');
|
||||
this.logger.debug('MainViewWidget has been deactivated');
|
||||
};
|
||||
|
||||
return MainViewWidget;
|
||||
|
||||
@@ -17,6 +17,15 @@ define([
|
||||
OperationCodeEditorWidget = function (logger, container) {
|
||||
TextEditorWidget.call(this, logger, container);
|
||||
this.lineOffset = 0;
|
||||
// Add the shift-enter command
|
||||
this.editor.commands.addCommand({
|
||||
name: 'executeOrStopJob',
|
||||
bindKey: {
|
||||
mac: 'Shift-Enter',
|
||||
win: 'Shift-Enter'
|
||||
},
|
||||
exec: () => this.executeOrStopJob()
|
||||
});
|
||||
};
|
||||
|
||||
_.extend(OperationCodeEditorWidget.prototype, TextEditorWidget.prototype);
|
||||
@@ -25,7 +34,6 @@ define([
|
||||
// Add comment about the inputs, attributes and references
|
||||
var inputs = desc.inputs.map(pair => `-- ${pair[0]} (${pair[1]})`).join('\n'),
|
||||
refs = desc.references.map(name => `-- ${name}`).join('\n'),
|
||||
outputs,
|
||||
header = [
|
||||
`-- Editing "${desc.name}" Implementation`
|
||||
];
|
||||
@@ -41,22 +49,28 @@ define([
|
||||
header.push('--');
|
||||
header.push('-- The following will be executed when the operation is run:');
|
||||
|
||||
// Add info about outputs
|
||||
outputs = desc.outputs.map(pair => `-- ${pair[0]} = <${pair[1]}>`)
|
||||
.join('\n');
|
||||
|
||||
if (outputs.length) {
|
||||
header.push('-- Returning something like:');
|
||||
header.push('-- {');
|
||||
header.push(outputs);
|
||||
header.push('-- }');
|
||||
}
|
||||
|
||||
return header.join('\n');
|
||||
};
|
||||
|
||||
OperationCodeEditorWidget.prototype.addNode = function () {
|
||||
TextEditorWidget.prototype.addNode.apply(this, arguments);
|
||||
OperationCodeEditorWidget.prototype.canAddReturnTmpl = function (desc) {
|
||||
return desc.outputs.length &&
|
||||
(!desc.ownText || desc.ownText.indexOf('return') === -1);
|
||||
};
|
||||
|
||||
OperationCodeEditorWidget.prototype.updateText = function (desc) {
|
||||
if (this.canAddReturnTmpl(desc)) {
|
||||
// Add the return template
|
||||
desc.text += '\n\nreturn {\n' +
|
||||
desc.outputs.map((pair, i) =>
|
||||
` ${pair[0]} = nil${i === desc.outputs.length-1 ? '' : ','} -- ${pair[1]}`).join('\n') +
|
||||
'\n}';
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
OperationCodeEditorWidget.prototype.addNode = function (desc) {
|
||||
this.updateText(desc);
|
||||
TextEditorWidget.prototype.addNode.call(this, desc);
|
||||
this.updateOffset();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*globals define */
|
||||
/*globals define*/
|
||||
define([
|
||||
'widgets/EasyDAG/DAGItem',
|
||||
'underscore'
|
||||
@@ -13,6 +13,7 @@ define([
|
||||
// Show the warnings
|
||||
this.$warning = null;
|
||||
this.updateWarnings();
|
||||
|
||||
};
|
||||
|
||||
_.extend(Item.prototype, DAGItem.prototype);
|
||||
@@ -29,38 +30,55 @@ define([
|
||||
if (this.desc.used === false) {
|
||||
this.warn(msg, isInput ? 'bottom' : 'top');
|
||||
} else {
|
||||
this.clearWarning();
|
||||
this.clearNotification('$warning');
|
||||
}
|
||||
|
||||
if (this.desc.isUnknown) { // ptrs only
|
||||
this.error('Unknown type! Click to set', 'bottom');
|
||||
} else if (this.$error) {
|
||||
// Set the baseName tooltip, if needed
|
||||
this.clearNotification('$error');
|
||||
this.decorator.enableTooltip(this.desc.baseName, 'dark');
|
||||
}
|
||||
};
|
||||
|
||||
Item.prototype.warn = function(message, tipJoint) {
|
||||
// Create a temporary div over the given svg element
|
||||
if (this.$warning) {
|
||||
this.clearWarning();
|
||||
}
|
||||
this.notify(message, '$warning', '#ffeb3b', 'standard', tipJoint);
|
||||
};
|
||||
|
||||
this.decorator.highlight('#ffeb3b');
|
||||
this.$warning = this.createTooltip(message, {
|
||||
Item.prototype.error = function(message, tipJoint) {
|
||||
this.notify(message, '$error', '#ef5350', 'alert', tipJoint);
|
||||
};
|
||||
|
||||
Item.prototype.notify = function(message, varname, color, style, tipJoint) {
|
||||
this.clearNotification(varname);
|
||||
|
||||
this.decorator.highlight(color);
|
||||
this[varname] = this.createTooltip(message, {
|
||||
showIf: () => !this.isSelected(),
|
||||
tipJoint: tipJoint,
|
||||
style: 'standard'
|
||||
style: style
|
||||
});
|
||||
};
|
||||
|
||||
Item.prototype.clearWarning = function() {
|
||||
if (this.$warning) {
|
||||
this.destroyTooltip(this.$warning);
|
||||
this.$warning = null;
|
||||
Item.prototype.clearNotification = function(varname) {
|
||||
if (this[varname]) {
|
||||
this.destroyTooltip(this[varname]);
|
||||
this[varname] = null;
|
||||
}
|
||||
this.decorator.unHighlight();
|
||||
};
|
||||
|
||||
|
||||
Item.prototype.onSelect = function() {
|
||||
DAGItem.prototype.onSelect.call(this);
|
||||
if (this.$warning) {
|
||||
this.$warning.hide();
|
||||
}
|
||||
|
||||
// Add click listener to set type
|
||||
if (this.desc.isUnknown) {
|
||||
this.onSetRefClicked(this.desc.name);
|
||||
}
|
||||
};
|
||||
|
||||
Item.prototype.setupDecoratorCallbacks = function() {
|
||||
|
||||
+20
-1
@@ -37,7 +37,7 @@ define([
|
||||
EasyDAG.prototype.setupItemCallbacks.call(this);
|
||||
// Add ptr rename callback
|
||||
this.ItemClass.prototype.changePtrName = (from, to) => this.changePtrName(from, to);
|
||||
|
||||
this.ItemClass.prototype.onSetRefClicked = OperationInterfaceEditorWidget.prototype.onSetRefClicked.bind(this);
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.onAddItemSelected = function(selected, isInput) {
|
||||
@@ -77,6 +77,25 @@ define([
|
||||
this.active = true; // keep refreshing the screen -> it is always visible
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.onSetRefClicked = function(name) {
|
||||
var refs = this.allValidReferences();
|
||||
|
||||
// Get all valid references
|
||||
if (refs.length > 1) {
|
||||
// Create the modal view with all possible subsequent nodes
|
||||
var dialog = new AddNodeDialog();
|
||||
|
||||
dialog.show(null, refs);
|
||||
dialog.onSelect = selected => {
|
||||
if (selected) {
|
||||
this.setRefType(name, selected.node.id);
|
||||
}
|
||||
};
|
||||
} else if (refs[0]) {
|
||||
this.setRefType(name, refs[0].node.id);
|
||||
}
|
||||
};
|
||||
|
||||
OperationInterfaceEditorWidget.prototype.onAddRefClicked = function() {
|
||||
var refs = this.allValidReferences();
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'deepforge/Constants',
|
||||
'widgets/EasyDAG/AddNodeDialog',
|
||||
'widgets/EasyDAG/EasyDAGWidget',
|
||||
'deepforge/viz/PipelineControl',
|
||||
@@ -13,6 +14,7 @@ define([
|
||||
'underscore',
|
||||
'css!./styles/PipelineEditorWidget.css'
|
||||
], function (
|
||||
CONSTANTS,
|
||||
AddNodeDialog,
|
||||
EasyDAGWidget,
|
||||
PipelineControl,
|
||||
@@ -32,8 +34,7 @@ define([
|
||||
STATE = {
|
||||
DEFAULT: 'default',
|
||||
CONNECTING: 'connecting'
|
||||
},
|
||||
UPLOAD_ARTIFACT_ID = '__UPLOAD_ARTIFACT__';
|
||||
};
|
||||
|
||||
PipelineEditorWidget = function (logger, container, execCntr) {
|
||||
EasyDAGWidget.call(this, logger, container);
|
||||
@@ -44,6 +45,7 @@ define([
|
||||
this._connForPort = {};
|
||||
this._itemsShowingPorts = [];
|
||||
|
||||
this.updateExecutions = _.debounce(this._updateExecutions, 50);
|
||||
this.initExecs(execCntr);
|
||||
};
|
||||
|
||||
@@ -283,7 +285,7 @@ define([
|
||||
this.updateExecutions();
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.updateExecutions = function() {
|
||||
PipelineEditorWidget.prototype._updateExecutions = function() {
|
||||
var keys = Object.keys(this.executions),
|
||||
hasExecutions = !!keys.length,
|
||||
msg = `${keys.length || 'No'} Associated Execution` +
|
||||
@@ -325,7 +327,7 @@ define([
|
||||
() => WebGMEGlobal.State.registerActiveObject(exec.id));
|
||||
|
||||
// Add the remove icon
|
||||
rmIcon.on('click', () => this.deleteNode(exec.id));
|
||||
rmIcon.on('click', () => this.deleteExecution(exec.id));
|
||||
row.append(title, timestamp, rmIcon);
|
||||
row[0].className = className;
|
||||
return row;
|
||||
@@ -338,36 +340,55 @@ define([
|
||||
|
||||
////////////////////////// Action Overrides //////////////////////////
|
||||
PipelineEditorWidget.prototype.selectTargetFor = function(itemId) {
|
||||
// If it is an 'ArtifactLoader', then we will need to add 'upload artifact'
|
||||
// If it is an input operation, then we will need to add 'upload artifact'
|
||||
// options
|
||||
if (this.items[itemId].desc.baseName === 'ArtifactLoader') {
|
||||
this.selectTargetForLoader.apply(this, arguments);
|
||||
if (this.items[itemId].desc.baseName === CONSTANTS.OP.INPUT) {
|
||||
return this.selectTargetForLoader.apply(this, arguments);
|
||||
} else if (this.isArchitecturePtr.apply(this, arguments)) {
|
||||
// Create new architecture from the "set ptr" dialog
|
||||
return this.selectArchitectureTarget.apply(this, arguments);
|
||||
} else {
|
||||
return EasyDAGWidget.prototype.selectTargetFor.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.selectTargetForLoader = function(itemId, ptr, filter) {
|
||||
var validTargets = this.getValidTargetsFor(itemId, ptr, filter),
|
||||
nodeId = validTargets.length ? validTargets[0].node.id : null,
|
||||
uploadNode;
|
||||
PipelineEditorWidget.prototype.addCreationNode = function(name, targets) {
|
||||
var nodeId = targets.length ? targets[0].node.id : null,
|
||||
creationNode;
|
||||
|
||||
// Add the 'Upload Artifact' option
|
||||
uploadNode = {
|
||||
creationNode = {
|
||||
node: {
|
||||
id: UPLOAD_ARTIFACT_ID,
|
||||
name: 'Upload Artifact',
|
||||
id: `creation-node-${name}`,
|
||||
name: name,
|
||||
class: 'create-node',
|
||||
attributes: {},
|
||||
Decorator: this.getDecorator(nodeId)
|
||||
}
|
||||
};
|
||||
validTargets.push(uploadNode);
|
||||
|
||||
targets.push(creationNode);
|
||||
return creationNode.node.id;
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.selectArchitectureTarget = function(itemId, ptr, filter) {
|
||||
return this.selectTargetWithCreationNode('New Architecture',
|
||||
DeepForge.create.Architecture, itemId, ptr, filter);
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.selectTargetForLoader = function(itemId, ptr, filter) {
|
||||
return this.selectTargetWithCreationNode('Upload Artifact',
|
||||
DeepForge.create.Artifact, itemId, ptr, filter);
|
||||
};
|
||||
|
||||
PipelineEditorWidget.prototype.selectTargetWithCreationNode = function(name, fn, itemId, ptr, filter) {
|
||||
var validTargets = this.getValidTargetsFor(itemId, ptr, filter),
|
||||
creationNodeId = this.addCreationNode(name, validTargets);
|
||||
|
||||
// Add the 'Upload Artifact' option
|
||||
AddNodeDialog.prompt(validTargets)
|
||||
.then(selected => {
|
||||
if (selected.node.id === UPLOAD_ARTIFACT_ID) {
|
||||
DeepForge.create.Artifact();
|
||||
if (selected.node.id === creationNodeId) {
|
||||
fn();
|
||||
} else {
|
||||
var item = this.items[itemId];
|
||||
if (item.decorator.savePointer) {
|
||||
|
||||
@@ -44,7 +44,7 @@ define([
|
||||
this.deletePipeline(id);
|
||||
});
|
||||
|
||||
this.$el.on('dblclick', '.pipeline-name', event => {
|
||||
this.$el.on('click', '.pipeline-name', event => {
|
||||
var html = $(event.target),
|
||||
id = html.data('id');
|
||||
|
||||
|
||||
@@ -34,9 +34,11 @@ define([
|
||||
this.editor.$blockScrolling = Infinity;
|
||||
this.DELAY = 750;
|
||||
this.silent = false;
|
||||
this.saving = false;
|
||||
|
||||
this.editor.on('change', () => {
|
||||
if (!this.silent) {
|
||||
this.saving = true;
|
||||
this.onChange();
|
||||
}
|
||||
});
|
||||
@@ -107,11 +109,13 @@ define([
|
||||
TextEditorWidget.prototype.saveText = function () {
|
||||
var text;
|
||||
|
||||
this.saving = false;
|
||||
if (this.readOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
text = this.editor.getValue().replace(this.currentHeader + '\n', '');
|
||||
text = this.editor.getValue()
|
||||
.replace(this.currentHeader + '\n', '');
|
||||
if (typeof this.activeNode === 'string') {
|
||||
this.saveTextFor(this.activeNode, text);
|
||||
} else {
|
||||
@@ -127,20 +131,17 @@ define([
|
||||
};
|
||||
|
||||
TextEditorWidget.prototype.updateNode = function (desc) {
|
||||
var shouldUpdate = this.readOnly ||
|
||||
(!this.saving && !this.editor.isFocused()) ||
|
||||
(this.activeNode === desc.id && this.getHeader(desc) !== this.currentHeader);
|
||||
|
||||
// Check for header changes
|
||||
if (this.readOnly) {
|
||||
this.addNode(desc);
|
||||
} else if (this.activeNode === desc.id &&
|
||||
this.getHeader(desc) !== this.currentHeader) {
|
||||
if (shouldUpdate) {
|
||||
this.addNode(desc);
|
||||
}
|
||||
// TODO: Handle concurrent editing... Currently, last save wins and there are no
|
||||
// updates after opening the node. Supporting multiple users editing the same
|
||||
// operation/layer is important but more work than it is worth for now
|
||||
//var currentText = this.editor.getValue().replace(this.currentHeader, '');
|
||||
//if (this.activeNode === desc.id && desc.text !== currentText) {
|
||||
//this.addNode(desc);
|
||||
//}
|
||||
};
|
||||
|
||||
/* * * * * * * * Visualizer life cycle callbacks * * * * * * * */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"deepforge": [
|
||||
"Graph",
|
||||
"initialize",
|
||||
"image"
|
||||
],
|
||||
"torch": [
|
||||
|
||||
+38
-28
@@ -12,8 +12,7 @@ var callRegister = {
|
||||
|
||||
var mocks = {
|
||||
childProcess: {},
|
||||
rimraf: {},
|
||||
forever: {}
|
||||
rimraf: {}
|
||||
};
|
||||
|
||||
var childProcess = {
|
||||
@@ -23,6 +22,14 @@ var childProcess = {
|
||||
return mocks.childProcess.execSync.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
spawnSync: function(cmd) {
|
||||
if (cmd === 'luarocks') {
|
||||
return {
|
||||
stdout: 'rnn'
|
||||
};
|
||||
}
|
||||
return {};
|
||||
},
|
||||
spawn: function() {
|
||||
if (mocks.childProcess.spawn) {
|
||||
mocks.childProcess.spawn.apply(this, arguments);
|
||||
@@ -38,16 +45,6 @@ var childProcess = {
|
||||
};
|
||||
}
|
||||
};
|
||||
var forever = {};
|
||||
forever.Monitor = function() {
|
||||
var res = {};
|
||||
res.on = nop;
|
||||
res.start = nop;
|
||||
if (mocks.forever.Monitor) {
|
||||
mocks.forever.Monitor.apply(this, arguments);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
var rimraf = {};
|
||||
rimraf.sync = function() {
|
||||
if (mocks.rimraf.sync) {
|
||||
@@ -63,8 +60,9 @@ describe('cli', function() {
|
||||
warnOnUnregistered: false
|
||||
});
|
||||
mockery.registerMock('child_process', childProcess);
|
||||
mockery.registerMock('forever-monitor', forever);
|
||||
mockery.registerMock('rimraf', rimraf);
|
||||
// Clear node's cache
|
||||
delete require.cache[require.resolve('../../bin/deepforge')];
|
||||
cli = require('../../bin/deepforge');
|
||||
});
|
||||
|
||||
@@ -75,10 +73,11 @@ describe('cli', function() {
|
||||
describe('start', function() {
|
||||
afterEach(function() {
|
||||
callRegister.childProcess.execSync = [];
|
||||
mocks.childProcess.execSync = nop;
|
||||
mocks.childProcess.spawn = nop;
|
||||
mocks.forever.Monitor = nop;
|
||||
mocks.childProcess.execSync = () => '123';
|
||||
mocks.rimraf.sync = nop;
|
||||
delete require.cache[require.resolve('../../bin/deepforge')];
|
||||
cli = require('../../bin/deepforge');
|
||||
});
|
||||
|
||||
it('should check for running mongo', function() {
|
||||
@@ -113,21 +112,29 @@ describe('cli', function() {
|
||||
cli('start --mongo');
|
||||
});
|
||||
|
||||
it('should start local deepforge by default', function() {
|
||||
mocks.forever.Monitor = main =>
|
||||
assert.notEqual(main.indexOf('start-local.js'), -1);
|
||||
it('should start local deepforge by default', function(done) {
|
||||
mocks.childProcess.spawn = (main, args) => {
|
||||
if (main === 'node') {
|
||||
assert.notEqual(args[0].indexOf('start-local.js'), -1);
|
||||
done();
|
||||
}
|
||||
};
|
||||
cli('start');
|
||||
});
|
||||
|
||||
it('should start normal deepforge if --server set', function() {
|
||||
mocks.forever.Monitor = main =>
|
||||
assert.notEqual(main.indexOf('app.js'), -1);
|
||||
it('should start normal deepforge if --server set', function(done) {
|
||||
mocks.childProcess.spawn = (main, args) => {
|
||||
if (main === 'node') {
|
||||
assert.notEqual(args[0].indexOf('app.js'), -1);
|
||||
done();
|
||||
}
|
||||
};
|
||||
cli('start --server');
|
||||
});
|
||||
|
||||
it('should start worker if --worker set', function(done) {
|
||||
mocks.forever.Monitor = main => {
|
||||
if (main.indexOf('start-worker.js') !== -1) {
|
||||
mocks.childProcess.spawn = (main, args) => {
|
||||
if (args[0].indexOf('start-worker.js') !== -1) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
@@ -163,17 +170,20 @@ describe('cli', function() {
|
||||
describe('update', function() {
|
||||
it('should update deepforge w/ npm', function() {
|
||||
mocks.childProcess.spawn = (cmd, args) => {
|
||||
assert.equal(cmd, 'npm');
|
||||
assert.equal(args[0], 'install');
|
||||
assert.notEqual(args.indexOf('deepforge'), -1);
|
||||
assert.notEqual(args.indexOf('-g'), -1);
|
||||
if (cmd === 'npm') {
|
||||
assert.equal(args[0], 'install');
|
||||
assert.notEqual(args.indexOf('deepforge'), -1);
|
||||
assert.notEqual(args.indexOf('-g'), -1);
|
||||
}
|
||||
};
|
||||
cli('update');
|
||||
});
|
||||
|
||||
it('should update deepforge from git if --git set w/ npm', function() {
|
||||
mocks.childProcess.spawn = (cmd, args) => {
|
||||
assert.notEqual(args.indexOf('dfst/deepforge'), -1);
|
||||
if (cmd === 'npm') {
|
||||
assert.notEqual(args.indexOf('dfst/deepforge'), -1);
|
||||
}
|
||||
};
|
||||
cli('update --git');
|
||||
});
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
var testFixture = require('../globals'),
|
||||
expect = testFixture.expect,
|
||||
assert = require('assert'),
|
||||
path = testFixture.path,
|
||||
gmeConfig = testFixture.getGmeConfig(),
|
||||
blobDir = gmeConfig.blob.fsDir,
|
||||
server = testFixture.WebGME.standaloneServer(gmeConfig),
|
||||
Logger = require('webgme/src/server/logger'),
|
||||
logger = Logger.createWithGmeConfig('gme', gmeConfig, true),
|
||||
JobLogsClient = testFixture.requirejs('deepforge/JobLogsClient'),
|
||||
rm_rf = require('rimraf'),
|
||||
exists = require('exists-file');
|
||||
|
||||
describe('JobLogsClient', function() {
|
||||
var logClient = new JobLogsClient({
|
||||
logger: logger,
|
||||
origin: server.getUrl(),
|
||||
projectId: 'testProject',
|
||||
branchName: 'master'
|
||||
}),
|
||||
jobId = '/4/q/l',
|
||||
firstLog = 'hello world';
|
||||
|
||||
before(function(done) {
|
||||
testFixture.mkdir(blobDir);
|
||||
server.start(done);
|
||||
});
|
||||
|
||||
after(function(done) {
|
||||
rm_rf.sync(blobDir);
|
||||
server.stop(done);
|
||||
});
|
||||
|
||||
describe('appendTo', function() {
|
||||
|
||||
before(function(done) {
|
||||
logClient.appendTo(jobId, firstLog)
|
||||
.then(() => done())
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should create job-logs directory', function() {
|
||||
assert(exists.sync(path.join(blobDir, 'log-storage')));
|
||||
});
|
||||
|
||||
describe('getLog', function() {
|
||||
it('should return the logs from the job', function(done) {
|
||||
logClient.getLog(jobId).then(log => {
|
||||
expect(log).to.contain(firstLog);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should append additional logs to the file', function(done) {
|
||||
var secondLog = 'goodbye world';
|
||||
logClient.appendTo(jobId, secondLog)
|
||||
.then(() => logClient.getLog(jobId))
|
||||
.then(log => {
|
||||
expect(log).to.contain(secondLog);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete', function() {
|
||||
var delJobId = '/4/8/l';
|
||||
|
||||
before(function(done) {
|
||||
logClient.appendTo(delJobId, firstLog).then(() => done());
|
||||
});
|
||||
|
||||
it('should delete the file from job-logs directory', function(done) {
|
||||
logClient.deleteLog(delJobId)
|
||||
.then(() => logClient.getLog(delJobId))
|
||||
.then(log => {
|
||||
expect(log).to.equal('');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('migration', function() {
|
||||
var client,
|
||||
jId = '/asd/4/q',
|
||||
logs = 'asdfasde',
|
||||
newBranch = 'otherBranch';
|
||||
|
||||
before(function(done) {
|
||||
client = new JobLogsClient({
|
||||
logger: logger,
|
||||
origin: server.getUrl(),
|
||||
projectId: 'migTest',
|
||||
branchName: 'master'
|
||||
});
|
||||
// Write logs to job
|
||||
client.appendTo(jId, logs)
|
||||
.then(() => client.fork(newBranch))
|
||||
.catch(err => done(err))
|
||||
.then(() => done());
|
||||
});
|
||||
|
||||
it('should migrate the edited nodes to the new branch', function(done) {
|
||||
client.getLog(jId).then(log => {
|
||||
expect(log).to.equal(logs);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('new logs', function() {
|
||||
it('should not edit old job logs', function() {
|
||||
var c2 = new JobLogsClient({
|
||||
logger: logger,
|
||||
origin: server.getUrl(),
|
||||
projectId: 'migTest',
|
||||
branchName: 'master'
|
||||
});
|
||||
c2.getLog(jId).then(log => {
|
||||
expect(log).to.equal(logs);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should write new logs', function() {
|
||||
client.appendTo(jId, 'moreStuff')
|
||||
.then(() => client.getLog(jId))
|
||||
.then(log => {
|
||||
expect(log).to.contain('moreStuff');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Test that, on a fork, the logClient will copy all the current jobs to
|
||||
// the new fork name
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,9 @@
|
||||
'use strict';
|
||||
|
||||
var testFixture = require('webgme/test/_globals'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
exists = require('exists-file'),
|
||||
WEBGME_CONFIG_PATH = '../config';
|
||||
|
||||
// This flag will make sure the config.test.js is being used
|
||||
@@ -34,4 +37,18 @@ testFixture.requirejs.config({
|
||||
testFixture.getGmeConfig = getGmeConfig;
|
||||
|
||||
testFixture.DF_SEED_DIR = testFixture.path.join(__dirname, '..', 'src', 'seeds');
|
||||
|
||||
testFixture.mkdir = function(dir) {
|
||||
var dirs = path.resolve(dir).split(path.sep),
|
||||
shortDir,
|
||||
i = 1;
|
||||
|
||||
while (i++ < dirs.length) {
|
||||
shortDir = dirs.slice(0,i).join(path.sep);
|
||||
if (!exists.sync(shortDir)) {
|
||||
fs.mkdirSync(shortDir);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = testFixture;
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*jshint node:true, mocha:true*/
|
||||
/**
|
||||
* Generated by PluginGenerator 1.7.0 from webgme on Tue Aug 23 2016 11:02:08 GMT-0500 (CDT).
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
var testFixture = require('../../globals');
|
||||
|
||||
describe('CheckLibraries', function () {
|
||||
var gmeConfig = testFixture.getGmeConfig(),
|
||||
expect = testFixture.expect,
|
||||
logger = testFixture.logger.fork('CheckLibraries'),
|
||||
PluginCliManager = testFixture.WebGME.PluginCliManager,
|
||||
projectName = 'testProject',
|
||||
pluginName = 'CheckLibraries',
|
||||
project,
|
||||
gmeAuth,
|
||||
storage,
|
||||
commitHash;
|
||||
|
||||
before(function (done) {
|
||||
testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName)
|
||||
.then(function (gmeAuth_) {
|
||||
gmeAuth = gmeAuth_;
|
||||
// This uses in memory storage. Use testFixture.getMongoStorage to persist test to database.
|
||||
storage = testFixture.getMemoryStorage(logger, gmeConfig, gmeAuth);
|
||||
return storage.openDatabase();
|
||||
})
|
||||
.then(function () {
|
||||
var importParam = {
|
||||
projectSeed: testFixture.path.join(testFixture.SEED_DIR, 'EmptyProject.webgmex'),
|
||||
projectName: projectName,
|
||||
branchName: 'master',
|
||||
logger: logger,
|
||||
gmeConfig: gmeConfig
|
||||
};
|
||||
|
||||
return testFixture.importProject(storage, importParam);
|
||||
})
|
||||
.then(function (importResult) {
|
||||
project = importResult.project;
|
||||
commitHash = importResult.commitHash;
|
||||
return project.createBranch('test', commitHash);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
storage.closeDatabase()
|
||||
.then(function () {
|
||||
return gmeAuth.unload();
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should not edit the model', function (done) {
|
||||
var manager = new PluginCliManager(null, logger, gmeConfig),
|
||||
pluginConfig = {
|
||||
},
|
||||
context = {
|
||||
project: project,
|
||||
commitHash: commitHash,
|
||||
branchName: 'test',
|
||||
activeNode: '/1'
|
||||
};
|
||||
|
||||
manager.executePlugin(pluginName, pluginConfig, context, function (err, pluginResult) {
|
||||
expect(err).to.equal(null);
|
||||
expect(typeof pluginResult).to.equal('object');
|
||||
expect(pluginResult.success).to.equal(true);
|
||||
|
||||
project.getBranchHash('test')
|
||||
.then(function (branchHash) {
|
||||
expect(branchHash).to.equal(commitHash);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -10,12 +10,14 @@ describe('ExecuteJob', function () {
|
||||
PluginCliManager = testFixture.WebGME.PluginCliManager,
|
||||
projectName = 'testProject',
|
||||
pluginName = 'ExecuteJob',
|
||||
manager = new PluginCliManager(null, logger, gmeConfig),
|
||||
project,
|
||||
gmeAuth,
|
||||
storage,
|
||||
commitHash;
|
||||
|
||||
before(function (done) {
|
||||
this.timeout(10000);
|
||||
testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName)
|
||||
.then(function (gmeAuth_) {
|
||||
gmeAuth = gmeAuth_;
|
||||
@@ -25,7 +27,7 @@ describe('ExecuteJob', function () {
|
||||
})
|
||||
.then(function () {
|
||||
var importParam = {
|
||||
projectSeed: testFixture.path.join(testFixture.SEED_DIR, 'EmptyProject.webgmex'),
|
||||
projectSeed: testFixture.path.join(testFixture.DF_SEED_DIR, 'devProject', 'devProject.webgmex'),
|
||||
projectName: projectName,
|
||||
branchName: 'master',
|
||||
logger: logger,
|
||||
@@ -51,9 +53,7 @@ describe('ExecuteJob', function () {
|
||||
});
|
||||
|
||||
it('should verify activeNode is "Job"', function (done) {
|
||||
var manager = new PluginCliManager(null, logger, gmeConfig),
|
||||
pluginConfig = {
|
||||
},
|
||||
var pluginConfig = {},
|
||||
context = {
|
||||
project: project,
|
||||
commitHash: commitHash,
|
||||
@@ -68,4 +68,285 @@ describe('ExecuteJob', function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
////////// Helper Functions //////////
|
||||
var plugin,
|
||||
node,
|
||||
preparePlugin = function(done) {
|
||||
var context = {
|
||||
project: project,
|
||||
commitHash: commitHash,
|
||||
branchName: 'test',
|
||||
activeNode: '/K/R/p' // hello world job
|
||||
};
|
||||
|
||||
return manager.initializePlugin(pluginName)
|
||||
.then(plugin_ => {
|
||||
plugin = plugin_;
|
||||
return manager.configurePlugin(plugin, {}, context);
|
||||
})
|
||||
.then(() => node = plugin.activeNode)
|
||||
.nodeify(done);
|
||||
};
|
||||
|
||||
////////// END Helper Functions //////////
|
||||
|
||||
// Race condition checks w/ saving...
|
||||
describe('get/set', function() {
|
||||
beforeEach(preparePlugin);
|
||||
|
||||
it('should get correct attribute after set', function() {
|
||||
plugin.setAttribute(node, 'status', 'queued');
|
||||
var attrValue = plugin.getAttribute(node, 'status');
|
||||
expect(attrValue).to.equal('queued');
|
||||
});
|
||||
|
||||
it('should get correct attribute before updating nodes', function(done) {
|
||||
// Run setAttribute on some node
|
||||
plugin.setAttribute(node, 'status', 'queued');
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
var updateNodes = plugin.updateNodes;
|
||||
plugin.updateNodes = function() {
|
||||
var attrValue = plugin.getAttribute(node, 'status');
|
||||
expect(attrValue).to.equal('queued');
|
||||
return updateNodes.apply(this, arguments);
|
||||
};
|
||||
plugin.save().nodeify(done);
|
||||
});
|
||||
|
||||
it('should get correct attribute (from new node) before updating nodes', function(done) {
|
||||
// Run setAttribute on some node
|
||||
var graphTmp = plugin.createNode('pipeline.Graph', node),
|
||||
newVal = 'testGraph',
|
||||
id = 'testId';
|
||||
|
||||
// Get the
|
||||
plugin.setAttribute(graphTmp, 'name', newVal);
|
||||
plugin._metadata[id] = graphTmp;
|
||||
plugin.createIdToMetadataId[graphTmp] = id;
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
var updateNodes = plugin.updateNodes;
|
||||
plugin.updateNodes = function() {
|
||||
var graph = plugin._metadata[id],
|
||||
attrValue = plugin.getAttribute(graph, 'name');
|
||||
|
||||
expect(attrValue).to.equal(newVal);
|
||||
return updateNodes.apply(this, arguments);
|
||||
};
|
||||
plugin.save().nodeify(done);
|
||||
});
|
||||
|
||||
it('should get correct attribute after save', function(done) {
|
||||
// Run setAttribute on some node
|
||||
plugin.setAttribute(node, 'status', 'queued');
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
plugin.save()
|
||||
.then(() => {
|
||||
var attrValue = plugin.getAttribute(node, 'status');
|
||||
expect(attrValue).to.equal('queued');
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should get correct attribute while applying node changes', function(done) {
|
||||
// Run setAttribute on some node
|
||||
plugin.setAttribute(node, 'status', 'queued');
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
var oldApplyChanges = plugin._applyNodeChanges;
|
||||
plugin._applyNodeChanges = function() {
|
||||
var attrValue = plugin.getAttribute(node, 'status');
|
||||
expect(attrValue).to.equal('queued');
|
||||
return oldApplyChanges.apply(this, arguments);
|
||||
};
|
||||
plugin.save().nodeify(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createNode', function() {
|
||||
beforeEach(preparePlugin);
|
||||
|
||||
it('should update _metadata after applying changes', function(done) {
|
||||
// Run setAttribute on some node
|
||||
var graphTmp = plugin.createNode('pipeline.Graph', node),
|
||||
id = 'testId';
|
||||
|
||||
plugin._metadata[id] = graphTmp;
|
||||
plugin.createIdToMetadataId[graphTmp] = id;
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
var applyModelChanges = plugin.applyModelChanges;
|
||||
plugin.applyModelChanges = function() {
|
||||
return applyModelChanges.apply(this, arguments)
|
||||
.then(() => {
|
||||
var graph = plugin._metadata[id];
|
||||
expect(graph).to.not.equal(graphTmp);
|
||||
});
|
||||
};
|
||||
plugin.save().nodeify(done);
|
||||
});
|
||||
|
||||
it('should update _metadata in updateNodes', function(done) {
|
||||
var id = 'testId';
|
||||
|
||||
plugin._metadata[id] = node;
|
||||
node.old = true;
|
||||
plugin.updateNodes()
|
||||
.then(() => {
|
||||
var graph = plugin._metadata[id];
|
||||
expect(graph.old).to.not.equal(true);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
// Check that it gets the correct value from a newly created node after
|
||||
// it has been saved/created
|
||||
it('should get changed attribute', function(done) {
|
||||
// Run setAttribute on some node
|
||||
var graphTmp = plugin.createNode('pipeline.Graph', node),
|
||||
id = 'testId';
|
||||
|
||||
plugin._metadata[id] = node;
|
||||
plugin.createIdToMetadataId[graphTmp] = id;
|
||||
|
||||
plugin.setAttribute(graphTmp, 'name', 'firstName');
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
plugin.save()
|
||||
.then(() => {
|
||||
var graph = plugin._metadata[id],
|
||||
val = plugin.getAttribute(graph, 'name');
|
||||
expect(val).to.equal('firstName');
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should get inherited attribute', function(done) {
|
||||
// Run setAttribute on some node
|
||||
var graphTmp = plugin.createNode('pipeline.Graph', node),
|
||||
id = 'testId',
|
||||
val;
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
plugin._metadata[id] = node;
|
||||
plugin.createIdToMetadataId[graphTmp] = id;
|
||||
|
||||
val = plugin.getAttribute(graphTmp, 'name');
|
||||
expect(val).to.equal('Graph');
|
||||
|
||||
plugin.save()
|
||||
.then(() => {
|
||||
var graph = plugin._metadata[id];
|
||||
|
||||
val = plugin.getAttribute(graph, 'name');
|
||||
|
||||
expect(val).to.equal('Graph');
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
});
|
||||
|
||||
// Canceling
|
||||
describe('cancel', function() {
|
||||
beforeEach(preparePlugin);
|
||||
|
||||
it('should stop the job if the execution is canceled', function(done) {
|
||||
var job = node,
|
||||
hash = 'abc123',
|
||||
exec = {
|
||||
cancelJob: jobHash => expect(jobHash).equal(hash)
|
||||
};
|
||||
|
||||
plugin.setAttribute(node, 'secret', 'abc');
|
||||
plugin.isExecutionCanceled = () => true;
|
||||
plugin.onOperationCanceled = () => done();
|
||||
plugin.watchOperation(exec, hash, job, job);
|
||||
});
|
||||
|
||||
it('should stop the job if a job is canceled', function(done) {
|
||||
var job = node,
|
||||
hash = 'abc123',
|
||||
exec = {
|
||||
cancelJob: jobHash => expect(jobHash).equal(hash)
|
||||
};
|
||||
|
||||
plugin.setAttribute(job, 'secret', 'abc');
|
||||
plugin.canceled = true;
|
||||
plugin.onOperationCanceled = () => done();
|
||||
plugin.watchOperation(exec, hash, job, job);
|
||||
});
|
||||
|
||||
it('should set exec to running', function(done) {
|
||||
var job = node,
|
||||
execNode = plugin.core.getParent(job);
|
||||
|
||||
// Set the execution to canceled
|
||||
plugin.setAttribute(execNode, 'status', 'canceled');
|
||||
plugin.prepare = () => {
|
||||
var status = plugin.getAttribute(execNode, 'status');
|
||||
expect(status).to.not.equal('canceled');
|
||||
return {then: () => done()};
|
||||
};
|
||||
plugin.main();
|
||||
});
|
||||
});
|
||||
|
||||
describe('exec files', function() {
|
||||
describe('attribute file', function() {
|
||||
var boolString = /['"](true|false)['"]/g;
|
||||
|
||||
beforeEach(preparePlugin);
|
||||
|
||||
it('should not quote true (s) boolean values', function() {
|
||||
var files = {},
|
||||
content,
|
||||
matches;
|
||||
|
||||
plugin.setAttribute(node, 'debug', 'true');
|
||||
plugin.createAttributeFile(node, files);
|
||||
content = files['attributes.lua'];
|
||||
matches = content.match(boolString);
|
||||
expect(matches).to.equal(null);
|
||||
});
|
||||
|
||||
it('should not quote true boolean values', function() {
|
||||
var files = {},
|
||||
content,
|
||||
matches;
|
||||
|
||||
plugin.setAttribute(node, 'debug', true);
|
||||
plugin.createAttributeFile(node, files);
|
||||
content = files['attributes.lua'];
|
||||
matches = content.match(boolString);
|
||||
expect(matches).to.equal(null);
|
||||
});
|
||||
|
||||
it('should not quote false (s) boolean values', function() {
|
||||
var files = {},
|
||||
content,
|
||||
matches;
|
||||
|
||||
plugin.setAttribute(node, 'debug', 'false');
|
||||
plugin.createAttributeFile(node, files);
|
||||
content = files['attributes.lua'];
|
||||
matches = content.match(boolString);
|
||||
expect(matches).to.equal(null);
|
||||
});
|
||||
|
||||
it('should not quote false boolean values', function() {
|
||||
var files = {},
|
||||
content,
|
||||
matches;
|
||||
|
||||
plugin.setAttribute(node, 'debug', false);
|
||||
plugin.createAttributeFile(node, files);
|
||||
content = files['attributes.lua'];
|
||||
matches = content.match(boolString);
|
||||
expect(matches).to.equal(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -89,6 +89,7 @@ describe('GenerateArchitecture', function () {
|
||||
//['/o', 'basic.lua'],
|
||||
//['/8', 'basic-transfers.lua'],
|
||||
//['/M', 'concat-parallel.lua'],
|
||||
['/4', 'requiredOmitted.lua'],
|
||||
['/e', 'googlenet.lua'],
|
||||
['/X', 'overfeat.lua']
|
||||
];
|
||||
|
||||
@@ -14,7 +14,7 @@ var testFixture = require('../../globals'),
|
||||
];
|
||||
|
||||
describe('ImportTorch', function () {
|
||||
this.timeout(5000);
|
||||
this.timeout(7500);
|
||||
var gmeConfig = testFixture.getGmeConfig(),
|
||||
Q = testFixture.Q,
|
||||
GraphChecker = testFixture.requirejs('deepforge/GraphChecker'),
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*jshint node:true, mocha:true*/
|
||||
|
||||
'use strict';
|
||||
var testFixture = require('../../globals');
|
||||
|
||||
describe.skip('UpdateLibrarySeed', function () {
|
||||
var gmeConfig = testFixture.getGmeConfig(),
|
||||
expect = testFixture.expect,
|
||||
logger = testFixture.logger.fork('UpdateLibrarySeed'),
|
||||
PluginCliManager = testFixture.WebGME.PluginCliManager,
|
||||
projectName = 'testProject',
|
||||
pluginName = 'UpdateLibrarySeed',
|
||||
project,
|
||||
gmeAuth,
|
||||
storage,
|
||||
commitHash;
|
||||
|
||||
before(function (done) {
|
||||
testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName)
|
||||
.then(function (gmeAuth_) {
|
||||
gmeAuth = gmeAuth_;
|
||||
// This uses in memory storage. Use testFixture.getMongoStorage to persist test to database.
|
||||
storage = testFixture.getMemoryStorage(logger, gmeConfig, gmeAuth);
|
||||
return storage.openDatabase();
|
||||
})
|
||||
.then(function () {
|
||||
var importParam = {
|
||||
projectSeed: testFixture.path.join(testFixture.SEED_DIR, 'EmptyProject.webgmex'),
|
||||
projectName: projectName,
|
||||
branchName: 'master',
|
||||
logger: logger,
|
||||
gmeConfig: gmeConfig
|
||||
};
|
||||
|
||||
return testFixture.importProject(storage, importParam);
|
||||
})
|
||||
.then(function (importResult) {
|
||||
project = importResult.project;
|
||||
commitHash = importResult.commitHash;
|
||||
return project.createBranch('test', commitHash);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
storage.closeDatabase()
|
||||
.then(function () {
|
||||
return gmeAuth.unload();
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should run plugin and update the branch', function (done) {
|
||||
var manager = new PluginCliManager(null, logger, gmeConfig),
|
||||
pluginConfig = {
|
||||
},
|
||||
context = {
|
||||
project: project,
|
||||
commitHash: commitHash,
|
||||
branchName: 'test',
|
||||
activeNode: '/1'
|
||||
};
|
||||
|
||||
manager.executePlugin(pluginName, pluginConfig, context, function (err, pluginResult) {
|
||||
expect(err).to.equal(null);
|
||||
expect(typeof pluginResult).to.equal('object');
|
||||
expect(pluginResult.success).to.equal(true);
|
||||
|
||||
project.getBranchHash('test')
|
||||
.then(function (branchHash) {
|
||||
expect(branchHash).to.not.equal(commitHash);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais
Referência em uma Nova Issue
Bloquear um usuário