Skip to content

Commit

Permalink
Merge branch 'master' into runtime-api
Browse files Browse the repository at this point in the history
  • Loading branch information
knolleary committed Jul 30, 2018
2 parents 9d507b0 + 5155770 commit 06abe63
Showing 1 changed file with 117 additions and 101 deletions.
218 changes: 117 additions & 101 deletions red/runtime-registry/installer.js
Expand Up @@ -38,6 +38,8 @@ function init(runtime) {
log = runtime.log;
}

var activePromise = Promise.resolve();

function checkModulePath(folder) {
var moduleName;
var err;
Expand Down Expand Up @@ -73,79 +75,86 @@ function checkExistingModule(module,version) {
return false;
}
function installModule(module,version) {
//TODO: ensure module is 'safe'
return new Promise(function(resolve,reject) {
var installName = module;
var isUpgrade = false;
try {
if (moduleRe.test(module)) {
// Simple module name - assume it can be npm installed
if (version) {
installName += "@"+version;
activePromise = activePromise.then(() => {
//TODO: ensure module is 'safe'
return new Promise((resolve,reject) => {
var installName = module;
var isUpgrade = false;
try {
if (moduleRe.test(module)) {
// Simple module name - assume it can be npm installed
if (version) {
installName += "@"+version;
}
} else if (slashRe.test(module)) {
// A path - check if there's a valid package.json
installName = module;
module = checkModulePath(module);
}
} else if (slashRe.test(module)) {
// A path - check if there's a valid package.json
installName = module;
module = checkModulePath(module);
isUpgrade = checkExistingModule(module,version);
} catch(err) {
return reject(err);
}
isUpgrade = checkExistingModule(module,version);
} catch(err) {
return reject(err);
}
if (!isUpgrade) {
log.info(log._("server.install.installing",{name: module,version: version||"latest"}));
} else {
log.info(log._("server.install.upgrading",{name: module,version: version||"latest"}));
}

var installDir = settings.userDir || process.env.NODE_RED_HOME || ".";
var args = ['install','--save','--save-prefix="~"','--production',installName];
log.trace(npmCommand + JSON.stringify(args));
var child = child_process.spawn(npmCommand,args,{
cwd: installDir,
shell: true
});
var output = "";
child.stdout.on('data', (data) => {
output += data;
});
child.stderr.on('data', (data) => {
output += data;
});
child.on('close', (code) => {
if (code !== 0) {
var e;
var lookFor404 = new RegExp(" 404 .*"+module,"m");
var lookForVersionNotFound = new RegExp("version not found: "+module+"@"+version,"m");
if (lookFor404.test(output)) {
log.warn(log._("server.install.install-failed-not-found",{name:module}));
e = new Error("Module not found");
e.code = 404;
reject(e);
} else if (isUpgrade && lookForVersionNotFound.test(output)) {
log.warn(log._("server.install.upgrade-failed-not-found",{name:module}));
e = new Error("Module not found");
e.code = 404;
reject(e);
} else {
log.warn(log._("server.install.install-failed-long",{name:module}));
log.warn("------------------------------------------");
log.warn(output);
log.warn("------------------------------------------");
reject(new Error(log._("server.install.install-failed")));
}
if (!isUpgrade) {
log.info(log._("server.install.installing",{name: module,version: version||"latest"}));
} else {
if (!isUpgrade) {
log.info(log._("server.install.installed",{name:module}));
resolve(require("./index").addModule(module).then(reportAddedModules));
log.info(log._("server.install.upgrading",{name: module,version: version||"latest"}));
}

var installDir = settings.userDir || process.env.NODE_RED_HOME || ".";
var args = ['install','--save','--save-prefix="~"','--production',installName];
log.trace(npmCommand + JSON.stringify(args));
var child = child_process.spawn(npmCommand,args,{
cwd: installDir,
shell: true
});
var output = "";
child.stdout.on('data', (data) => {
output += data;
});
child.stderr.on('data', (data) => {
output += data;
});
child.on('close', (code) => {
if (code !== 0) {
var e;
var lookFor404 = new RegExp(" 404 .*"+module,"m");
var lookForVersionNotFound = new RegExp("version not found: "+module+"@"+version,"m");
if (lookFor404.test(output)) {
log.warn(log._("server.install.install-failed-not-found",{name:module}));
e = new Error("Module not found");
e.code = 404;
reject(e);
} else if (isUpgrade && lookForVersionNotFound.test(output)) {
log.warn(log._("server.install.upgrade-failed-not-found",{name:module}));
e = new Error("Module not found");
e.code = 404;
reject(e);
} else {
log.warn(log._("server.install.install-failed-long",{name:module}));
log.warn("------------------------------------------");
log.warn(output);
log.warn("------------------------------------------");
reject(new Error(log._("server.install.install-failed")));
}
} else {
log.info(log._("server.install.upgraded",{name:module, version:version}));
events.emit("runtime-event",{id:"restart-required",payload:{type:"warning",text:"notification.warnings.restartRequired"},retain:true});
resolve(require("./registry").setModulePendingUpdated(module,version));
if (!isUpgrade) {
log.info(log._("server.install.installed",{name:module}));
resolve(require("./index").addModule(module).then(reportAddedModules));
} else {
log.info(log._("server.install.upgraded",{name:module, version:version}));
events.emit("runtime-event",{id:"restart-required",payload:{type:"warning",text:"notification.warnings.restartRequired"},retain:true});
resolve(require("./registry").setModulePendingUpdated(module,version));
}
}
}
});
});
}).catch(err => {
// In case of error, reset activePromise to be resolvable
activePromise = Promise.resolve();
throw err;
});
return activePromise;
}


Expand Down Expand Up @@ -178,46 +187,53 @@ function reportRemovedModules(removedNodes) {
}

function uninstallModule(module) {
return new Promise(function(resolve,reject) {
if (/[\s;]/.test(module)) {
reject(new Error(log._("server.install.invalid")));
return;
}
var installDir = settings.userDir || process.env.NODE_RED_HOME || ".";
var moduleDir = path.join(installDir,"node_modules",module);
activePromise = activePromise.then(() => {
return new Promise((resolve,reject) => {
if (/[\s;]/.test(module)) {
reject(new Error(log._("server.install.invalid")));
return;
}
var installDir = settings.userDir || process.env.NODE_RED_HOME || ".";
var moduleDir = path.join(installDir,"node_modules",module);

try {
fs.statSync(moduleDir);
} catch(err) {
return reject(new Error(log._("server.install.uninstall-failed",{name:module})));
}
try {
fs.statSync(moduleDir);
} catch(err) {
return reject(new Error(log._("server.install.uninstall-failed",{name:module})));
}

var list = registry.removeModule(module);
log.info(log._("server.install.uninstalling",{name:module}));
var list = registry.removeModule(module);
log.info(log._("server.install.uninstalling",{name:module}));

var args = ['remove','--save',module];
log.trace(npmCommand + JSON.stringify(args));
var args = ['remove','--save',module];
log.trace(npmCommand + JSON.stringify(args));

var child = child_process.execFile(npmCommand,args,
{
cwd: installDir
},
function(err, stdin, stdout) {
if (err) {
log.warn(log._("server.install.uninstall-failed-long",{name:module}));
log.warn("------------------------------------------");
log.warn(err.toString());
log.warn("------------------------------------------");
reject(new Error(log._("server.install.uninstall-failed",{name:module})));
} else {
log.info(log._("server.install.uninstalled",{name:module}));
reportRemovedModules(list);
library.removeExamplesDir(module);
resolve(list);
var child = child_process.execFile(npmCommand,args,
{
cwd: installDir
},
function(err, stdin, stdout) {
if (err) {
log.warn(log._("server.install.uninstall-failed-long",{name:module}));
log.warn("------------------------------------------");
log.warn(err.toString());
log.warn("------------------------------------------");
reject(new Error(log._("server.install.uninstall-failed",{name:module})));
} else {
log.info(log._("server.install.uninstalled",{name:module}));
reportRemovedModules(list);
library.removeExamplesDir(module);
resolve(list);
}
}
}
);
);
});
}).catch(err => {
// In case of error, reset activePromise to be resolvable
activePromise = Promise.resolve();
throw err;
});
return activePromise;
}

function checkPrereq() {
Expand All @@ -230,7 +246,7 @@ function checkPrereq() {
paletteEditorEnabled = false;
return Promise.resolve();
} else {
return new Promise(function(resolve) {
return new Promise(resolve => {
child_process.execFile(npmCommand,['-v'],function(err) {
if (err) {
log.info(log._("server.palette-editor.npm-not-found"));
Expand Down

0 comments on commit 06abe63

Please sign in to comment.