-
-
Notifications
You must be signed in to change notification settings - Fork 134
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: add node part of git extension into phoenix node core
- Loading branch information
Showing
10 changed files
with
469 additions
and
150 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
const gitNodeConnector = global.createNodeConnector("phcode-git-core", exports); | ||
|
||
const GIT_PROGRESS_EVENT = "git_progress"; | ||
|
||
let ChildProcess = require("child_process"), | ||
crossSpawn = require('cross-spawn'), | ||
ProcessUtils = require("./processUtils"), | ||
processMap = {}, | ||
resolvedPaths = {}; | ||
|
||
function fixEOL(str) { | ||
if (str[str.length - 1] === "\n") { | ||
str = str.slice(0, -1); | ||
} | ||
return str; | ||
} | ||
|
||
// handler with ChildProcess.exec | ||
// this won't handle cases where process outputs a large string | ||
function execute(directory, command, args, opts, callback) { | ||
// execute commands have to be escaped, spawn does this automatically and will fail if cmd is escaped | ||
if (command[0] !== "\"" || command[command.length - 1] !== "\"") { | ||
command = "\"" + command + "\""; | ||
} | ||
// http://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback | ||
const toExec = command + " " + args.join(" "); | ||
processMap[opts.cliId] = ChildProcess.exec(toExec, { | ||
cwd: directory, | ||
maxBuffer: 20 * 1024 * 1024 | ||
}, function (err, stdout, stderr) { | ||
delete processMap[opts.cliId]; | ||
callback(err ? fixEOL(stderr) : undefined, err ? undefined : fixEOL(stdout)); | ||
}); | ||
} | ||
|
||
// handler with cross-spawn | ||
function join(arr) { | ||
let result, index = 0, length; | ||
length = arr.reduce(function (l, b) { | ||
return l + b.length; | ||
}, 0); | ||
result = new Buffer(length); | ||
arr.forEach(function (b) { | ||
b.copy(result, index); | ||
index += b.length; | ||
}); | ||
return fixEOL(result.toString("utf8")); | ||
} | ||
|
||
function spawn(directory, command, args, opts, callback) { | ||
// https://github.com/creationix/node-git | ||
const child = crossSpawn(command, args, { | ||
cwd: directory | ||
}); | ||
child.on("error", function (err) { | ||
callback(err.stack, undefined); | ||
}); | ||
|
||
processMap[opts.cliId] = child; | ||
|
||
let exitCode, stdout = [], stderr = []; | ||
child.stdout.addListener("data", function (text) { | ||
stdout[stdout.length] = text; | ||
}); | ||
child.stderr.addListener("data", function (text) { | ||
// Git writes its informational messages (such as Successfully rebased | ||
// and updated) to stderr. This behavior is intentional because Git uses | ||
// stderr for all output that is not a direct result of the command (e.g., | ||
// status updates, progress, or errors). | ||
if (opts.watchProgress) { | ||
gitNodeConnector.triggerPeer(GIT_PROGRESS_EVENT, { | ||
cliId: opts.cliId, | ||
time: (new Date()).getTime(), | ||
data: fixEOL(text.toString("utf8")) | ||
}); | ||
} | ||
stderr[stderr.length] = text; | ||
}); | ||
child.addListener("exit", function (code) { | ||
exitCode = code; | ||
}); | ||
child.addListener("close", function () { | ||
delete processMap[opts.cliId]; | ||
callback(exitCode > 0 ? join(stderr) : undefined, | ||
exitCode > 0 ? undefined : join(stdout)); | ||
}); | ||
child.stdin.end(); | ||
} | ||
|
||
function doIfExists(method, directory, command, args, opts, callback) { | ||
// do not call executableExists if we already know it exists | ||
if (resolvedPaths[command]) { | ||
return method(directory, resolvedPaths[command], args, opts, callback); | ||
} | ||
|
||
ProcessUtils.executableExists(command, function (err, exists, resolvedPath) { | ||
if (exists) { | ||
resolvedPaths[command] = resolvedPath; | ||
return method(directory, resolvedPath, args, opts, callback); | ||
} else { | ||
callback("ProcessUtils can't resolve the path requested: " + command); | ||
} | ||
}); | ||
} | ||
|
||
function executeIfExists({directory, command, args, opts}) { | ||
return new Promise(function (resolve, reject) { | ||
doIfExists(execute, directory, command, args, opts, (err, stdout)=>{ | ||
if(err){ | ||
reject(err); | ||
} else { | ||
resolve(stdout); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
function spawnIfExists({directory, command, args, opts}) { | ||
return new Promise(function (resolve, reject) { | ||
doIfExists(spawn, directory, command, args, opts, (err, stdout)=>{ | ||
if(err){ | ||
reject(err); | ||
} else { | ||
resolve(stdout); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
function kill(cliId) { | ||
return new Promise(function (resolve, reject) { | ||
const process = processMap[cliId]; | ||
if (!process) { | ||
reject("Couldn't find process to kill with ID:" + cliId); | ||
} | ||
delete processMap[cliId]; | ||
resolve(""); // at this point we resolve anyways as we cant do anything after deleting the object | ||
ProcessUtils.getChildrenOfPid(process.pid, function (err, children) { | ||
// kill also parent process | ||
children.push(process.pid); | ||
children.forEach(function (pid) { | ||
ProcessUtils.killSingleProcess(pid); | ||
}); | ||
}); | ||
}); | ||
} | ||
|
||
function which({command}) { | ||
return new Promise(function (resolve, reject) { | ||
ProcessUtils.executableExists(command, function (err, exists, resolvedPath) { | ||
if (exists) { | ||
resolve(resolvedPath); | ||
} else { | ||
reject("ProcessUtils can't resolve the path requested: " + command); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
exports.execute = executeIfExists; | ||
exports.spawn = spawnIfExists; | ||
exports.kill = kill; | ||
exports.which = which; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
const ProcessUtils = require("./processUtils"); | ||
|
||
/* | ||
var pid = 5064; | ||
ProcessUtils.getChildrenOfPid(pid, function (err, children) { | ||
console.log(children); | ||
children.push(pid); | ||
children.forEach(function (pid) { | ||
ProcessUtils.killSingleProcess(pid); | ||
}); | ||
}); | ||
*/ | ||
|
||
[ | ||
"git", | ||
"C:\\Program Files (x86)\\Git\\cmd\\git.exe", | ||
"C:/Program Files (x86)/Git/cmd/git.exe", | ||
"C:/Program Files (x86)/Git/cmd/git2.exe", | ||
"C:/Program Files (x86)/Git/cmd/", | ||
"C:/Program Files (x86)/Git/cmd", | ||
"C:\\Program Files (x86)\\Git\\Git Bash.vbs" | ||
].forEach(function (path) { | ||
|
||
ProcessUtils.executableExists(path, function (err, exists, resolvedPath) { | ||
console.log("ProcessUtils.executableExists for: " + path); | ||
console.log(" - exists: " + exists); | ||
console.log(" - resolvedPath: " + resolvedPath); | ||
}); | ||
|
||
}); | ||
|
||
/* | ||
ProcessUtils.executableExists("git", function (err, result, resolvedPath) { | ||
console.log("git"); | ||
console.log(result); | ||
}); | ||
ProcessUtils.executableExists("C:\\Program Files (x86)\\Git\\cmd\\git.exe", function (err, result) { | ||
console.log("result for C:\\Program Files (x86)\\Git\\cmd\\git.exe"); | ||
console.log(result); | ||
}); | ||
ProcessUtils.executableExists("C:/Program Files (x86)/Git/cmd/git.exe", function (err, result) { | ||
console.log("result for C:/Program Files (x86)/Git/cmd/git.exe"); | ||
console.log(result); | ||
}); | ||
ProcessUtils.executableExists("C:/Program Files (x86)/Git/cmd/git2.exe", function (err, result) { | ||
console.log("result for C:/Program Files (x86)/Git/cmd/git2.exe"); | ||
console.log(result); | ||
}); | ||
ProcessUtils.executableExists("C:/Program Files (x86)/Git/cmd/", function (err, result) { | ||
console.log("result for C:/Program Files (x86)/Git/cmd/"); | ||
console.log(result); | ||
}); | ||
ProcessUtils.executableExists("C:/Program Files (x86)/Git/cmd", function (err, result) { | ||
console.log("result for C:/Program Files (x86)/Git/cmd"); | ||
console.log(result); | ||
}); | ||
*/ |
Oops, something went wrong.