mirror of
https://github.com/nodejs/node.git
synced 2025-05-17 20:06:54 +00:00

Conflicts: ChangeLog Makefile deps/npm/AUTHORS deps/npm/html/api/bin.html deps/npm/html/api/bugs.html deps/npm/html/api/commands.html deps/npm/html/api/config.html deps/npm/html/api/deprecate.html deps/npm/html/api/docs.html deps/npm/html/api/edit.html deps/npm/html/api/explore.html deps/npm/html/api/help-search.html deps/npm/html/api/init.html deps/npm/html/api/install.html deps/npm/html/api/link.html deps/npm/html/api/load.html deps/npm/html/api/ls.html deps/npm/html/api/npm.html deps/npm/html/api/outdated.html deps/npm/html/api/owner.html deps/npm/html/api/pack.html deps/npm/html/api/prefix.html deps/npm/html/api/prune.html deps/npm/html/api/publish.html deps/npm/html/api/rebuild.html deps/npm/html/api/restart.html deps/npm/html/api/root.html deps/npm/html/api/run-script.html deps/npm/html/api/search.html deps/npm/html/api/shrinkwrap.html deps/npm/html/api/start.html deps/npm/html/api/stop.html deps/npm/html/api/submodule.html deps/npm/html/api/tag.html deps/npm/html/api/test.html deps/npm/html/api/uninstall.html deps/npm/html/api/unpublish.html deps/npm/html/api/update.html deps/npm/html/api/version.html deps/npm/html/api/view.html deps/npm/html/api/whoami.html deps/npm/html/doc/README.html deps/npm/html/doc/adduser.html deps/npm/html/doc/bin.html deps/npm/html/doc/bugs.html deps/npm/html/doc/build.html deps/npm/html/doc/bundle.html deps/npm/html/doc/cache.html deps/npm/html/doc/changelog.html deps/npm/html/doc/coding-style.html deps/npm/html/doc/completion.html deps/npm/html/doc/config.html deps/npm/html/doc/deprecate.html deps/npm/html/doc/developers.html deps/npm/html/doc/disputes.html deps/npm/html/doc/docs.html deps/npm/html/doc/edit.html deps/npm/html/doc/explore.html deps/npm/html/doc/faq.html deps/npm/html/doc/folders.html deps/npm/html/doc/help-search.html deps/npm/html/doc/help.html deps/npm/html/doc/index.html deps/npm/html/doc/init.html deps/npm/html/doc/install.html deps/npm/html/doc/json.html deps/npm/html/doc/link.html deps/npm/html/doc/list.html deps/npm/html/doc/npm.html deps/npm/html/doc/outdated.html deps/npm/html/doc/owner.html deps/npm/html/doc/pack.html deps/npm/html/doc/prefix.html deps/npm/html/doc/prune.html deps/npm/html/doc/publish.html deps/npm/html/doc/rebuild.html deps/npm/html/doc/registry.html deps/npm/html/doc/removing-npm.html deps/npm/html/doc/restart.html deps/npm/html/doc/root.html deps/npm/html/doc/run-script.html deps/npm/html/doc/scripts.html deps/npm/html/doc/search.html deps/npm/html/doc/semver.html deps/npm/html/doc/shrinkwrap.html deps/npm/html/doc/star.html deps/npm/html/doc/start.html deps/npm/html/doc/stop.html deps/npm/html/doc/submodule.html deps/npm/html/doc/tag.html deps/npm/html/doc/test.html deps/npm/html/doc/uninstall.html deps/npm/html/doc/unpublish.html deps/npm/html/doc/update.html deps/npm/html/doc/version.html deps/npm/html/doc/view.html deps/npm/html/doc/whoami.html deps/npm/man/man1/npm.1 deps/npm/man/man3/npm.3 deps/npm/package.json doc/api/url.markdown lib/http.js src/node_version.h test/simple/test-fs-sync-fd-leak.js
157 lines
3.9 KiB
JavaScript
157 lines
3.9 KiB
JavaScript
|
|
// centralized stdout writer.
|
|
|
|
exports.doColor = doColor
|
|
exports.write = write
|
|
|
|
var npm = require("../npm.js")
|
|
, tty = require("tty")
|
|
, streams = {}
|
|
, ttys = {}
|
|
, net = require("net")
|
|
, util = require("util")
|
|
, deadStreams = {}
|
|
|
|
function doColor (stream) {
|
|
var conf = npm.config.get("color")
|
|
return (!conf) ? false
|
|
: (conf === "always") ? true
|
|
: isatty(stream)
|
|
}
|
|
function isatty (stream) {
|
|
// console.error("isatty?", stream)
|
|
if (!tty.isatty) return true
|
|
if (!stream) return false
|
|
if (stream.isTTY) return true
|
|
if (stream && (typeof stream.fd === "number")) {
|
|
stream.isTTY = tty.isatty(stream.fd)
|
|
}
|
|
return stream.isTTY
|
|
}
|
|
|
|
function write (args, stream, lf, cb) {
|
|
// console.error("write", [args, stream, lf, cb])
|
|
if (typeof cb !== "function" && typeof lf === "function") {
|
|
cb = lf
|
|
lf = null
|
|
}
|
|
if (typeof cb !== "function" && typeof stream === "function") {
|
|
cb = stream
|
|
stream = npm.config.get("outfd")
|
|
}
|
|
|
|
stream = getStream(stream)
|
|
// console.error("gotStream", stream)
|
|
if (lf == null) lf = isatty(stream)
|
|
if (!stream) return cb && cb(), false
|
|
if (!Array.isArray(args)) args = [args]
|
|
|
|
// console.error("write", args)
|
|
|
|
var msg = ""
|
|
, colored = doColor(stream)
|
|
msg = args.map(function (arg) {
|
|
if (typeof arg !== "string") {
|
|
return util.inspect(arg, false, 5, colored) + "\n"
|
|
}
|
|
if (!colored) arg = arg.replace(/\033\[[0-9;]*m/g, '')
|
|
if (!npm.config.get("unicode")) {
|
|
arg = arg.replace(/└/g, "`")
|
|
.replace(/─/g, "-")
|
|
.replace(/├/g, "+")
|
|
.replace(/┬/g, "-")
|
|
}
|
|
return arg
|
|
}).join(" ")
|
|
|
|
// listen to the "output" event to cancel/modify/redirect
|
|
npm.output = {stream:stream, message:msg}
|
|
npm.emit("output", npm.output)
|
|
if (!npm.output) return cb && cb(), false // cancelled
|
|
stream = npm.output.stream
|
|
msg = npm.output.message
|
|
|
|
// EPIPE errors just mean that the stream is not listening
|
|
// any more. Mark the stream as dead, and return.
|
|
if (deadStreams[stream.fd]) {
|
|
return cb && cb(), false
|
|
}
|
|
if (!deadStreams.hasOwnProperty(stream.fd)) {
|
|
deadStreams[stream.fd] = false
|
|
stream.on("error", function (er) {
|
|
if (er.code === "EPIPE") {
|
|
deadStreams[stream.fd] = true
|
|
return cb && cb()
|
|
}
|
|
if (stream.listeners("error").length === 1) {
|
|
throw er
|
|
}
|
|
})
|
|
}
|
|
|
|
// use the \r\n in case we're in raw mode.
|
|
msg = msg.split(/\r?\n/).concat("").join(lf ? "\r\n" : "\n")
|
|
// output to stderr should be synchronous
|
|
if (stream === process.stderr || stream.fd === 2) {
|
|
process.stderr.write(msg)
|
|
if (cb) cb()
|
|
return true
|
|
}
|
|
// console.error("writing ", msg)
|
|
var flushed = stream.write(msg)
|
|
if (flushed && cb) {
|
|
process.nextTick(cb)
|
|
} else if (cb) {
|
|
stream.once("drain", cb)
|
|
}
|
|
return flushed
|
|
}
|
|
|
|
var hadError = false
|
|
function getStream (fd) {
|
|
if (hadError) return
|
|
|
|
var stream
|
|
if (!fd && fd !== 0) return
|
|
if (typeof fd === "string") fd = +fd
|
|
|
|
// console.error("getStream", fd, hadError)
|
|
|
|
if (fd && typeof fd === "object") {
|
|
stream = fd
|
|
fd = fd.fd
|
|
} else if (streams[fd]) {
|
|
stream = streams[fd]
|
|
} else {
|
|
switch (fd) {
|
|
case 1:
|
|
stream = process.stdout
|
|
stream.fd = fd
|
|
stream.writable = true
|
|
break
|
|
case 2:
|
|
stream = process.stderr
|
|
stream.fd = fd
|
|
stream.writable = true
|
|
break
|
|
default:
|
|
try {
|
|
stream = new net.Stream(fd)
|
|
if (!stream || !stream.writable) {
|
|
throw new Error("Stream not writable")
|
|
}
|
|
} catch (ex) {
|
|
// if this fails, then regular logging is most likely broken.
|
|
var er = new Error("cannot output to fd "+fd + ": "+
|
|
(ex.stack || ex.message).substr(7) + "\n")
|
|
console.error(er.stack)
|
|
hadError = true
|
|
process.exit(1)
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!stream || !stream.writable) return
|
|
return streams[fd] = stream
|
|
}
|