Merge 0.18.5

This commit is contained in:
Nick O'Leary
2018-05-10 21:45:25 +01:00
69 changed files with 2396 additions and 882 deletions

View File

@@ -237,8 +237,8 @@ function Flow(global,flow) {
this.handleError = function(node,logMessage,msg) {
var count = 1;
if (msg && msg.hasOwnProperty("error")) {
if (msg.error.hasOwnProperty("source")) {
if (msg && msg.hasOwnProperty("error") && msg.error !== null) {
if (msg.error.hasOwnProperty("source") && msg.error.source !== null) {
if (msg.error.source.id === node.id) {
count = msg.error.source.count+1;
if (count === 10) {

View File

@@ -53,15 +53,13 @@ function getGitUser(user) {
}
return null;
}
function Project(name) {
this.name = name;
this.path = fspath.join(projectsDir,name);
function Project(path) {
this.path = path;
this.name = fspath.basename(path);
this.paths = {};
this.files = {};
this.auth = {origin:{}};
this.missingFiles = [];
this.credentialSecret = null;
}
Project.prototype.load = function () {
@@ -70,7 +68,9 @@ Project.prototype.load = function () {
// console.log(globalProjectSettings)
var projectSettings = {};
if (globalProjectSettings) {
projectSettings = globalProjectSettings.projects[this.name]||{};
if (globalProjectSettings.projects.hasOwnProperty(this.name)) {
projectSettings = globalProjectSettings.projects[this.name] || {};
}
}
this.credentialSecret = projectSettings.credentialSecret;
@@ -81,9 +81,7 @@ Project.prototype.load = function () {
var promises = [];
return checkProjectFiles(project).then(function(missingFiles) {
if (missingFiles.length > 0) {
project.missingFiles = missingFiles;
}
project.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) {
@@ -135,9 +133,9 @@ Project.prototype.load = function () {
Project.prototype.initialise = function(user,data) {
var project = this;
if (!this.empty) {
throw new Error("Cannot initialise non-empty project");
}
// if (!this.empty) {
// throw new Error("Cannot initialise non-empty project");
// }
var files = Object.keys(defaultFileSet);
var promises = [];
@@ -148,17 +146,25 @@ Project.prototype.initialise = function(user,data) {
promises.push(settings.set('projects',projects));
}
project.files.flow = data.files.flow;
project.files.credentials = data.files.credentials;
var flowFilePath = fspath.join(project.path,project.files.flow);
var credsFilePath = getCredentialsFilename(flowFilePath);
promises.push(util.writeFile(flowFilePath,"[]"));
promises.push(util.writeFile(credsFilePath,"{}"));
files.push(project.files.flow);
files.push(project.files.credentials);
if (data.hasOwnProperty('files')) {
if (data.files.hasOwnProperty('flow') && data.files.hasOwnProperty('credentials')) {
project.files.flow = data.files.flow;
project.files.credentials = data.files.credentials;
var flowFilePath = fspath.join(project.path,project.files.flow);
var credsFilePath = getCredentialsFilename(flowFilePath);
promises.push(util.writeFile(flowFilePath,"[]"));
promises.push(util.writeFile(credsFilePath,"{}"));
files.push(project.files.flow);
files.push(project.files.credentials);
}
}
for (var file in defaultFileSet) {
if (defaultFileSet.hasOwnProperty(file)) {
promises.push(util.writeFile(fspath.join(project.path,file),defaultFileSet[file](project)));
var path = fspath.join(project.path,file);
if (!fs.existsSync(path)) {
promises.push(util.writeFile(path,defaultFileSet[file](project)));
}
}
}
@@ -740,7 +746,7 @@ Project.prototype.getCredentialsFileBackup = function() {
return getBackupFilename(this.getCredentialsFile());
}
Project.prototype.toJSON = function () {
Project.prototype.export = function () {
return {
name: this.name,
@@ -780,28 +786,18 @@ function getBackupFilename(filename) {
return fspath.join(ffDir,"."+ffName+".backup");
}
function checkProjectExists(project) {
var projectPath = fspath.join(projectsDir,project);
function checkProjectExists(projectPath) {
return fs.pathExists(projectPath).then(function(exists) {
if (!exists) {
var e = new Error("Project not found: "+project);
var e = new Error("Project not found");
e.code = "project_not_found";
e.project = project;
var name = fspath.basename(projectPath);
e.project = name;
throw e;
}
});
}
function createProjectDirectory(project) {
var projectPath = fspath.join(projectsDir,project);
return fs.ensureDir(projectPath);
}
function deleteProjectDirectory(project) {
var projectPath = fspath.join(projectsDir,project);
return fs.remove(projectPath);
}
function createDefaultProject(user, project) {
var projectPath = fspath.join(projectsDir,project.name);
// Create a basic skeleton of a project
@@ -904,17 +900,23 @@ function createProject(user, metadata) {
} else {
username = user.username;
}
if (!metadata.path) {
throw new Error("Project missing path property");
}
if (!metadata.name) {
throw new Error("Project missing name property");
}
var project = metadata.name;
var projectPath = metadata.path;
return new 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() {
fs.ensureDir(projectPath).then(function() {
var projects = settings.get('projects');
if (!projects) {
projects = {
@@ -951,7 +953,7 @@ function createProject(user, metadata) {
return createDefaultProject(user, metadata);
}
}).then(function() {
resolve(getProject(project))
resolve(loadProject(projectPath))
}).catch(function(err) {
fs.remove(projectPath,function() {
reject(err);
@@ -961,50 +963,21 @@ function createProject(user, metadata) {
})
}
function deleteProject(user, name) {
return checkProjectExists(name).then(function() {
if (currentProject && currentProject.name === name) {
var e = new Error("NLS: Can't delete the active project");
e.code = "cannot_delete_active_project";
throw e;
}
else {
return deleteProjectDirectory(name).then(function() {
var projects = settings.get('projects');
delete projects.projects[name];
return settings.set('projects', projects);
});
}
});
}
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(function(A,B) {
return A.toLowerCase().localeCompare(B.toLowerCase());
}).filter(function(fn) {
var fullPath = fspath.join(projectsDir,fn);
if (fn[0] != ".") {
var stats = fs.lstatSync(fullPath);
if (stats.isDirectory()) {
dirs.push(fn);
}
}
function deleteProject(user, projectPath) {
return checkProjectExists(projectPath).then(function() {
return fs.remove(projectPath).then(function() {
var name = fspath.basename(projectPath);
var projects = settings.get('projects');
delete projects.projects[name];
return settings.set('projects', projects);
});
return dirs;
});
}
function loadProject(projectPath) {
return checkProjectExists(projectPath).then(function() {
var project = new Project(projectPath);
return project.load();
});
}
@@ -1018,9 +991,7 @@ function init(_settings, _runtime) {
module.exports = {
init: init,
get: getProject,
load: loadProject,
create: createProject,
delete: deleteProject,
list: listProjects
delete: deleteProject
}

View File

@@ -48,7 +48,9 @@ function runGitCommand(args,cwd,env) {
var err = new Error(stderr);
err.stdout = stdout;
err.stderr = stderr;
if (/fatal: could not read/i.test(stderr)) {
if(/Connection refused/i.test(stderr)) {
err.code = "git_connection_failed";
} else if (/fatal: could not read/i.test(stderr)) {
// Username/Password
err.code = "git_auth_failed";
} else if(/HTTP Basic: Access denied/i.test(stderr)) {
@@ -58,8 +60,6 @@ function runGitCommand(args,cwd,env) {
} else if(/Host key verification failed/i.test(stderr)) {
// TODO: handle host key verification errors separately
err.code = "git_auth_failed";
} else if(/Connection refused/i.test(stderr)) {
err.code = "git_connection_failed";
} else if (/commit your changes or stash/i.test(stderr)) {
err.code = "git_local_overwrite";
} else if (/CONFLICT/.test(err.stdout)) {

View File

@@ -127,10 +127,20 @@ function init(_settings, _runtime) {
activeProject = globalSettings.projects.activeProject;
}
if (settings.flowFile) {
// if flowFile is a known project name - use it
if (globalSettings.projects.projects.hasOwnProperty(settings.flowFile)) {
activeProject = settings.flowFile;
globalSettings.projects.activeProject = settings.flowFile;
saveSettings = true;
} else {
// if it resolves to a dir - use it... but:
// - where to get credsecret from?
// - what if the name clashes with a known project?
// var stat = fs.statSync(settings.flowFile);
// if (stat && stat.isDirectory()) {
// activeProject = settings.flowFile;
// }
}
}
if (!activeProject) {
@@ -148,6 +158,24 @@ function init(_settings, _runtime) {
return Promise.resolve();
}
function listProjects() {
return fs.readdir(projectsDir).then(function(fns) {
var dirs = [];
fns.sort(function(A,B) {
return A.toLowerCase().localeCompare(B.toLowerCase());
}).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 getUserGitSettings(user) {
var userSettings = settings.getUserSettings(user)||{};
return userSettings.git;
@@ -160,7 +188,11 @@ function getBackupFilename(filename) {
}
function loadProject(name) {
return Projects.get(name).then(function(project) {
var projectPath = name;
if (projectPath.indexOf(fspath.sep) === -1) {
projectPath = fspath.join(projectsDir,name);
}
return Projects.load(projectPath).then(function(project) {
activeProject = project;
flowsFullPath = project.getFlowFile();
flowsFileBackup = project.getFlowFileBackup();
@@ -170,26 +202,20 @@ function loadProject(name) {
})
}
function listProjects(user) {
return Projects.list();
}
function getProject(user, name) {
checkActiveProject(name);
//return when.resolve(activeProject.info);
var username;
if (!user) {
username = "_";
} else {
username = user.username;
}
return Projects.get(name).then(function(project) {
return project.toJSON();
});
return Promise.resolve(activeProject.export());
}
function deleteProject(user, name) {
return Projects.delete(user, name);
if (activeProject && activeProject.name === name) {
var e = new Error("NLS: Can't delete the active project");
e.code = "cannot_delete_active_project";
throw e;
}
var projectPath = fspath.join(projectsDir,name);
return Projects.delete(user, projectPath);
}
function checkActiveProject(project) {
@@ -347,6 +373,7 @@ function createProject(user, metadata) {
metadata.files.oldCredentials = credentialsFile;
metadata.files.credentialSecret = currentEncryptionKey;
}
metadata.path = fspath.join(projectsDir,metadata.name);
return Projects.create(user, metadata).then(function(p) {
return setActiveProject(user, p.name);
}).then(function() {
@@ -479,6 +506,12 @@ function getFlows() {
error.code = "project_empty";
return when.reject(error);
}
if (activeProject.missingFiles && activeProject.missingFiles.indexOf('package.json') !== -1) {
log.warn("Project missing package.json");
error = new Error("Project missing package.json");
error.code = "missing_package_file";
return when.reject(error);
}
if (!activeProject.getFlowFile()) {
log.warn("Project has no flow file");
error = new Error("Project has no flow file");

View File

@@ -80,27 +80,26 @@ module.exports = {
*/
writeFile: function(path,content,backupPath) {
if (backupPath) {
try {
fs.renameSync(path,backupPath);
} catch(err) {
}
}
return when.promise(function(resolve,reject) {
var stream = fs.createWriteStream(path);
stream.on('open',function(fd) {
stream.write(content,'utf8',function() {
fs.fsync(fd,function(err) {
if (err) {
log.warn(log._("storage.localfilesystem.fsync-fail",{path: path, message: err.toString()}));
}
stream.end(resolve);
});
});
});
stream.on('error',function(err) {
reject(err);
});
});
if (fs.existsSync(path)) {
fs.renameSync(path,backupPath);
}
}
return when.promise(function(resolve,reject) {
var stream = fs.createWriteStream(path);
stream.on('open',function(fd) {
stream.write(content,'utf8',function() {
fs.fsync(fd,function(err) {
if (err) {
log.warn(log._("storage.localfilesystem.fsync-fail",{path: path, message: err.toString()}));
}
stream.end(resolve);
});
});
});
stream.on('error',function(err) {
reject(err);
});
});
},
readFile: readFile,