From f75948b7e84ce430b4e5a5e6622349a62178d1cb Mon Sep 17 00:00:00 2001 From: Jared Allard Date: Mon, 1 Feb 2016 12:56:48 -0800 Subject: [PATCH] exe: use custom tar+gz extraction method, should fix #175 --- lib/exe.js | 179 ++++++++++++++++++++++------- package.json | 3 +- test/ignoreFlags-test/index.js | 19 +++ test/ignoreFlags-test/package.json | 15 +++ 4 files changed, 173 insertions(+), 43 deletions(-) create mode 100644 test/ignoreFlags-test/index.js create mode 100644 test/ignoreFlags-test/package.json diff --git a/lib/exe.js b/lib/exe.js index 022ada9..de0056f 100644 --- a/lib/exe.js +++ b/lib/exe.js @@ -26,8 +26,10 @@ var async = require("async"), outcome = require("outcome"), mkdirp = require("mkdirp"), request = require("request"), + gunzip = require("gunzip-maybe"), path = require("path"), fs = require("fs"), + tarstream = require('tar-stream'), colors = require('colors'), ncp = require("ncp").ncp, ProgressBar = require("progress"), @@ -36,7 +38,6 @@ var async = require("async"), bundle = require("./bundle"), embed = require("./embed"), os = require("os"), - targz = require('tar.gz'), _log = require("./log"), _monkeypatch = require("./monkeypatch"), spawn = child_process.spawn; @@ -355,10 +356,72 @@ function _downloadNode(version, directory, nodeConfigureArgs, nodeMakeArgs, comp */ function unzipNodeTarball (next) { + var onError = function(err) { + console.log(err.stack); + _log("error", "failed to extract the node source"); + process.exit(1); + } + if(isWin) { - _log("Extracting the .tar.gz."); - new targz().extract(nodeFilePath, nodeFileDir, next); + _log("extracting the node source [node-tar.gz]"); + + // tar-stream method w/ gunzip-maybe + var read = fs.createReadStream(nodeFilePath); + var extract = tarstream.extract() + var basedir = nodeFileDir; + + if(!fs.existsSync(nodeFileDir)) { + fs.mkdirSync(nodeFileDir); + } + + extract.on('entry', function(header, stream, callback) { + // header is the tar header + // stream is the content body (might be an empty stream) + // call next when you are done with this entry + + var absolutepath = path.join(basedir, header.name); + if(header.type === 'directory') { + // handle directories. + // console.log('dir:', header.name); + fs.mkdirSync(absolutepath); + return callback(); + } else if(header.type === 'file') { + // handle files + // console.log('file:', header.name); + } else { + console.log(header.type+':', header.name); + _log('warn', 'unhandled type in tar extraction, skipping'); + return callback(); + } + + var write = fs.createWriteStream(absolutepath); + + stream.pipe(write); + + write.on('close', function() { + return callback(); + }); + + stream.on('error', function(err) { + return onError(err); + }) + + write.on('error', function(err) { + return onError(err); + }); + + stream.resume() // just auto drain the stream + }) + + extract.on('finish', function() { + _log('extraction finished'); + return next(); + }) + + read.pipe(gunzip()).pipe(extract); } else { + _log("extracting the node source [native tar]"); + var cmd = ["tar", "-xf", nodeFilePath, "-C", nodeFileDir]; _log(cmd.join(" ")); @@ -366,12 +429,10 @@ function _downloadNode(version, directory, nodeConfigureArgs, nodeMakeArgs, comp tar.stdout.pipe(process.stdout); tar.stderr.pipe(process.stderr); - tar.on("close", function () { next(); }) - tar.on("error", function (err) { - console.log(err); - _log("error", "failed to extract the node tar file."); - process.exit(1); + tar.on("close", function () { + return next(); }); + tar.on("error", onError); } }, @@ -638,43 +699,77 @@ function _monkeyPatchChildProcess(compiler, complete) { function _monkeyPatchMainCc(compiler, complete) { var mainPath = path.join(compiler.dir, "src", "node.cc"); - _monkeypatch( - mainPath, - function (content) { - return ~content.indexOf('// // TODO use parse opts'); - }, - function (content, next) { // TODO: failsafe this - var lines = content.split('\n'); - var endLine = lines.indexOf(' option_end_index = i;'); // pre node 0.11.6 compat + var mainC = fs.readFileSync(mainPath, {encoding: 'utf8'}); - if(endLine !== -1) { // check if it succedded or not. - lines[endLine] = ' option_end_index = 1;'; - _log("patched node.cc") - } + // content split, and original start/end + var constant_loc = 1; + var lines = mainC.split('\n'); + var startLine = lines.indexOf(' // TODO use parse opts'); + var endLine = lines.indexOf(' option_end_index = i;'); // pre node 0.11.6 compat + var isPatched = lines.indexOf('// NEXE_PATCH_IGNOREFLAGS'); - /** - * This is the new method of passing the args. Tested on node.js 0.12.5 - * and iojs 2.3.1 - **/ - if(endLine === -1) { // only if the pre-0.12.5 failed. - var startLine = lines.indexOf(' while (index < nargs && argv[index][0] == \'-\') {'); // beginning of the function - endLine = lines.indexOf(' // Copy remaining arguments.'); - endLine = endLine-1; // space, then it's at the } + if(isPatched !== -1) { + _log('already patched node.cc'); + return complete(); + } - // remove the offending lines - if(startLine !== -1) { - for (var i = startLine; i < endLine; i++) { - lines[i] = undefined; // set the value to undefined so it's skipped by the join - } - _log('patched node.cc'); - } - } + /** + * This is the new method of passing the args. Tested on node.js 0.12.5 + * and iojs 2.3.1 + **/ + if(endLine === -1 && startLine === -1) { // only if the pre-0.12.5 failed. + _log("using the after 0.12.5 method of ignoring flags."); - lines = lines.join('\n'); - next(null, lines); - }, - complete - ); + startLine = lines.indexOf(" while (index < nargs && argv[index][0] == '-') {"); // beginning of the function + endLine = lines.indexOf(' // Copy remaining arguments.'); + endLine--; // space, then it's at the } + + constant_loc = lines.length+1; + } else { + _log('using 0.10.x > method of ignoring flags'); + lines[endLine] = ' option_end_index = 1;'; + } + + /** + * This is the method for 5.5.0 + **/ + if(endLine === -1 || startLine === -1) { + _log("using the after 5.5.0 method of ignoring flags."); + + startLine = lines.indexOf(" while (index < nargs && argv[index][0] == '-' && !short_circuit) {"); // beginning of the function + endLine = lines.indexOf(' // Copy remaining arguments.'); + endLine--; // space, then it's at the } + + constant_loc = lines.length+1; + } + + // other versions here. + if(endLine === -1 || startLine === -1) { // failsafe. + _log("error", "Failed to find a way to patch node.cc to ignoreFlags"); + _log("startLine =", startLine, '| endLine =', endLine); + process.exit(1); + } + + // check if it's been done + lines[constant_loc] = '// NEXE_PATCH_IGNOREFLAGS'; + + for (var i = startLine; i < endLine; i++) { + lines[i] = undefined; // set the value to undefined so it's skipped by the join + } + + _log('patched node.cc'); + + finalContents = lines.join('\n'); + + // write the file contents + fs.writeFile(mainPath, finalContents, {encoding: 'utf8'}, function(err) { + if(err) { + _log('error', 'failed to write to', mainPath); + return process.exit(1); + } + + return complete(); + }); } /** @@ -729,7 +824,7 @@ SetFlagsFromString(nexevargs, nexevargslen);\n\ dontCombine; if(lineToInjectAfter !== -1 && haveWeInjectedBefore === -1) { - _log('injecting v8 args c++'); + _log('injecting v8/flags.cc'); // super debug // _log('v8 injection determined by', lastInjectionLine); diff --git a/package.json b/package.json index d477c7a..3d8503d 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "builtins": "1.0.3", "colors": "^1.1.2", "glob": "^6.0.4", + "gunzip-maybe": "^1.3.1", "insert-module-globals": "^7.0.1", "mkdirp": "^0.5.1", "module-deps": "^4.0.5", @@ -31,7 +32,7 @@ "request": "^2.67.0", "sprintf": "~0.1.5", "step": "0.0.x", - "tar.gz": "1.0.2", + "tar-stream": "^1.3.1", "yargs": "^3.32.0" }, "nexe": { diff --git a/test/ignoreFlags-test/index.js b/test/ignoreFlags-test/index.js new file mode 100644 index 0000000..4facaa7 --- /dev/null +++ b/test/ignoreFlags-test/index.js @@ -0,0 +1,19 @@ +/** + * Test to verify if we support strict mode (flags) + * + * @author Jared Allard + * @version 0.0.1 + * @license MIT + **/ + + // test.nex --help + + var status = false; + + // console.log(process.argv); + + if(process.argv[2]) { + status = true; + } + + console.log('test:ignoreFlags:status =', status); diff --git a/test/ignoreFlags-test/package.json b/test/ignoreFlags-test/package.json new file mode 100644 index 0000000..09c705b --- /dev/null +++ b/test/ignoreFlags-test/package.json @@ -0,0 +1,15 @@ +{ + "name": "flags-test", + "nexe": { + "input": "./index.js", + "output": "test.nex", + "temp": "src", + "runtime": { + "framework": "node", + "version": "5.5.0", + "ignoreFlags": true, + "node-args": "" + } + }, + "dependencies": {} +}