diff --git a/editor/js/ui/projectSettings.js b/editor/js/ui/projectSettings.js
index 82470306f..8dd0f770f 100644
--- a/editor/js/ui/projectSettings.js
+++ b/editor/js/ui/projectSettings.js
@@ -477,7 +477,7 @@ RED.projects.settings = (function() {
});
}
- if (activeProject.settings.credentialsInvalid) {
+ if (activeProject.settings.credentialSecretInvalid) {
row = $('
').appendTo(pane);
$(' The current key is not valid. Set the correct key or reset credentials.
').appendTo(row);
}
@@ -498,7 +498,7 @@ RED.projects.settings = (function() {
}
if (activeProject.settings.credentialsEncrypted) {
- if (!activeProject.settings.credentialsInvalid) {
+ if (!activeProject.settings.credentialSecretInvalid) {
row = $('').appendTo(credentialsContainer);
$('').appendTo(row);
currentKey = $('').appendTo(row);
@@ -518,7 +518,7 @@ RED.projects.settings = (function() {
// $('').appendTo(row);
row = $('').appendTo(credentialsContainer);
- $('').text((activeProject.settings.credentialsEncrypted&& !activeProject.settings.credentialsInvalid)?"New key":"Encryption key").appendTo(row);
+ $('').text((activeProject.settings.credentialsEncrypted&& !activeProject.settings.credentialSecretInvalid)?"New key":"Encryption key").appendTo(row);
newKey = $('').appendTo(row).on("change keyup paste",checkInputs);
row = $('').appendTo(credentialsContainer);
@@ -551,14 +551,14 @@ RED.projects.settings = (function() {
var payload = {
credentialSecret: newKey.val()
};
- if (activeProject.settings.credentialsInvalid) {
+ if (activeProject.settings.credentialSecretInvalid) {
RED.deploy.setDeployInflight(true);
}
if (activeProject.settings.credentialsEncrypted) {
if (action === 'reset') {
payload.resetCredentialSecret = true;
- } else if (!activeProject.settings.credentialsInvalid) {
+ } else if (!activeProject.settings.credentialSecretInvalid) {
payload.currentCredentialSecret = currentKey.val();
}
}
@@ -606,7 +606,7 @@ RED.projects.settings = (function() {
},
}
},payload).always(function() {
- if (activeProject.settings.credentialsInvalid) {
+ if (activeProject.settings.credentialSecretInvalid) {
RED.deploy.setDeployInflight(false);
}
});
@@ -620,11 +620,11 @@ RED.projects.settings = (function() {
// $('').appendTo(row);
- // $('').text("Repository").appendTo(pane);
- // row = $('').appendTo(pane);
- // var input;
- // $('').appendTo(row);
- // $('').appendTo(row);
+ $('').text("Repository").appendTo(pane);
+ row = $('').appendTo(pane);
+ var input;
+ $('').appendTo(row);
+ $('').appendTo(row);
return pane;
diff --git a/editor/sass/projects.scss b/editor/sass/projects.scss
index d53d26d1e..ef76f3333 100644
--- a/editor/sass/projects.scss
+++ b/editor/sass/projects.scss
@@ -178,7 +178,10 @@
padding-top: 4px;
}
}
-
+.projects-dialog-screen-create-type.editor-button.toggle.selected:not(.disabled):not(:disabled) {
+ background: #fff !important;
+ color: #666 !important;
+}
.sidebar-version-control {
height: 100%;
diff --git a/red/api/editor/projects/index.js b/red/api/editor/projects/index.js
index 5a45d46e1..d403c57f9 100644
--- a/red/api/editor/projects/index.js
+++ b/red/api/editor/projects/index.js
@@ -33,7 +33,7 @@ module.exports = {
runtime.storage.projects.listProjects().then(function(list) {
var active = runtime.storage.projects.getActiveProject();
var response = {
- active: active,
+ active: active.name,
projects: list
};
res.json(response);
@@ -68,7 +68,7 @@ module.exports = {
//TODO: validate the payload properly
if (req.body.active) {
var currentProject = runtime.storage.projects.getActiveProject();
- if (req.params.id !== currentProject) {
+ if (req.params.id !== currentProject.name) {
runtime.storage.projects.setActiveProject(req.params.id).then(function() {
res.redirect(303,req.baseUrl + '/');
}).catch(function(err) {
diff --git a/red/runtime/index.js b/red/runtime/index.js
index c8f269d37..73f09317a 100644
--- a/red/runtime/index.js
+++ b/red/runtime/index.js
@@ -158,9 +158,9 @@ function start() {
if (settings.httpStatic) {
log.info(log._("runtime.paths.httpStatic",{path:path.resolve(settings.httpStatic)}));
}
- redNodes.loadFlows().then(redNodes.startFlows).otherwise(function(err) {});
+ redNodes.loadFlows().then(redNodes.startFlows).catch(function(err) {});
started = true;
- }).otherwise(function(err) {
+ }).catch(function(err) {
console.log(err);
});
});
diff --git a/red/runtime/nodes/credentials.js b/red/runtime/nodes/credentials.js
index b4d6c1841..57103ff4c 100644
--- a/red/runtime/nodes/credentials.js
+++ b/red/runtime/nodes/credentials.js
@@ -16,6 +16,7 @@
var when = require("when");
var crypto = require('crypto');
+var runtime;
var settings;
var log;
@@ -38,30 +39,9 @@ function decryptCredentials(key,credentials) {
return JSON.parse(decrypted);
}
-function markProjectSecretValid(project,valid) {
- try {
- var projects = settings.get('projects');
- if (projects) {
- if (valid) {
- if (!projects.projects[project].credentialSecretInvalid) {
- return when.resolve();
- } else {
- delete projects.projects[project].credentialSecretInvalid;
- }
- } else {
- projects.projects[project].credentialSecretInvalid = true;
- }
- return settings.set('projects',projects);
- } else {
- return when.resolve();
- }
- } catch(err) {
- return when.resolve();
- }
-}
-
var api = module.exports = {
- init: function(runtime) {
+ init: function(_runtime) {
+ runtime = _runtime;
log = runtime.log;
settings = runtime.settings;
dirty = false;
@@ -98,14 +78,14 @@ var api = module.exports = {
var projectKey = false;
var activeProject;
- try {
- var projects = settings.get('projects');
- if (projects && projects.activeProject) {
- activeProject = projects.activeProject;
- projectKey = projects.projects[projects.activeProject].credentialSecret;
+ if (runtime.storage.projects) {
+ // projects enabled
+ activeProject = runtime.storage.projects.getActiveProject();
+ if (activeProject) {
+ projectKey = activeProject.credentialSecret;
}
- } catch(err) {
}
+
if (projectKey) {
log.debug("red/runtime/nodes/credentials.load : using active project key - ignoring user provided key");
userKey = projectKey;
@@ -208,9 +188,9 @@ var api = module.exports = {
error.code = "credentials_load_failed";
if (projectKey) {
// This is a project with a bad key. Mark it as invalid
- return markProjectSecretValid(activeProject,false).then(function() {
- return when.reject(error);
- })
+ // TODO: this delves too deep into Project structure
+ activeProject.info.settings.credentialSecretInvalid = true;
+ return when.reject(error);
}
return when.reject(error);
}
@@ -218,7 +198,7 @@ var api = module.exports = {
credentialCache = credentials;
}
if (clearInvalidFlag) {
- return markProjectSecretValid(activeProject,true)
+ delete activeProject.info.settings.credentialSecretInvalid;
}
});
},
diff --git a/red/runtime/nodes/flows/index.js b/red/runtime/nodes/flows/index.js
index 6131e18e4..e05ae56f7 100644
--- a/red/runtime/nodes/flows/index.js
+++ b/red/runtime/nodes/flows/index.js
@@ -76,7 +76,7 @@ function loadFlows() {
events.emit("runtime-event",{id:"runtime-state",retain:true});
return config;
});
- }).otherwise(function(err) {
+ }).catch(function(err) {
activeConfig = null;
events.emit("runtime-event",{id:"runtime-state",payload:{type:"warning",error:"credentials_load_failed",text:"notification.warnings.invalid-credentials-secret"},retain:true});
log.warn(log._("nodes.flows.error",{message:err.toString()}));
@@ -141,7 +141,7 @@ function setFlows(_config,type,muteLog,forceStart) {
events.emit("runtime-event",{id:"runtime-deploy",payload:{revision:flowRevision},retain: true});
});
return flowRevision;
- }).otherwise(function(err) {
+ }).catch(function(err) {
})
} else {
events.emit("runtime-event",{id:"runtime-deploy",payload:{revision:flowRevision},retain: true});
diff --git a/red/runtime/storage/localfilesystem/projects/Project.js b/red/runtime/storage/localfilesystem/projects/Project.js
new file mode 100644
index 000000000..7517607fe
--- /dev/null
+++ b/red/runtime/storage/localfilesystem/projects/Project.js
@@ -0,0 +1,338 @@
+/**
+ * Copyright JS Foundation and other contributors, http://js.foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+
+var fs = require('fs-extra');
+var when = require('when');
+var fspath = require("path");
+
+var gitTools = require("./git");
+var util = require("../util");
+var defaultFileSet = require("./defaultFileSet");
+
+var settings;
+var runtime;
+var log;
+
+var projectsDir;
+
+function Project(name) {
+ this.name = name;
+ this.path = fspath.join(projectsDir,name);
+ this.paths = {};
+ this.info = {
+ name: name,
+ settings: {}
+ };
+ this.credentialSecret = null;
+}
+Project.prototype.load = function () {
+ var project = this;
+ var globalProjectSettings = settings.get("projects");
+// console.log(globalProjectSettings)
+ var projectSettings = {};
+ if (globalProjectSettings) {
+ projectSettings = globalProjectSettings.projects[this.name]||{};
+ }
+
+ this.credentialSecret = projectSettings.credentialSecret;
+// console.log(this.name,"credSec",this.credentialSecret )
+ if (typeof projectSettings.credentialSecret === "string") {
+ this.info.settings.credentialsEncrypted = true;
+ } else {
+ this.info.settings.credentialsEncrypted = false;
+ }
+ var promises = [];
+ return checkProjectFiles(project.name).then(function(missingFiles) {
+ if (missingFiles.length > 0) {
+ project.info.missingFiles = missingFiles;
+ }
+ if (missingFiles.indexOf('package.json') === -1) {
+ project.paths['package.json'] = fspath.join(project.path,"package.json");
+ promises.push(fs.readFile(project.paths['package.json'],"utf8").then(function(content) {
+ project.package = util.parseJSON(content);
+ project.info.summary = project.package.description||"";
+ project.info.dependencies = project.package.dependencies||{};
+ }));
+ }
+ if (missingFiles.indexOf('README.md') === -1) {
+ project.paths['README.md'] = fspath.join(project.path,"README.md");
+ promises.push(fs.readFile(project.paths['README.md'],"utf8").then(function(content) {
+ project.info.description = content;
+ }));
+ } else {
+ project.info.description = "";
+ }
+
+ return when.settle(promises).then(function() {
+ return project;
+ })
+ });
+};
+
+Project.prototype.update = function (data) {
+ var filesToUpdate = {};
+ var promises = [];
+ var project = this;
+
+ if (data.credentialSecret) {
+ var existingSecret = data.currentCredentialSecret;
+ var isReset = data.resetCredentialSecret;
+ var secret = data.credentialSecret;
+
+ // console.log("updating credentialSecret");
+ // console.log("request:");
+ // console.log(JSON.stringify(data,"",4));
+ // console.log(" this.credentialSecret",this.credentialSecret);
+ // console.log(" this.info", this.info);
+
+ if (!isReset && // not a reset
+ this.credentialSecret && // key already set
+ !this.info.settings.credentialSecretInvalid && // key not invalid
+ this.credentialSecret !== existingSecret) { // key doesn't match provided existing key
+ var e = new Error("Cannot change credentialSecret without current key");
+ e.code = "missing_current_credential_key";
+ throw e;
+ }
+ this.credentialSecret = secret;
+
+ var globalProjectSettings = settings.get("projects");
+ globalProjectSettings.projects[this.name] = globalProjectSettings.projects[this.name]||{}
+ globalProjectSettings.projects[this.name].credentialSecret = project.credentialSecret;
+ delete this.info.settings.credentialSecretInvalid;
+
+ return settings.set("projects",globalProjectSettings);
+ }
+
+ if (data.hasOwnProperty('description')) {
+ filesToUpdate[this.paths['README.md']] = function() {
+ return data.description;
+ };
+ this.info.description = data.description;
+ }
+ if (data.hasOwnProperty('dependencies')) {
+ filesToUpdate[this.paths['package.json']] = function() {
+ return JSON.stringify(project.package,"",4)
+ };
+ this.package.dependencies = data.dependencies;
+ this.info.dependencies = data.dependencies;
+ }
+ if (data.hasOwnProperty('summary')) {
+ filesToUpdate[this.paths['package.json']] = function() {
+ return JSON.stringify(project.package,"",4)
+ };
+ this.package.description = data.summary;
+ this.info.summary = data.summary;
+ }
+
+ var files = Object.keys(filesToUpdate);
+ files.forEach(function(f) {
+ promises.push(util.writeFile(f,filesToUpdate[f]()));
+ });
+ return when.settle(promises);
+};
+
+Project.prototype.getFiles = function () {
+ return gitTools.getFiles(this.path);
+};
+Project.prototype.stageFile = function(file) {
+ return gitTools.stageFile(this.path,file);
+};
+Project.prototype.unstageFile = function(file) {
+ return gitTools.unstageFile(this.path,file);
+}
+Project.prototype.commit = function(options) {
+ return gitTools.commit(this.path,options.message);
+}
+Project.prototype.getFileDiff = function(file,type) {
+ return gitTools.getFileDiff(this.path,file,type);
+}
+Project.prototype.getCommits = function(options) {
+ return gitTools.getCommits(this.path,options);
+}
+Project.prototype.getCommit = function(sha) {
+ return gitTools.getCommit(this.path,sha);
+}
+
+Project.prototype.getFlowFile = function() {
+ return fspath.join(this.path,"flow.json");
+}
+Project.prototype.getFlowFileBackup = function() {
+ return getBackupFilename(this.getFlowFile());
+}
+Project.prototype.getCredentialsFile = function() {
+ return fspath.join(this.path,"flow_cred.json");
+}
+Project.prototype.getCredentialsFileBackup = function() {
+ return getBackupFilename(this.getCredentialsFile());
+}
+
+function getBackupFilename(filename) {
+ var ffName = fspath.basename(filename);
+ var ffDir = fspath.dirname(filename);
+ return fspath.join(ffDir,"."+ffName+".backup");
+}
+
+function checkProjectExists(project) {
+ var projectPath = fspath.join(projectsDir,project);
+ return fs.pathExists(projectPath).then(function(exists) {
+ if (!exists) {
+ var e = new Error("NLD: project not found");
+ e.code = "project_not_found";
+ throw e;
+ }
+ });
+}
+
+function createProjectDirectory(project) {
+ var projectPath = fspath.join(projectsDir,project);
+ return fs.ensureDir(projectPath);
+}
+
+function createDefaultProject(project) {
+ var projectPath = fspath.join(projectsDir,project.name);
+ // Create a basic skeleton of a project
+ return gitTools.initRepo(projectPath).then(function() {
+ var promises = [];
+ for (var file in defaultFileSet) {
+ if (defaultFileSet.hasOwnProperty(file)) {
+ promises.push(util.writeFile(fspath.join(projectPath,file),defaultFileSet[file](project)));
+ }
+ }
+ return when.all(promises);
+ });
+}
+
+function checkProjectFiles(project) {
+ var projectPath = fspath.join(projectsDir,project);
+ var promises = [];
+ var paths = [];
+ for (var file in defaultFileSet) {
+ if (defaultFileSet.hasOwnProperty(file)) {
+ paths.push(file);
+ promises.push(fs.stat(fspath.join(projectPath,file)));
+ }
+ }
+ return when.settle(promises).then(function(results) {
+ var missing = [];
+ results.forEach(function(result,i) {
+ if (result.state === 'rejected') {
+ missing.push(paths[i]);
+ }
+ });
+ return missing;
+ }).then(function(missing) {
+ // if (createMissing) {
+ // var promises = [];
+ // missing.forEach(function(file) {
+ // promises.push(util.writeFile(fspath.join(projectPath,file),defaultFileSet[file](project)));
+ // });
+ // return promises;
+ // } else {
+ return missing;
+ // }
+ });
+}
+
+function createProject(metadata) {
+ var project = metadata.name;
+ return when.promise(function(resolve,reject) {
+ var projectPath = fspath.join(projectsDir,project);
+ fs.stat(projectPath, function(err,stat) {
+ if (!err) {
+ var e = new Error("NLS: Project already exists");
+ e.code = "project_exists";
+ return reject(e);
+ }
+ createProjectDirectory(project).then(function() {
+ var projects = settings.get('projects');
+ projects.projects[project] = {};
+ if (metadata.credentialSecret) {
+ projects.projects[project].credentialSecret = metadata.credentialSecret;
+ }
+ return settings.set('projects',projects);
+ }).then(function() {
+ if (metadata.remote) {
+ return gitTools.clone(metadata.remote,projectPath).then(function(result) {
+ // Check this is a valid project
+ // If it is empty
+ // - if 'populate' flag is set, call populateProject
+ // - otherwise reject with suitable error to allow UI to confirm population
+ // If it is missing package.json/flow.json/flow_cred.json
+ // - reject as invalid project
+
+ // checkProjectFiles(project).then(function(results) {
+ // console.log("checkProjectFiles");
+ // console.log(results);
+ // });
+
+ resolve(getProject(project));
+ }).catch(function(error) {
+ fs.remove(projectPath,function() {
+ reject(error);
+ });
+ })
+ } else {
+ createDefaultProject(metadata).then(function() { resolve(getProject(project))}).catch(reject);
+ }
+ }).catch(reject);
+ })
+ })
+}
+
+var currentProject;
+
+function getProject(name) {
+ return checkProjectExists(name).then(function() {
+ if (currentProject && currentProject.name === name) {
+ return currentProject;
+ }
+ currentProject = new Project(name);
+ return currentProject.load();
+ })
+
+}
+
+function listProjects() {
+ return fs.readdir(projectsDir).then(function(fns) {
+ var dirs = [];
+ fns.sort().filter(function(fn) {
+ var fullPath = fspath.join(projectsDir,fn);
+ if (fn[0] != ".") {
+ var stats = fs.lstatSync(fullPath);
+ if (stats.isDirectory()) {
+ dirs.push(fn);
+ }
+ }
+ });
+ return dirs;
+ });
+}
+
+function init(_settings, _runtime) {
+ settings = _settings;
+ runtime = _runtime;
+ log = runtime.log;
+ projectsDir = fspath.join(settings.userDir,"projects");
+}
+
+module.exports = {
+ init: init,
+ get: getProject,
+ create: createProject,
+ list: listProjects
+
+}
diff --git a/red/runtime/storage/localfilesystem/projects/git/index.js b/red/runtime/storage/localfilesystem/projects/git/index.js
index 4cb3277b1..07d0a6d43 100644
--- a/red/runtime/storage/localfilesystem/projects/git/index.js
+++ b/red/runtime/storage/localfilesystem/projects/git/index.js
@@ -208,6 +208,9 @@ module.exports = {
return runCommand(gitCommand,args,cwd);
},
clone: function(repo, cwd) {
+ if (repo.url) {
+ repo = repo.url;
+ }
var args = ["clone",repo,"."];
return runCommand(gitCommand,args,cwd);
},
diff --git a/red/runtime/storage/localfilesystem/projects/index.js b/red/runtime/storage/localfilesystem/projects/index.js
index 5ccc9acbf..a296b9744 100644
--- a/red/runtime/storage/localfilesystem/projects/index.js
+++ b/red/runtime/storage/localfilesystem/projects/index.js
@@ -24,18 +24,21 @@ var storageSettings = require("../settings");
var util = require("../util");
var gitTools = require("./git");
+var Projects = require("./Project");
+
var settings;
var runtime;
var projectsDir;
-
-var defaultFileSet = require("./defaultFileSet");
+var activeProject
function init(_settings, _runtime) {
settings = _settings;
runtime = _runtime;
log = runtime.log;
+ Projects.init(settings,runtime);
+
projectsDir = fspath.join(settings.userDir,"projects");
if (settings.flowFile) {
@@ -85,11 +88,6 @@ function init(_settings, _runtime) {
return storageSettings.saveSettings(globalSettings);
} else {
activeProject = globalSettings.projects.activeProject;
- var projectPath = fspath.join(projectsDir,activeProject);
- flowsFullPath = fspath.join(projectPath,"flow.json");
- flowsFileBackup = getBackupFilename(flowsFullPath);
- credentialsFile = fspath.join(projectPath,"flow_cred.json");
- credentialsFileBackup = getBackupFilename(credentialsFile);
}
});
} else {
@@ -103,347 +101,123 @@ function getBackupFilename(filename) {
return fspath.join(ffDir,"."+ffName+".backup");
}
-function listProjects() {
- return fs.readdir(projectsDir).then(function(fns) {
- var dirs = [];
- fns.sort().filter(function(fn) {
- var fullPath = fspath.join(projectsDir,fn);
- if (fn[0] != ".") {
- var stats = fs.lstatSync(fullPath);
- if (stats.isDirectory()) {
- dirs.push(fn);
- }
- }
- });
- return dirs;
- });
-}
-
-function getProject(project) {
-
- return when.promise(function(resolve,reject) {
- if (project === "") {
- return reject(new Error("NLS: No active project set"));
- }
- var projectPath = fspath.join(projectsDir,project);
- var globalProjectSettings = settings.get("projects");
- var projectSettings = {};
- if (globalProjectSettings.projects) {
- projectSettings = globalProjectSettings.projects[project]||{};
- }
-
- var projectData = {
- name: project,
- settings: {}
- };
-
- if (typeof projectSettings.credentialSecret === "string") {
- projectData.settings.credentialsEncrypted = true;
- } else {
- projectData.settings.credentialsEncrypted = false;
- }
- if (projectSettings.credentialSecretInvalid) {
- projectData.settings.credentialsInvalid = true;
- }
-
- var promises = [];
- checkProjectFiles(project).then(function(missingFiles) {
- if (missingFiles.length > 0) {
- projectData.missingFiles = missingFiles;
- }
- if (missingFiles.indexOf('package.json') === -1) {
- promises.push(fs.readFile(fspath.join(projectPath,"package.json"),"utf8").then(function(content) {
- var package = util.parseJSON(content);
- projectData.summary = package.description||"";
- projectData.dependencies = package.dependencies||{};
- }));
- }
- if (missingFiles.indexOf('README.md') === -1) {
- promises.push(fs.readFile(fspath.join(projectPath,"README.md"),"utf8").then(function(content) {
- projectData.description = content;
- }));
- } else {
- projectData.description = "";
- }
-
- when.settle(promises).then(function() {
- resolve(projectData);
- })
- });
-
- // fs.stat(projectPath,function(err,stat) {
- // if (err) {
- // return resolve(null);
- // }
- // resolve(fs.readFile(projectPackage,'utf8').then(util.parseJSON));
- // })
- }).catch(function(err) {
- console.log(err);
- var e = new Error("NLD: project not found");
- e.code = "project_not_found";
- throw e;
- });
-}
-
-function setCredentialSecret(project,data) { //existingSecret,secret) {
- var existingSecret = data.currentCredentialSecret;
- var isReset = data.resetCredentialSecret;
- var secret = data.credentialSecret;
- var wasInvalid = false;
-
- var globalProjectSettings = settings.get("projects");
- if (globalProjectSettings.projects.hasOwnProperty(project)) {
- if (!isReset &&
- globalProjectSettings.projects[project].credentialSecret &&
- !globalProjectSettings.projects[project].credentialSecretInvalid &&
- globalProjectSettings.projects[project].credentialSecret !== existingSecret) {
- var e = new Error("Cannot change credentialSecret without current key");
- e.code = "missing_current_credential_key";
- throw e;
- }
- } else {
- globalProjectSettings.projects[project] = {};
- }
-
- globalProjectSettings.projects[project].credentialSecret = secret;
- wasInvalid = globalProjectSettings.projects[project].credentialSecretInvalid;
- delete globalProjectSettings.projects[project].credentialSecretInvalid;
-
- return settings.set("projects",globalProjectSettings).then(function() {
- if (isReset || !wasInvalid) {
- if (isReset) {
- runtime.nodes.clearCredentials();
- }
- runtime.nodes.setCredentialSecret(secret);
- return runtime.nodes.exportCredentials()
- .then(runtime.storage.saveCredentials)
- .then(function() {
- return wasInvalid;
- });
- }
- return wasInvalid;
- });
-}
-
-function createProject(metadata) {
- var project = metadata.name;
- return when.promise(function(resolve,reject) {
- if (project === "") {
- return reject(new Error("NLS: No project set"));
- }
- var projectPath = fspath.join(projectsDir,project);
- fs.stat(projectPath, function(err,stat) {
- if (!err) {
- var e = new Error("NLS: Project already exists");
- e.code = "project_exists";
- return reject(e);
- }
- createProjectDirectory(project).then(function() {
- var projects = settings.get('projects');
- projects[project] = {};
- if (metadata.credentialSecret) {
- projects[project].credentialSecret = metadata.credentialSecret;
- }
- return settings.set('projects',projects);
- }).then(function() {
- if (metadata.remote) {
- return gitTools.pull(metadata.remote,projectPath).then(function(result) {
- // Check this is a valid project
- // If it is empty
- // - if 'populate' flag is set, call populateProject
- // - otherwise reject with suitable error to allow UI to confirm population
- // If it is missing package.json/flow.json/flow_cred.json
- // - reject as invalid project
-
- checkProjectFiles(project).then(function(results) {
- console.log("checkProjectFiles");
- console.log(results);
- });
-
- resolve(project);
- }).catch(function(error) {
- fs.remove(projectPath,function() {
- reject(error);
- });
- })
- } else {
- createDefaultProject(metadata).then(function() { resolve(project)}).catch(reject);
- }
- }).catch(reject);
- })
+function loadProject(name) {
+ return Projects.get(name).then(function(project) {
+ activeProject = project;
+ flowsFullPath = project.getFlowFile();
+ flowsFileBackup = project.getFlowFileBackup();
+ credentialsFile = project.getCredentialsFile();
+ credentialsFileBackup = project.getCredentialsFileBackup();
+ return project;
})
}
-function createProjectDirectory(project) {
- var projectPath = fspath.join(projectsDir,project);
- return fs.ensureDir(projectPath).then(function() {
- return gitTools.initRepo(projectPath)
- });
-}
-
-function createDefaultProject(project) {
- var projectPath = fspath.join(projectsDir,project.name);
- // Create a basic skeleton of a project
- var promises = [];
- for (var file in defaultFileSet) {
- if (defaultFileSet.hasOwnProperty(file)) {
- promises.push(util.writeFile(fspath.join(projectPath,file),defaultFileSet[file](project)));
- }
+function getProject(name) {
+ if (!activeProject || activeProject.name !== name) {
+ //TODO: throw better err
+ throw new Error("Cannot get inactive project");
}
- return when.all(promises);
+ //return when.resolve(activeProject.info);
+ return Projects.get(name).then(function(p) {
+ return p.info
+ })
}
-function checkProjectExists(project) {
- var projectPath = fspath.join(projectsDir,project);
- return fs.pathExists(projectPath).then(function(exists) {
- console.log(projectPath,exists);
- if (!exists) {
- var e = new Error("NLD: project not found");
- e.code = "project_not_found";
- throw e;
- }
- });
-}
-function checkProjectFiles(project) {
- var projectPath = fspath.join(projectsDir,project);
- var promises = [];
- var paths = [];
- for (var file in defaultFileSet) {
- if (defaultFileSet.hasOwnProperty(file)) {
- paths.push(file);
- promises.push(fs.stat(fspath.join(projectPath,file)));
- }
- }
- return when.settle(promises).then(function(results) {
- var missing = [];
- results.forEach(function(result,i) {
- if (result.state === 'rejected') {
- missing.push(paths[i]);
- }
- });
- return missing;
- }).then(function(missing) {
- // if (createMissing) {
- // var promises = [];
- // missing.forEach(function(file) {
- // promises.push(util.writeFile(fspath.join(projectPath,file),defaultFileSet[file](project)));
- // });
- // return promises;
- // } else {
- return missing;
- // }
- });
-}
-
function getFiles(project) {
- var projectPath = fspath.join(projectsDir,project);
- return gitTools.getFiles(projectPath);
+ return activeProject.getFiles();
}
function stageFile(project,file) {
- var projectPath = fspath.join(projectsDir,project);
- return gitTools.stageFile(projectPath,file);
+ return activeProject.stageFile(file);
}
function unstageFile(project,file) {
- var projectPath = fspath.join(projectsDir,project);
- return gitTools.unstageFile(projectPath,file);
+ return activeProject.unstageFile(file);
}
function commit(project,options) {
- var projectPath = fspath.join(projectsDir,project);
- return gitTools.commit(projectPath,options.message);
+ return activeProject.commit(options);
}
function getFileDiff(project,file,type) {
- var projectPath = fspath.join(projectsDir,project);
- return gitTools.getFileDiff(projectPath,file,type);
+ return activeProject.getFileDiff(file,type);
}
function getCommits(project,options) {
- var projectPath = fspath.join(projectsDir,project);
- return gitTools.getCommits(projectPath,options);
+ return activeProject.getCommits(options);
}
function getCommit(project,sha) {
- var projectPath = fspath.join(projectsDir,project);
- return gitTools.getCommit(projectPath,sha);
+ return activeProject.getCommit(sha);
}
function getFile(project,path) {
}
-var activeProject
function getActiveProject() {
return activeProject;
}
-function reloadActiveProject(project) {
+function reloadActiveProject() {
return runtime.nodes.stopFlows().then(function() {
return runtime.nodes.loadFlows(true).then(function() {
- runtime.events.emit("runtime-event",{id:"project-change",payload:{ project: project}});
+ runtime.events.emit("runtime-event",{id:"project-change",payload:{ project: activeProject.name}});
}).catch(function(err) {
// We're committed to the project change now, so notify editors
// that it has changed.
- runtime.events.emit("runtime-event",{id:"project-change",payload:{ project: project}});
+ runtime.events.emit("runtime-event",{id:"project-change",payload:{ project: activeProject.name}});
throw err;
});
});
}
-
-function setActiveProject(project) {
- return checkProjectExists(project).then(function() {
- activeProject = project;
+function createProject(metadata) {
+ return Projects.create(metadata).then(function(p) {
+ return p.name;
+ })
+}
+function setActiveProject(projectName) {
+ return loadProject(projectName).then(function(project) {
var globalProjectSettings = settings.get("projects");
- globalProjectSettings.activeProject = project;
+ globalProjectSettings.activeProject = project.name;
return settings.set("projects",globalProjectSettings).then(function() {
- var projectPath = fspath.join(projectsDir,project);
- flowsFullPath = fspath.join(projectPath,"flow.json");
- flowsFileBackup = getBackupFilename(flowsFullPath);
- credentialsFile = fspath.join(projectPath,"flow_cred.json");
- credentialsFileBackup = getBackupFilename(credentialsFile);
-
log.info(log._("storage.localfilesystem.changing-project",{project:activeProject||"none"}));
log.info(log._("storage.localfilesystem.flows-file",{path:flowsFullPath}));
- console.log("Updated file targets to");
- console.log(flowsFullPath)
- console.log(credentialsFile)
-
- return reloadActiveProject(project);
-
+ // console.log("Updated file targets to");
+ // console.log(flowsFullPath)
+ // console.log(credentialsFile)
+ return reloadActiveProject();
})
- // return when.promise(function(resolve,reject) {
- // console.log("Activating project");
- // resolve();
- // });
});
}
function updateProject(project,data) {
- return checkProjectExists(project).then(function() {
- if (data.credentialSecret) {
- // TODO: this path assumes we aren't trying to migrate the secret
- return setCredentialSecret(project,data).then(function(wasInvalid) {
- if (wasInvalid) {
- return reloadActiveProject(project);
- }
- })
- } else if (data.hasOwnProperty('description')) {
- var projectPath = fspath.join(projectsDir,project);
- var readmeFile = fspath.join(projectPath,"README.md");
- return util.writeFile(readmeFile, data.description);
- } else if (data.hasOwnProperty('dependencies') || data.hasOwnProperty('summary')) {
- var projectPath = fspath.join(projectsDir,project);
- var packageJSON = fspath.join(projectPath,"package.json");
- return fs.readFile(packageJSON,"utf8").then(function(content) {
- var package = util.parseJSON(content);
- if (data.dependencies) {
- package.dependencies = data.dependencies;
- }
- if (data.summary) {
- package.description = data.summary;
- }
-
- return util.writeFile(packageJSON,JSON.stringify(package,"",4));
- });
- }
- });
+ if (!activeProject || activeProject.name !== project) {
+ // TODO standardise
+ throw new Error("Cannot update inactive project");
+ }
+ if (data.hasOwnProperty('credentialSecret')) {
+ return setCredentialSecret(data);
+ } else {
+ return activeProject.update(data);
+ }
}
+function setCredentialSecret(data) { //existingSecret,secret) {
+ var isReset = data.resetCredentialSecret;
+ var wasInvalid = activeProject.info.settings.credentialSecretInvalid;
+ return activeProject.update(data).then(function() {
+ if (isReset || !wasInvalid) {
+ if (isReset) {
+ runtime.nodes.clearCredentials();
+ }
+ runtime.nodes.setCredentialSecret(activeProject.credentialSecret);
+ return runtime.nodes.exportCredentials()
+ .then(runtime.storage.saveCredentials)
+ .then(function() {
+ if (wasInvalid) {
+ return reloadActiveProject();
+ }
+ });
+ } else if (wasInvalid) {
+ return reloadActiveProject();
+ }
+ })
+}
+
var initialFlowLoadComplete = false;
@@ -458,9 +232,14 @@ function getFlows() {
initialFlowLoadComplete = true;
log.info(log._("storage.localfilesystem.user-dir",{path:settings.userDir}));
if (activeProject) {
- log.info(log._("storage.localfilesystem.active-project",{project:activeProject||"none"}));
+ return loadProject(activeProject).then(function() {
+ log.info(log._("storage.localfilesystem.active-project",{project:activeProject.name||"none"}));
+ log.info(log._("storage.localfilesystem.flows-file",{path:flowsFullPath}));
+ return getFlows();
+ });
+ } else {
+ log.info(log._("storage.localfilesystem.flows-file",{path:flowsFullPath}));
}
- log.info(log._("storage.localfilesystem.flows-file",{path:flowsFullPath}));
}
return util.readFile(flowsFullPath,flowsFileBackup,[],'flow');
}
@@ -510,7 +289,7 @@ function saveCredentials(credentials) {
module.exports = {
init: init,
- listProjects: listProjects,
+ listProjects: Projects.list,
getActiveProject: getActiveProject,
setActiveProject: setActiveProject,
getProject: getProject,