diff options
author | isaacs <i@izs.me> | 2012-03-02 09:31:24 -0800 |
---|---|---|
committer | isaacs <i@izs.me> | 2012-03-02 09:31:46 -0800 |
commit | 054127112ce335ceb4477a481e99e3fb2176b457 (patch) | |
tree | 22c5386ce5538f3db7996a6e71d30264617a66b8 /deps/npm/node_modules | |
parent | edea94c332f07ed81ea7de9b93bbcec806c81544 (diff) | |
download | node-new-054127112ce335ceb4477a481e99e3fb2176b457.tar.gz |
Upgrade npm to 1.1.3
* Update request to support HTTPS-over-HTTP proxy tunneling
* Throw on undefined envs in config settings
* Update which to 1.0.5
* Fix windows UNC busyloop in findPrefix
* Bundle nested bundleDependencies properly
* Alias adduser to add-user
* Doc updates (Christian Howe, Henrik Hodne, Andrew Lunny)
* ignore logfd/outfd streams in makeEnv() (Rod Vagg)
* shrinkwrap: Behave properly with url-installed deps
* install: Support --save with url install targets
* Support installing naked tars or single-file modules from urls etc.
* init: Don't add engines section
* Don't run make clean on rebuild
* Added missing unicode replacement (atomizer)
Diffstat (limited to 'deps/npm/node_modules')
-rw-r--r-- | deps/npm/node_modules/request/forever.js | 21 | ||||
-rw-r--r-- | deps/npm/node_modules/request/main.js | 158 | ||||
-rw-r--r-- | deps/npm/node_modules/request/package.json | 58 | ||||
-rw-r--r-- | deps/npm/node_modules/request/tunnel.js | 229 | ||||
-rw-r--r-- | deps/npm/node_modules/which/package.json | 25 | ||||
-rw-r--r-- | deps/npm/node_modules/which/which.js | 29 |
6 files changed, 467 insertions, 53 deletions
diff --git a/deps/npm/node_modules/request/forever.js b/deps/npm/node_modules/request/forever.js index e6531a21b3..ac853c0d28 100644 --- a/deps/npm/node_modules/request/forever.js +++ b/deps/npm/node_modules/request/forever.js @@ -1,8 +1,11 @@ module.exports = ForeverAgent +ForeverAgent.SSL = ForeverAgentSSL var util = require('util') , Agent = require('http').Agent , net = require('net') + , tls = require('tls') + , AgentSSL = require('https').Agent function ForeverAgent(options) { var self = this @@ -34,12 +37,14 @@ function ForeverAgent(options) { socket.destroy(); } }) - self.createConnection = net.createConnection + } util.inherits(ForeverAgent, Agent) ForeverAgent.defaultMinSockets = 5 + +ForeverAgent.prototype.createConnection = net.createConnection ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest ForeverAgent.prototype.addRequest = function(req, host, port) { var name = host + ':' + port @@ -82,3 +87,17 @@ ForeverAgent.prototype.removeSocket = function(s, name, host, port) { this.createSocket(name, host, port).emit('free'); } } + +function ForeverAgentSSL (options) { + ForeverAgent.call(this, options) +} +util.inherits(ForeverAgentSSL, ForeverAgent) + +ForeverAgentSSL.prototype.createConnection = createConnectionSSL +ForeverAgentSSL.prototype.addRequestNoreuse = AgentSSL.prototype.addRequest + +function createConnectionSSL (port, host, options) { + options.port = port + options.host = host + return tls.connect(options) +} diff --git a/deps/npm/node_modules/request/main.js b/deps/npm/node_modules/request/main.js index 5c14264163..f651202740 100644 --- a/deps/npm/node_modules/request/main.js +++ b/deps/npm/node_modules/request/main.js @@ -26,6 +26,7 @@ var http = require('http') , Cookie = require('./vendor/cookie') , CookieJar = require('./vendor/cookie/jar') , cookieJar = new CookieJar + , tunnel = require('./tunnel') ; if (process.logging) { @@ -133,6 +134,20 @@ Request.prototype.init = function (options) { } if (self.proxy) { if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy) + + // do the HTTP CONNECT dance using koichik/node-tunnel + if (http.globalAgent && self.uri.protocol === "https:") { + self.tunnel = true + var tunnelFn = self.proxy.protocol === "http:" + ? tunnel.httpsOverHttp : tunnel.httpsOverHttps + + var tunnelOptions = { proxy: { host: self.proxy.hostname + , port: +self.proxy.port } + , ca: this.ca } + + self.agent = tunnelFn(tunnelOptions) + self.tunnel = true + } } self._redirectsFollowed = self._redirectsFollowed || 0 @@ -163,7 +178,7 @@ Request.prototype.init = function (options) { else if (self.uri.protocol == 'https:') {self.uri.port = 443} } - if (self.proxy) { + if (self.proxy && !self.tunnel) { self.port = self.proxy.port self.host = self.proxy.hostname } else { @@ -177,9 +192,12 @@ Request.prototype.init = function (options) { } self.clientErrorHandler = function (error) { + if (self._aborted) return + if (self.setHost) delete self.headers.host - if (self.req._reusedSocket && error.code === 'ECONNRESET') { - self.agent = {addRequest: ForeverAgent.prototype.addRequestNoreuse.bind(self.agent)} + if (self.req._reusedSocket && error.code === 'ECONNRESET' + && self.agent.addRequestNoreuse) { + self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) } self.start() self.req.end() return @@ -204,7 +222,7 @@ Request.prototype.init = function (options) { if (self.uri.auth && !self.headers.authorization) { self.headers.authorization = "Basic " + toBase64(self.uri.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) } - if (self.proxy && self.proxy.auth && !self.headers['proxy-authorization']) { + if (self.proxy && self.proxy.auth && !self.headers['proxy-authorization'] && !self.tunnel) { self.headers['proxy-authorization'] = "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) } @@ -218,7 +236,7 @@ Request.prototype.init = function (options) { if (self.path.length === 0) self.path = '/' - if (self.proxy) self.path = (self.uri.protocol + '//' + self.uri.host + self.path) + if (self.proxy && !self.tunnel) self.path = (self.uri.protocol + '//' + self.uri.host + self.path) if (options.json) { self.json(options.json) @@ -247,7 +265,7 @@ Request.prototype.init = function (options) { } } - var protocol = self.proxy ? self.proxy.protocol : self.uri.protocol + var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol , defaultModules = {'http:':http, 'https:':https} , httpModules = self.httpModules || {} ; @@ -255,17 +273,30 @@ Request.prototype.init = function (options) { if (!self.httpModule) throw new Error("Invalid protocol") + if (options.ca) self.ca = options.ca + + if (!self.agent) { + if (options.agentOptions) self.agentOptions = options.agentOptions + + if (options.agentClass) { + self.agentClass = options.agentClass + } else if (options.forever) { + self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL + } else { + self.agentClass = self.httpModule.Agent + } + } + if (self.pool === false) { self.agent = false } else { + self.agent = self.agent || self.getAgent() if (self.maxSockets) { // Don't use our pooling if node has the refactored client - self.agent = self.agent || self.httpModule.globalAgent || self.getAgent(self.host, self.port) self.agent.maxSockets = self.maxSockets } if (self.pool.maxSockets) { // Don't use our pooling if node has the refactored client - self.agent = self.agent || self.httpModule.globalAgent || self.getAgent(self.host, self.port) self.agent.maxSockets = self.pool.maxSockets } } @@ -295,6 +326,8 @@ Request.prototype.init = function (options) { }) process.nextTick(function () { + if (self._aborted) return + if (self.body) { if (Array.isArray(self.body)) { self.body.forEach(function(part) { @@ -314,19 +347,61 @@ Request.prototype.init = function (options) { self.ntick = true }) } -Request.prototype.getAgent = function (host, port) { - if (!this.pool[host+':'+port]) { - this.pool[host+':'+port] = new this.httpModule.Agent({host:host, port:port}) + +Request.prototype.getAgent = function () { + var Agent = this.agentClass + var options = {} + if (this.agentOptions) { + for (var i in this.agentOptions) { + options[i] = this.agentOptions[i] + } + } + if (this.ca) options.ca = this.ca + + var poolKey = '' + + // different types of agents are in different pools + if (Agent !== this.httpModule.Agent) { + poolKey += Agent.name + } + + if (!this.httpModule.globalAgent) { + // node 0.4.x + options.host = this.host + options.port = this.port + if (poolKey) poolKey += ':' + poolKey += this.host + ':' + this.port } - return this.pool[host+':'+port] + + if (options.ca) { + if (poolKey) poolKey += ':' + poolKey += options.ca + } + + if (!poolKey && Agent === this.httpModule.Agent && this.httpModule.globalAgent) { + // not doing anything special. Use the globalAgent + return this.httpModule.globalAgent + } + + // already generated an agent for this setting + if (this.pool[poolKey]) return this.pool[poolKey] + + return this.pool[poolKey] = new Agent(options) } + Request.prototype.start = function () { var self = this + + if (self._aborted) return + self._started = true self.method = self.method || 'GET' self.href = self.uri.href if (log) log('%method %href', self) self.req = self.httpModule.request(self, function (response) { + if (self._aborted) return + if (self._paused) response.pause() + self.response = response response.request = self @@ -353,7 +428,7 @@ Request.prototype.start = function () { if (response.statusCode >= 300 && response.statusCode < 400 && (self.followAllRedirects || - (self.followRedirect && (self.method !== 'PUT' && self.method !== 'POST'))) && + (self.followRedirect && (self.method !== 'PUT' && self.method !== 'POST' && self.method !== 'DELETE'))) && response.headers.location) { if (self._redirectsFollowed >= self.maxRedirects) { self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop.")) @@ -423,6 +498,8 @@ Request.prototype.start = function () { bodyLen += chunk.length }) self.on("end", function () { + if (self._aborted) return + if (buffer.length && Buffer.isBuffer(buffer[0])) { var body = new Buffer(bodyLen) var i = 0 @@ -439,7 +516,7 @@ Request.prototype.start = function () { response.body = buffer.join('') } - if (self.json) { + if (self._json) { try { response.body = JSON.parse(response.body) } catch (e) {} @@ -461,20 +538,36 @@ Request.prototype.start = function () { // Set additional timeout on socket - in case if remote // server freeze after sending headers - self.req.setTimeout(self.timeout, function(){ - if (self.req) { - self.req.abort() - var e = new Error("ESOCKETTIMEDOUT") - e.code = "ESOCKETTIMEDOUT" - self.emit("error", e) - } - }); + if (self.req.setTimeout) { // only works on node 0.6+ + self.req.setTimeout(self.timeout, function(){ + if (self.req) { + self.req.abort() + var e = new Error("ESOCKETTIMEDOUT") + e.code = "ESOCKETTIMEDOUT" + self.emit("error", e) + } + }) + } } self.req.on('error', self.clientErrorHandler) self.emit('request', self.req) } + +Request.prototype.abort = function() { + this._aborted = true; + + if (this.req) { + this.req.abort() + } + else if (this.response) { + this.response.abort() + } + + this.emit("abort") +} + Request.prototype.pipeDest = function (dest) { var response = this.response // Called after the response is received @@ -554,6 +647,7 @@ Request.prototype.multipart = function (multipart) { Request.prototype.json = function (val) { this.setHeader('content-type', 'application/json') this.setHeader('accept', 'application/json') + this._json = true if (typeof val === 'boolean') { if (typeof this.body === 'object') this.body = JSON.stringify(this.body) } else { @@ -659,22 +753,20 @@ Request.prototype.pipe = function (dest, opts) { } Request.prototype.write = function () { if (!this._started) this.start() - if (!this.req) throw new Error("This request has been piped before http.request() was called.") this.req.write.apply(this.req, arguments) } Request.prototype.end = function (chunk) { if (chunk) this.write(chunk) if (!this._started) this.start() - if (!this.req) throw new Error("This request has been piped before http.request() was called.") this.req.end() } Request.prototype.pause = function () { - if (!this.response) throw new Error("This request has been piped before http.request() was called.") - this.response.pause.apply(this.response, arguments) + if (!this.response) this._paused = true + else this.response.pause.apply(this.response, arguments) } Request.prototype.resume = function () { - if (!this.response) throw new Error("This request has been piped before http.request() was called.") - this.response.resume.apply(this.response, arguments) + if (!this.response) this._paused = false + else this.response.resume.apply(this.response, arguments) } Request.prototype.destroy = function () { if (!this._ended) this.end() @@ -735,12 +827,13 @@ request.defaults = function (options) { request.forever = function (agentOptions, optionsArg) { var options = {} - if (agentOptions) { + if (optionsArg) { for (option in optionsArg) { options[option] = optionsArg[option] } } - options.agent = new ForeverAgent(agentOptions) + if (agentOptions) options.agentOptions = agentOptions + options.forever = true return request.defaults(options) } @@ -758,7 +851,10 @@ request.put = function (uri, options, callback) { request.head = function (uri, options, callback) { var params = initParams(uri, options, callback); params.options.method = 'HEAD' - if (options.body || options.requestBodyStream || options.json || options.multipart) { + if (params.options.body || + params.options.requestBodyStream || + (params.options.json && typeof params.options.json !== 'boolean') || + params.options.multipart) { throw new Error("HTTP HEAD requests MUST NOT include a request body.") } return request(params.uri, params.options, params.callback) diff --git a/deps/npm/node_modules/request/package.json b/deps/npm/node_modules/request/package.json index 305cf167b1..4a62c5a469 100644 --- a/deps/npm/node_modules/request/package.json +++ b/deps/npm/node_modules/request/package.json @@ -1,15 +1,45 @@ -{ "name" : "request" -, "description" : "Simplified HTTP request client." -, "tags" : ["http", "simple", "util", "utility"] -, "version" : "2.9.151" -, "author" : "Mikeal Rogers <mikeal.rogers@gmail.com>" -, "repository" : - { "type" : "git" - , "url" : "http://github.com/mikeal/request.git" - } -, "bugs" : - { "url" : "http://github.com/mikeal/request/issues" } -, "engines" : ["node >= 0.3.6"] -, "main" : "./main" -, "scripts": { "test": "node tests/run.js" } +{ + "name": "request", + "description": "Simplified HTTP request client.", + "tags": [ + "http", + "simple", + "util", + "utility" + ], + "version": "2.9.153", + "author": { + "name": "Mikeal Rogers", + "email": "mikeal.rogers@gmail.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/mikeal/request.git" + }, + "bugs": { + "url": "http://github.com/mikeal/request/issues" + }, + "engines": [ + "node >= 0.3.6" + ], + "main": "./main", + "scripts": { + "test": "node tests/run.js" + }, + "_npmUser": { + "name": "isaacs", + "email": "i@izs.me" + }, + "_id": "request@2.9.153", + "dependencies": {}, + "devDependencies": {}, + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.2", + "_nodeVersion": "v0.7.6-pre", + "_defaultsLoaded": true, + "dist": { + "shasum": "d1f4855a90a9e69bf6cd2a68503e253cc4a27a71" + }, + "_from": "request@~2.9" } diff --git a/deps/npm/node_modules/request/tunnel.js b/deps/npm/node_modules/request/tunnel.js new file mode 100644 index 0000000000..453786c5e7 --- /dev/null +++ b/deps/npm/node_modules/request/tunnel.js @@ -0,0 +1,229 @@ +'use strict'; + +var net = require('net'); +var tls = require('tls'); +var http = require('http'); +var https = require('https'); +var events = require('events'); +var assert = require('assert'); +var util = require('util'); + + +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + return agent; +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + return agent; +} + + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port) { + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === host && pending.port === port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); +} +util.inherits(TunnelingAgent, events.EventEmitter); + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port) { + var self = this; + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push({host: host, port: port, request: req}); + return; + } + + // If we are under maxSockets create a new one. + self.createSocket({host: host, port: port, request: req}, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, host, port); + } + + function onCloseOrRemove(err) { + self.removeSocket(); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); + } + }); +}; + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false + }); + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); + } + + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); + }); + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + + if (res.statusCode === 200) { + assert.equal(head.length, 0); + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + cb(socket); + } else { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + var error = new Error('tunneling socket could not be established, ' + + 'sutatusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } + } + + function onError(cause) { + connectReq.removeAllListeners(); + + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } +}; + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); + } +}; + +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, mergeOptions({}, self.options, { + socket: socket + })); + cb(secureSocket); + }); +} + + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; + } + } + } + } + return target; +} + + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; +} +exports.debug = debug; // for test diff --git a/deps/npm/node_modules/which/package.json b/deps/npm/node_modules/which/package.json index ea26853b88..c45dafee92 100644 --- a/deps/npm/node_modules/which/package.json +++ b/deps/npm/node_modules/which/package.json @@ -1,17 +1,34 @@ { - "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, "name": "which", "description": "Like which(1) unix command. Find the first instance of an executable in the PATH.", - "version": "1.0.3", + "version": "1.0.5", "repository": { "type": "git", "url": "git://github.com/isaacs/node-which.git" }, "main": "which.js", - "bin": "./bin/which", + "bin": { + "which": "./bin/which" + }, "engines": { "node": "*" }, "dependencies": {}, - "devDependencies": {} + "devDependencies": {}, + "_npmUser": { + "name": "isaacs", + "email": "i@izs.me" + }, + "_id": "which@1.0.5", + "optionalDependencies": {}, + "_engineSupported": true, + "_npmVersion": "1.1.2", + "_nodeVersion": "v0.7.6-pre", + "_defaultsLoaded": true, + "_from": "which@1" } diff --git a/deps/npm/node_modules/which/which.js b/deps/npm/node_modules/which/which.js index 634e3af6e9..db7e8f74dc 100644 --- a/deps/npm/node_modules/which/which.js +++ b/deps/npm/node_modules/which/which.js @@ -27,13 +27,16 @@ if (process.platform == "win32") { } } + + function which (cmd, cb) { - if (cmd.charAt(0) === "/") return cb(null, cmd) + if (isAbsolute(cmd)) return cb(null, cmd) var pathEnv = (process.env.PATH || "").split(COLON) , pathExt = [""] if (process.platform === "win32") { pathEnv.push(process.cwd()) pathExt = (process.env.PATHEXT || ".EXE").split(COLON) + if (cmd.indexOf(".") !== -1) pathExt.unshift("") } //console.error("pathEnv", pathEnv) ;(function F (i, l) { @@ -57,14 +60,14 @@ function which (cmd, cb) { })(0, pathEnv.length) } - function whichSync (cmd) { - if (cmd.charAt(0) === "/") return cmd + if (isAbsolute(cmd)) return cmd var pathEnv = (process.env.PATH || "").split(COLON) , pathExt = [""] if (process.platform === "win32") { pathEnv.push(process.cwd()) pathExt = (process.env.PATHEXT || ".EXE").split(COLON) + if (cmd.indexOf(".") !== -1) pathExt.unshift("") } for (var i = 0, l = pathEnv.length; i < l; i ++) { var p = path.join(pathEnv[i], cmd) @@ -79,3 +82,23 @@ function whichSync (cmd) { } throw new Error("not found: "+cmd) } + +var isAbsolute = process.platform === "win32" ? absWin : absUnix + +function absWin (p) { + if (absUnix(p)) return true + // pull off the device/UNC bit from a windows path. + // from node's lib/path.js + var splitDeviceRe = + /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?/ + , result = splitDeviceRe.exec(p) + , device = result[1] || '' + , isUnc = device && device.charAt(1) !== ':' + , isAbsolute = !!result[2] || isUnc // UNC paths are always absolute + + return isAbsolute +} + +function absUnix (p) { + return p.charAt(0) === "/" || p === "" +} |