From 9c5da9dd23d39a1a91c98ba447bacc3b176cdf66 Mon Sep 17 00:00:00 2001 From: isaacs Date: Sat, 23 Oct 2010 18:46:59 -0700 Subject: More "programmatic npm" updates. Building more upon the patch from Charlie Robbins (d7c69821a01c8327f5468fe7a115f2537f908da9), these changes remove any way of npm actually triggering a program exit than by being called by the cli. - Move the "exit" option off the opts object and onto a proper config setting. Why not? - Use \r\n for most output, so that it'll look correct in the repl, or other places where \n may not be enough. - Add a comment about loading npm programmatically. --- cli.js | 29 +++++++++++++++-------------- lib/ls.js | 2 +- lib/utils/default-config.js | 2 +- lib/utils/error-handler.js | 27 ++++++++++++++++----------- lib/utils/log.js | 2 +- lib/utils/prompt.js | 1 + npm.js | 15 ++++++--------- 7 files changed, 41 insertions(+), 37 deletions(-) diff --git a/cli.js b/cli.js index a387c7377..90d3deb09 100755 --- a/cli.js +++ b/cli.js @@ -51,7 +51,7 @@ var vindex = arglist.indexOf("-v") , printVersion = vindex !== -1 || conf.version if (printVersion) { sys.puts(npm.version) - if (vindex !== -1) arglist.splice(vindex, 1) + process.exit(0) } else log("npm@"+npm.version, "using") // make sure that this version of node works with this version of npm. @@ -59,22 +59,23 @@ var semver = require("./lib/utils/semver") , nodeVer = process.version , reqVer = npm.nodeVersionRequired if (reqVer && !semver.satisfies(nodeVer, reqVer)) { - var badNodeVersion = new Error( - "npm doesn't work with node " + nodeVer + "\nRequired: node@" + reqVer) - throw badNodeVersion + errorHandler(new Error( + "npm doesn't work with node " + nodeVer + "\nRequired: node@" + reqVer), true) } process.on("uncaughtException", errorHandler) -if (!command && !printVersion) conf.usage = true +if (!command) conf.usage = true -if (printVersion) itWorked = true -else { - if (conf.usage && command !== "help") { - arglist.unshift(command) - command = "help" - } - npm.load({ conf: conf, exit: true }, function (err, loaded) { - npm.commands[command](arglist, errorHandler) - }); +if (conf.usage && command !== "help") { + arglist.unshift(command) + command = "help" } + +// now actually fire up npm and run the command. +// this is how to use npm programmatically: +conf._exit = true +npm.load(conf, function (er) { + if (er) return errorHandler(er) + npm.commands[command](arglist, errorHandler) +}) diff --git a/lib/ls.js b/lib/ls.js index 58174da21..ebc464d7e 100755 --- a/lib/ls.js +++ b/lib/ls.js @@ -90,7 +90,7 @@ function prettify (data, args) { }) if (!pretty.length) pretty = ["Nothing found"] pretty.push("") - return pretty.join("\n") + return pretty.join("\r\n") } function merge (installed, remote) { var merged = {} diff --git a/lib/utils/default-config.js b/lib/utils/default-config.js index a55c5fb95..6a16ab186 100644 --- a/lib/utils/default-config.js +++ b/lib/utils/default-config.js @@ -27,7 +27,7 @@ module.exports = , manroot : path.join(process.execPath, "..", "..", "share", "man") , editor : process.env.EDITOR , tmproot : (process.env.TMPDIR || "/tmp") - + , _exit : true // // TODO: Fix when node's SSL client can upload properly. // , registry : hasSSL ? "https://registry.npmjs.org/" diff --git a/lib/utils/error-handler.js b/lib/utils/error-handler.js index d5e66e31a..2bc081354 100644 --- a/lib/utils/error-handler.js +++ b/lib/utils/error-handler.js @@ -11,16 +11,16 @@ var cbCalled = false try { constants = require("constants") } catch (ex) { constants = process } -process.on("exit", function () { if (!itWorked) log.win("not ok") }) +process.on("exit", function (code) { + if (code) itWorked = false + log.win(itWorked ? "ok" : "not ok") + itWorked = false // ready for next exit +}) -function errorHandler (er, doExit) { +function errorHandler (er) { if (cbCalled) throw new Error("Callback called more than once.") cbCalled = true - if (!er) { - itWorked = true - log.win("ok") - return exit(doExit) - } + if (!er) return exit(0) log.error(er) if (!(er instanceof Error)) return exit(1) if (!er.errno) { @@ -70,10 +70,15 @@ function errorHandler (er, doExit) { ,"Just tweeting a tiny part of the error will not be helpful." ].join("\n")) } - exit(doExit, 1) + exit(typeof error.errno === "number" ? err.errno : 1) } -function exit (doExit, code) { - doExit = doExit || true - rm(npm.tmp, function () { if (doExit) process.exit(code || 0) }) +function exit (code) { + var doExit = npm.config.get("_exit") + log.verbose([code, doExit], "exit") + rm(npm.tmp, function () { + itWorked = !code + if (doExit) process.exit(code || 0) + else process.emit("exit", code || 0) + }) } diff --git a/lib/utils/log.js b/lib/utils/log.js index 1e116cd90..07e8e3e12 100644 --- a/lib/utils/log.js +++ b/lib/utils/log.js @@ -138,7 +138,7 @@ function log (msg, pref, level, cb) { msg = msg.split(/\n/).join("\n"+pref+" ") } msg = pref+" "+msg - sys.error(msg) + sys.error(msg.split(/\n/).join("\r\n") + "\r") cb && cb() } var spaces = " " diff --git a/lib/utils/prompt.js b/lib/utils/prompt.js index 4669796da..5035caece 100644 --- a/lib/utils/prompt.js +++ b/lib/utils/prompt.js @@ -24,6 +24,7 @@ function read (def, cb) { stdin.on("data", function D (chunk) { val += buffer + chunk buffer = "" + val = val.replace(/\r/g, '') if (val.indexOf("\n") !== -1) { if (val !== "\n") val = val.replace(/^\n+/, "") buffer = val.substr(val.indexOf("\n")) diff --git a/npm.js b/npm.js index ccd7365c3..007589c06 100644 --- a/npm.js +++ b/npm.js @@ -8,7 +8,6 @@ var npm = exports , ini = require("./lib/utils/ini") , log = require("./lib/utils/log") , fs = require("./lib/utils/graceful-fs") - , errorHandler = require("./lib/utils/error-handler") , path = require("path") npm.commands = {} @@ -69,17 +68,15 @@ var commandCache = {} }, enumerable: true}) }) -npm.load = function (opts, cb) { +var loaded = false +npm.load = function (conf, cb) { + if (!cb && typeof conf === "function") cb = conf , conf = {} + if (loaded) return cb() + loaded = true // don't assume that npm is installed in any particular spot, since this // might conceivably be a bootstrap attempt. - var log = require("./lib/utils/log") log.waitForConfig() - - ini.resolveConfigs(conf, function (er) { - if (er) return errorHandler(er, opts.exit) - npm.config.set("root", ini.get("root")) - cb(null, true) - }) + ini.resolveConfigs(conf, cb) } // Local store for package data, so it won't have to be fetched/read more than -- cgit v1.2.3