mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Add event log to editor
Shows output from git pull/push and npm install in the editor
This commit is contained in:
@@ -42,6 +42,21 @@ function handleRuntimeEvent(event) {
|
||||
runtime.log.trace("runtime event: "+JSON.stringify(event));
|
||||
publish("notification/"+event.id,event.payload||{},event.retain);
|
||||
}
|
||||
function handleEventLog(event) {
|
||||
var type = event.payload.type;
|
||||
var id = event.id;
|
||||
if (event.payload.data) {
|
||||
var data = event.payload.data;
|
||||
if (data.endsWith('\n')) {
|
||||
data = data.substring(0,data.length-1);
|
||||
}
|
||||
var lines = data.split(/\n/);
|
||||
lines.forEach(line => {
|
||||
runtime.log.debug((type?("["+type+"] "):"")+line)
|
||||
})
|
||||
}
|
||||
publish("event-log/"+event.id,event.payload||{});
|
||||
}
|
||||
|
||||
function publish(topic,data,retain) {
|
||||
if (retain) {
|
||||
@@ -64,6 +79,8 @@ var api = module.exports = {
|
||||
runtime.events.on("runtime-event",handleRuntimeEvent);
|
||||
runtime.events.removeListener("comms",handleCommsEvent);
|
||||
runtime.events.on("comms",handleCommsEvent);
|
||||
runtime.events.removeListener("event-log",handleEventLog);
|
||||
runtime.events.on("event-log",handleEventLog);
|
||||
},
|
||||
|
||||
/**
|
||||
|
69
packages/node_modules/@node-red/runtime/lib/exec.js
vendored
Normal file
69
packages/node_modules/@node-red/runtime/lib/exec.js
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
const child_process = require('child_process');
|
||||
const { util } = require('@node-red/util');
|
||||
|
||||
var events;
|
||||
|
||||
function logLines(id,type,data) {
|
||||
events.emit("event-log", {id:id,payload:{ts: Date.now(),data:data,type:type}});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtime) {
|
||||
events = _runtime.events;
|
||||
},
|
||||
run: function(command,args,options,emit) {
|
||||
var invocationId = util.generateId();
|
||||
|
||||
emit && events.emit("event-log", {ts: Date.now(),id:invocationId,payload:{ts: Date.now(),data:command+" "+args.join(" ")}});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
const child = child_process.spawn(command,args,options);
|
||||
child.stdout.on('data', (data) => {
|
||||
const str = ""+data;
|
||||
stdout += str;
|
||||
emit && logLines(invocationId,"out",str);
|
||||
});
|
||||
child.stderr.on('data', (data) => {
|
||||
const str = ""+data;
|
||||
stderr += str;
|
||||
emit && logLines(invocationId,"err",str);
|
||||
});
|
||||
child.on('error', function(err) {
|
||||
stderr = err.toString();
|
||||
emit && logLines(invocationId,"err",stderr);
|
||||
})
|
||||
child.on('close', (code) => {
|
||||
let result = {
|
||||
code: code,
|
||||
stdout: stdout,
|
||||
stderr: stderr
|
||||
}
|
||||
emit && events.emit("event-log", {id:invocationId,payload:{ts: Date.now(),data:"rc="+code}});
|
||||
|
||||
if (code === 0) {
|
||||
resolve(result)
|
||||
} else {
|
||||
reject(result);
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
@@ -23,6 +23,7 @@ var storage = require("./storage");
|
||||
var library = require("./library");
|
||||
var events = require("./events");
|
||||
var settings = require("./settings");
|
||||
var exec = require("./exec");
|
||||
|
||||
var express = require("express");
|
||||
var path = require('path');
|
||||
@@ -71,6 +72,7 @@ function init(userSettings,_redUtil,_adminApi) {
|
||||
redNodes.init(runtime);
|
||||
library.init(runtime);
|
||||
externalAPI.init(runtime);
|
||||
exec.init(runtime);
|
||||
}
|
||||
|
||||
var version;
|
||||
@@ -248,6 +250,7 @@ var runtime = {
|
||||
events: events,
|
||||
nodes: redNodes,
|
||||
library: library,
|
||||
exec: exec,
|
||||
util: require("@node-red/util").util,
|
||||
get adminApi() { return adminApi },
|
||||
get nodeApp() { return nodeApp },
|
||||
|
@@ -15,8 +15,9 @@
|
||||
**/
|
||||
|
||||
var when = require('when');
|
||||
var exec = require('child_process').exec;
|
||||
var spawn = require('child_process').spawn;
|
||||
|
||||
var exec = require("../../../../exec");
|
||||
|
||||
var authResponseServer = require('./authServer').ResponseServer;
|
||||
var sshResponseServer = require('./authServer').ResponseSSHServer;
|
||||
var clone = require('clone');
|
||||
@@ -26,83 +27,70 @@ var gitCommand = "git";
|
||||
var gitVersion;
|
||||
var log;
|
||||
|
||||
function runGitCommand(args,cwd,env) {
|
||||
function runGitCommand(args,cwd,env,emit) {
|
||||
log.trace(gitCommand + JSON.stringify(args));
|
||||
return when.promise(function(resolve,reject) {
|
||||
args.unshift("credential.helper=")
|
||||
args.unshift("-c");
|
||||
var child = spawn(gitCommand, args, {cwd:cwd, detached:true, env:env});
|
||||
var stdout = "";
|
||||
var stderr = "";
|
||||
child.stdout.on('data', function(data) {
|
||||
stdout += data;
|
||||
});
|
||||
child.stderr.on('data', function(data) {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('error', function(err) {
|
||||
stderr = err.toString();
|
||||
})
|
||||
child.on('close', function(code) {
|
||||
if (code !== 0) {
|
||||
var err = new Error(stderr);
|
||||
err.stdout = stdout;
|
||||
err.stderr = stderr;
|
||||
if (/Connection refused/i.test(stderr)) {
|
||||
err.code = "git_connection_failed";
|
||||
} else if (/Connection timed out/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)) {
|
||||
err.code = "git_auth_failed";
|
||||
} else if(/Permission denied \(publickey\)/i.test(stderr)) {
|
||||
err.code = "git_auth_failed";
|
||||
} else if(/Host key verification failed/i.test(stderr)) {
|
||||
// TODO: handle host key verification errors separately
|
||||
err.code = "git_auth_failed";
|
||||
} else if (/commit your changes or stash/i.test(stderr)) {
|
||||
err.code = "git_local_overwrite";
|
||||
} else if (/CONFLICT/.test(err.stdout)) {
|
||||
err.code = "git_pull_merge_conflict";
|
||||
} else if (/not fully merged/i.test(stderr)) {
|
||||
err.code = "git_delete_branch_unmerged";
|
||||
} else if (/remote .* already exists/i.test(stderr)) {
|
||||
err.code = "git_remote_already_exists";
|
||||
} else if (/does not appear to be a git repository/i.test(stderr)) {
|
||||
err.code = "git_not_a_repository";
|
||||
} else if (/Repository not found/i.test(stderr)) {
|
||||
err.code = "git_repository_not_found";
|
||||
} else if (/repository '.*' does not exist/i.test(stderr)) {
|
||||
err.code = "git_repository_not_found";
|
||||
} else if (/refusing to merge unrelated histories/i.test(stderr)) {
|
||||
err.code = "git_pull_unrelated_history"
|
||||
} else if (/Please tell me who you are/i.test(stderr)) {
|
||||
err.code = "git_missing_user";
|
||||
} else if (/name consists only of disallowed characters/i.test(stderr)) {
|
||||
err.code = "git_missing_user";
|
||||
}
|
||||
return reject(err);
|
||||
}
|
||||
resolve(stdout);
|
||||
});
|
||||
});
|
||||
args.unshift("credential.helper=")
|
||||
args.unshift("-c");
|
||||
return exec.run(gitCommand, args, {cwd:cwd, env:env}, emit).then(result => {
|
||||
return result.stdout;
|
||||
}).catch(result => {
|
||||
var err = new Error(stderr);
|
||||
var stdout = result.stdout;
|
||||
var stderr = result.stderr;
|
||||
err.stdout = stdout;
|
||||
err.stderr = stderr;
|
||||
if (/Connection refused/i.test(stderr)) {
|
||||
err.code = "git_connection_failed";
|
||||
} else if (/Connection timed out/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)) {
|
||||
err.code = "git_auth_failed";
|
||||
} else if(/Permission denied \(publickey\)/i.test(stderr)) {
|
||||
err.code = "git_auth_failed";
|
||||
} else if(/Host key verification failed/i.test(stderr)) {
|
||||
// TODO: handle host key verification errors separately
|
||||
err.code = "git_auth_failed";
|
||||
} else if (/commit your changes or stash/i.test(stderr)) {
|
||||
err.code = "git_local_overwrite";
|
||||
} else if (/CONFLICT/.test(err.stdout)) {
|
||||
err.code = "git_pull_merge_conflict";
|
||||
} else if (/not fully merged/i.test(stderr)) {
|
||||
err.code = "git_delete_branch_unmerged";
|
||||
} else if (/remote .* already exists/i.test(stderr)) {
|
||||
err.code = "git_remote_already_exists";
|
||||
} else if (/does not appear to be a git repository/i.test(stderr)) {
|
||||
err.code = "git_not_a_repository";
|
||||
} else if (/Repository not found/i.test(stderr)) {
|
||||
err.code = "git_repository_not_found";
|
||||
} else if (/repository '.*' does not exist/i.test(stderr)) {
|
||||
err.code = "git_repository_not_found";
|
||||
} else if (/refusing to merge unrelated histories/i.test(stderr)) {
|
||||
err.code = "git_pull_unrelated_history"
|
||||
} else if (/Please tell me who you are/i.test(stderr)) {
|
||||
err.code = "git_missing_user";
|
||||
} else if (/name consists only of disallowed characters/i.test(stderr)) {
|
||||
err.code = "git_missing_user";
|
||||
}
|
||||
throw err;
|
||||
})
|
||||
}
|
||||
function runGitCommandWithAuth(args,cwd,auth) {
|
||||
function runGitCommandWithAuth(args,cwd,auth,emit) {
|
||||
return authResponseServer(auth).then(function(rs) {
|
||||
var commandEnv = clone(process.env);
|
||||
commandEnv.GIT_ASKPASS = path.join(__dirname,"node-red-ask-pass.sh");
|
||||
commandEnv.NODE_RED_GIT_NODE_PATH = process.execPath;
|
||||
commandEnv.NODE_RED_GIT_SOCK_PATH = rs.path;
|
||||
commandEnv.NODE_RED_GIT_ASKPASS_PATH = path.join(__dirname,"authWriter.js");
|
||||
return runGitCommand(args,cwd,commandEnv).finally(function() {
|
||||
return runGitCommand(args,cwd,commandEnv,emit).finally(function() {
|
||||
rs.close();
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function runGitCommandWithSSHCommand(args,cwd,auth) {
|
||||
function runGitCommandWithSSHCommand(args,cwd,auth,emit) {
|
||||
return sshResponseServer(auth).then(function(rs) {
|
||||
var commandEnv = clone(process.env);
|
||||
commandEnv.SSH_ASKPASS = path.join(__dirname,"node-red-ask-pass.sh");
|
||||
@@ -116,7 +104,7 @@ function runGitCommandWithSSHCommand(args,cwd,auth) {
|
||||
// GIT_SSH_COMMAND - added in git 2.3.0
|
||||
commandEnv.GIT_SSH_COMMAND = "ssh -i " + auth.key_path + " -F /dev/null";
|
||||
// console.log('commandEnv:', commandEnv);
|
||||
return runGitCommand(args,cwd,commandEnv).finally(function() {
|
||||
return runGitCommand(args,cwd,commandEnv,emit).finally(function() {
|
||||
rs.close();
|
||||
});
|
||||
})
|
||||
@@ -448,13 +436,13 @@ module.exports = {
|
||||
var promise;
|
||||
if (auth) {
|
||||
if ( auth.key_path ) {
|
||||
promise = runGitCommandWithSSHCommand(args,cwd,auth);
|
||||
promise = runGitCommandWithSSHCommand(args,cwd,auth,true);
|
||||
}
|
||||
else {
|
||||
promise = runGitCommandWithAuth(args,cwd,auth);
|
||||
promise = runGitCommandWithAuth(args,cwd,auth,true);
|
||||
}
|
||||
} else {
|
||||
promise = runGitCommand(args,cwd)
|
||||
promise = runGitCommand(args,cwd,undefined,true)
|
||||
}
|
||||
return promise;
|
||||
// .catch(function(err) {
|
||||
@@ -485,13 +473,13 @@ module.exports = {
|
||||
var promise;
|
||||
if (auth) {
|
||||
if ( auth.key_path ) {
|
||||
promise = runGitCommandWithSSHCommand(args,cwd,auth);
|
||||
promise = runGitCommandWithSSHCommand(args,cwd,auth,true);
|
||||
}
|
||||
else {
|
||||
promise = runGitCommandWithAuth(args,cwd,auth);
|
||||
promise = runGitCommandWithAuth(args,cwd,auth,true);
|
||||
}
|
||||
} else {
|
||||
promise = runGitCommand(args,cwd)
|
||||
promise = runGitCommand(args,cwd,undefined,true)
|
||||
}
|
||||
return promise.catch(function(err) {
|
||||
if (err.code === 'git_error') {
|
||||
@@ -517,13 +505,13 @@ module.exports = {
|
||||
args.push(".");
|
||||
if (auth) {
|
||||
if ( auth.key_path ) {
|
||||
return runGitCommandWithSSHCommand(args,cwd,auth);
|
||||
return runGitCommandWithSSHCommand(args,cwd,auth,true);
|
||||
}
|
||||
else {
|
||||
return runGitCommandWithAuth(args,cwd,auth);
|
||||
return runGitCommandWithAuth(args,cwd,auth,true);
|
||||
}
|
||||
} else {
|
||||
return runGitCommand(args,cwd);
|
||||
return runGitCommand(args,cwd,undefined,true);
|
||||
}
|
||||
},
|
||||
getStatus: getStatus,
|
||||
|
Reference in New Issue
Block a user