summaryrefslogtreecommitdiff
path: root/deps/npm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/lib')
-rw-r--r--deps/npm/lib/adduser.js45
-rw-r--r--deps/npm/lib/bugs.js24
-rw-r--r--deps/npm/lib/build.js4
-rw-r--r--deps/npm/lib/cache.js177
-rw-r--r--deps/npm/lib/cache/add-local-tarball.js13
-rw-r--r--deps/npm/lib/cache/add-local.js22
-rw-r--r--deps/npm/lib/cache/add-named.js59
-rw-r--r--deps/npm/lib/cache/add-remote-git.js65
-rw-r--r--deps/npm/lib/cache/add-remote-tarball.js43
-rw-r--r--deps/npm/lib/cache/get-stat.js4
-rw-r--r--deps/npm/lib/cache/maybe-github.js19
-rw-r--r--deps/npm/lib/dedupe.js18
-rw-r--r--deps/npm/lib/deprecate.js39
-rw-r--r--deps/npm/lib/docs.js26
-rw-r--r--deps/npm/lib/install.js276
-rw-r--r--deps/npm/lib/link.js20
-rw-r--r--deps/npm/lib/ls.js23
-rw-r--r--deps/npm/lib/npm.js11
-rw-r--r--deps/npm/lib/outdated.js35
-rw-r--r--deps/npm/lib/owner.js213
-rw-r--r--deps/npm/lib/pack.js9
-rw-r--r--deps/npm/lib/publish.js84
-rw-r--r--deps/npm/lib/rebuild.js7
-rw-r--r--deps/npm/lib/repo.js28
-rw-r--r--deps/npm/lib/run-script.js34
-rw-r--r--deps/npm/lib/search.js13
-rw-r--r--deps/npm/lib/star.js30
-rw-r--r--deps/npm/lib/stars.js21
-rw-r--r--deps/npm/lib/submodule.js5
-rw-r--r--deps/npm/lib/tag.js28
-rw-r--r--deps/npm/lib/unbuild.js11
-rw-r--r--deps/npm/lib/unpublish.js84
-rw-r--r--deps/npm/lib/utils/error-handler.js122
-rw-r--r--deps/npm/lib/utils/fetch.js106
-rw-r--r--deps/npm/lib/utils/gently-rm.js173
-rw-r--r--deps/npm/lib/utils/is-git-url.js13
-rw-r--r--deps/npm/lib/utils/lifecycle.js13
-rw-r--r--deps/npm/lib/utils/map-to-registry.js54
-rw-r--r--deps/npm/lib/version.js6
-rw-r--r--deps/npm/lib/view.js115
-rw-r--r--deps/npm/lib/whoami.js40
41 files changed, 1244 insertions, 888 deletions
diff --git a/deps/npm/lib/adduser.js b/deps/npm/lib/adduser.js
index 579ecb0a9..7e933ea7d 100644
--- a/deps/npm/lib/adduser.js
+++ b/deps/npm/lib/adduser.js
@@ -19,9 +19,10 @@ function adduser (args, cb) {
if (!crypto) return cb(new Error(
"You must compile node with ssl support to use the adduser feature"))
- var c = { u : npm.config.get("username") || ""
- , p : npm.config.get("_password") || ""
- , e : npm.config.get("email") || ""
+ var creds = npm.config.getCredentialsByURI(npm.config.get("registry"))
+ var c = { u : creds.username || ""
+ , p : creds.password || ""
+ , e : creds.email || ""
}
, u = {}
, fns = [readUsername, readPassword, readEmail, save]
@@ -94,7 +95,7 @@ function readPassword (c, u, cb) {
return readPassword(c, u, cb)
}
- c.changed = c.changed || c.p != pw
+ c.changed = c.changed || c.p !== pw
u.p = pw
cb(er)
})
@@ -132,17 +133,45 @@ function save (c, u, cb) {
registry.password = u.p
}
npm.spinner.start()
+
// save existing configs, but yank off for this PUT
- registry.adduser(npm.config.get("registry"), u.u, u.p, u.e, function (er) {
+ var uri = npm.config.get("registry")
+ var scope = npm.config.get("scope")
+
+ // there may be a saved scope and no --registry (for login)
+ if (scope) {
+ if (scope.charAt(0) !== "@") scope = "@" + scope
+
+ var scopedRegistry = npm.config.get(scope + ":registry")
+ if (scopedRegistry) uri = scopedRegistry
+ }
+
+ registry.adduser(uri, u.u, u.p, u.e, function (er, doc) {
npm.spinner.stop()
if (er) return cb(er)
+
registry.username = u.u
registry.password = u.p
registry.email = u.e
- npm.config.set("username", u.u, "user")
- npm.config.set("_password", u.p, "user")
- npm.config.set("email", u.e, "user")
+
+ // don't want this polluting the configuration
npm.config.del("_token", "user")
+
+ if (scope) npm.config.set(scope + ":registry", uri, "user")
+
+ if (doc && doc.token) {
+ npm.config.setCredentialsByURI(uri, {
+ token : doc.token
+ })
+ }
+ else {
+ npm.config.setCredentialsByURI(uri, {
+ username : u.u,
+ password : u.p,
+ email : u.e
+ })
+ }
+
log.info("adduser", "Authorized user %s", u.u)
npm.config.save("user", cb)
})
diff --git a/deps/npm/lib/bugs.js b/deps/npm/lib/bugs.js
index b3022bf2a..16744cd5c 100644
--- a/deps/npm/lib/bugs.js
+++ b/deps/npm/lib/bugs.js
@@ -9,19 +9,23 @@ var npm = require("./npm.js")
, opener = require("opener")
, path = require("path")
, readJson = require("read-package-json")
+ , npa = require("npm-package-arg")
, fs = require("fs")
- , url = require("url")
+ , mapToRegistry = require("./utils/map-to-registry.js")
bugs.completion = function (opts, cb) {
if (opts.conf.argv.remain.length > 2) return cb()
- var uri = url.resolve(npm.config.get("registry"), "-/short")
- registry.get(uri, { timeout : 60000 }, function (er, list) {
- return cb(null, list || [])
+ mapToRegistry("-/short", npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, { timeout : 60000 }, function (er, list) {
+ return cb(null, list || [])
+ })
})
}
function bugs (args, cb) {
- var n = args.length && args[0].split("@").shift() || '.'
+ var n = args.length && npa(args[0]).name || '.'
fs.stat(n, function (er, s) {
if (er && er.code === "ENOENT") return callRegistry(n, cb)
else if (er) return cb (er)
@@ -56,9 +60,13 @@ function getUrlAndOpen (d, cb) {
}
function callRegistry (n, cb) {
- var uri = url.resolve(npm.config.get("registry"), n + "/latest")
- registry.get(uri, { timeout : 3600 }, function (er, d) {
+ mapToRegistry(n, npm.config, function (er, uri) {
if (er) return cb(er)
- getUrlAndOpen (d, cb)
+
+ registry.get(uri + "/latest", { timeout : 3600 }, function (er, d) {
+ if (er) return cb(er)
+
+ getUrlAndOpen (d, cb)
+ })
})
}
diff --git a/deps/npm/lib/build.js b/deps/npm/lib/build.js
index 350774a45..f1c61bdb8 100644
--- a/deps/npm/lib/build.js
+++ b/deps/npm/lib/build.js
@@ -75,7 +75,7 @@ function linkStuff (pkg, folder, global, didRB, cb) {
// if it's global, and folder is in {prefix}/node_modules,
// then bins are in {prefix}/bin
// otherwise, then bins are in folder/../.bin
- var parent = path.dirname(folder)
+ var parent = pkg.name[0] === "@" ? path.dirname(path.dirname(folder)) : path.dirname(folder)
, gnm = global && npm.globalDir
, gtop = parent === gnm
@@ -95,7 +95,7 @@ function linkStuff (pkg, folder, global, didRB, cb) {
function shouldWarn(pkg, folder, global, cb) {
var parent = path.dirname(folder)
, top = parent === npm.dir
- , cwd = process.cwd()
+ , cwd = npm.localPrefix
readJson(path.resolve(cwd, "package.json"), function(er, topPkg) {
if (er) return cb(er)
diff --git a/deps/npm/lib/cache.js b/deps/npm/lib/cache.js
index 37bba5a06..281d6100a 100644
--- a/deps/npm/lib/cache.js
+++ b/deps/npm/lib/cache.js
@@ -47,9 +47,15 @@ adding a name@range:
adding a local tarball:
1. untar to tmp/random/{blah}
2. goto folder(2)
+
+adding a namespaced package:
+1. lookup registry for @namespace
+2. namespace_registry.get('name')
+3. add url(namespace/latest.tarball)
*/
exports = module.exports = cache
+
cache.unpack = unpack
cache.clean = clean
cache.read = read
@@ -61,17 +67,18 @@ var npm = require("./npm.js")
, readJson = require("read-package-json")
, log = require("npmlog")
, path = require("path")
- , url = require("url")
, asyncMap = require("slide").asyncMap
, tar = require("./utils/tar.js")
, fileCompletion = require("./utils/completion/file-completion.js")
- , isGitUrl = require("./utils/is-git-url.js")
, deprCheck = require("./utils/depr-check.js")
, addNamed = require("./cache/add-named.js")
, addLocal = require("./cache/add-local.js")
, addRemoteTarball = require("./cache/add-remote-tarball.js")
, addRemoteGit = require("./cache/add-remote-git.js")
+ , maybeGithub = require("./cache/maybe-github.js")
, inflight = require("inflight")
+ , npa = require("npm-package-arg")
+ , getStat = require("./cache/get-stat.js")
cache.usage = "npm cache add <tarball file>"
+ "\nnpm cache add <folder>"
@@ -108,9 +115,8 @@ function cache (args, cb) {
switch (cmd) {
case "rm": case "clear": case "clean": return clean(args, cb)
case "list": case "sl": case "ls": return ls(args, cb)
- case "add": return add(args, cb)
- default: return cb(new Error(
- "Invalid cache action: "+cmd))
+ case "add": return add(args, npm.prefix, cb)
+ default: return cb("Usage: "+cache.usage)
}
}
@@ -147,15 +153,30 @@ function read (name, ver, forceBypass, cb) {
})
}
+function normalize (args) {
+ var normalized = ""
+ if (args.length > 0) {
+ var a = npa(args[0])
+ if (a.name) normalized = a.name
+ if (a.rawSpec) normalized = [normalized, a.rawSpec].join("/")
+ if (args.length > 1) normalized = [normalized].concat(args.slice(1)).join("/")
+ }
+
+ if (normalized.substr(-1) === "/") {
+ normalized = normalized.substr(0, normalized.length - 1)
+ }
+ log.silly("ls", "normalized", normalized)
+
+ return normalized
+}
+
// npm cache ls [<path>]
function ls (args, cb) {
- args = args.join("/").split("@").join("/")
- if (args.substr(-1) === "/") args = args.substr(0, args.length - 1)
var prefix = npm.config.get("cache")
- if (0 === prefix.indexOf(process.env.HOME)) {
+ if (prefix.indexOf(process.env.HOME) === 0) {
prefix = "~" + prefix.substr(process.env.HOME.length)
}
- ls_(args, npm.config.get("depth"), function (er, files) {
+ ls_(normalize(args), npm.config.get("depth"), function (er, files) {
console.log(files.map(function (f) {
return path.join(prefix, f)
}).join("\n").trim())
@@ -174,9 +195,7 @@ function clean (args, cb) {
if (!args) args = []
- args = args.join("/").split("@").join("/")
- if (args.substr(-1) === "/") args = args.substr(0, args.length - 1)
- var f = path.join(npm.cache, path.normalize(args))
+ var f = path.join(npm.cache, path.normalize(normalize(args)))
if (f === npm.cache) {
fs.readdir(npm.cache, function (er, files) {
if (er) return cb()
@@ -187,30 +206,30 @@ function clean (args, cb) {
})
, rm, cb )
})
- } else rm(path.join(npm.cache, path.normalize(args)), cb)
+ } else rm(path.join(npm.cache, path.normalize(normalize(args))), cb)
}
// npm cache add <tarball-url>
// npm cache add <pkg> <ver>
// npm cache add <tarball>
// npm cache add <folder>
-cache.add = function (pkg, ver, scrub, cb) {
+cache.add = function (pkg, ver, where, scrub, cb) {
assert(typeof pkg === "string", "must include name of package to install")
assert(typeof cb === "function", "must include callback")
if (scrub) {
return clean([], function (er) {
if (er) return cb(er)
- add([pkg, ver], cb)
+ add([pkg, ver], where, cb)
})
}
log.verbose("cache add", [pkg, ver])
- return add([pkg, ver], cb)
+ return add([pkg, ver], where, cb)
}
var adding = 0
-function add (args, cb) {
+function add (args, where, cb) {
// this is hot code. almost everything passes through here.
// the args can be any of:
// ["url"]
@@ -226,60 +245,69 @@ function add (args, cb) {
+ " npm cache add <pkg>@<ver>\n"
+ " npm cache add <tarball>\n"
+ " npm cache add <folder>\n"
- , name
, spec
+ , p
if (args[1] === undefined) args[1] = null
// at this point the args length must ==2
if (args[1] !== null) {
- name = args[0]
- spec = args[1]
+ spec = args[0]+"@"+args[1]
} else if (args.length === 2) {
spec = args[0]
}
- log.verbose("cache add", "name=%j spec=%j args=%j", name, spec, args)
+ log.verbose("cache add", "spec=%j args=%j", spec, args)
- if (!name && !spec) return cb(usage)
+ if (!spec) return cb(usage)
if (adding <= 0) {
npm.spinner.start()
}
adding ++
- cb = afterAdd([name, spec], cb)
-
- // see if the spec is a url
- // otherwise, treat as name@version
- var p = url.parse(spec) || {}
- log.verbose("parsed url", p)
-
- // If there's a /, and it's a path, then install the path.
- // If not, and there's a @, it could be that we got name@http://blah
- // in that case, we will not have a protocol now, but if we
- // split and check, we will.
- if (!name && !p.protocol) {
- return maybeFile(spec, cb)
- }
- else {
- switch (p.protocol) {
- case "http:":
- case "https:":
- return addRemoteTarball(spec, { name: name }, null, cb)
+ cb = afterAdd(cb)
+
+ // package.json can have local URI ("file:") dependencies which require
+ // normalization
+ p = npa(spec)
+ if (p.type === "local" && where) spec = path.resolve(where, p.spec)
+ log.verbose("parsed spec", p)
+
+ // short-circuit local installs
+ fs.stat(spec, function (er, s) {
+ if (er) return addNonLocal(spec, cb)
+ if (!s.isDirectory()) return addAndLogLocal(spec, cb)
+ fs.stat(path.join(spec, "package.json"), function (er) {
+ if (er) return addNonLocal(spec, cb)
+ addAndLogLocal(spec, cb)
+ })
+ })
+}
+
+function addAndLogLocal (spec, cb) {
+ log.verbose("cache add", "local package", path.resolve(spec))
+ return addLocal(spec, null, cb)
+}
+function addNonLocal (spec, cb) {
+ var p = npa(spec)
+ log.verbose("parsed spec", p)
+
+ switch (p.type) {
+ case "remote":
+ addRemoteTarball(p.spec, {name : p.name}, null, cb)
+ break
+ case "git":
+ addRemoteGit(p.spec, false, cb)
+ break
+ case "github":
+ maybeGithub(p.spec, cb)
+ break
default:
- if (isGitUrl(p)) return addRemoteGit(spec, p, false, cb)
+ if (p.name) return addNamed(p.name, p.spec, null, cb)
- // if we have a name and a spec, then try name@spec
- if (name) {
- addNamed(name, spec, null, cb)
- }
- // if not, then try just spec (which may try name@"" if not found)
- else {
- addLocal(spec, {}, cb)
- }
+ cb(new Error("couldn't figure out how to install " + spec))
}
- }
}
function unpack (pkg, ver, unpackTarget, dMode, fMode, uid, gid, cb) {
@@ -304,7 +332,7 @@ function unpack (pkg, ver, unpackTarget, dMode, fMode, uid, gid, cb) {
})
}
-function afterAdd (arg, cb) { return function (er, data) {
+function afterAdd (cb) { return function (er, data) {
adding --
if (adding <= 0) {
npm.spinner.stop()
@@ -322,49 +350,32 @@ function afterAdd (arg, cb) { return function (er, data) {
var done = inflight(pj, cb)
- if (!done) return
+ if (!done) return undefined
fs.writeFile(tmp, JSON.stringify(data), "utf8", function (er) {
if (er) return done(er)
- fs.rename(tmp, pj, function (er) {
- done(er, data)
+ getStat(function (er, cs) {
+ if (er) return done(er)
+ fs.rename(tmp, pj, function (er) {
+ if (cs.uid && cs.gid) {
+ fs.chown(pj, cs.uid, cs.gid, function (er) {
+ return done(er, data)
+ })
+ } else {
+ done(er, data)
+ }
+ })
})
})
}}
-function maybeFile (spec, cb) {
- // split name@2.3.4 only if name is a valid package name,
- // don't split in case of "./test@example.com/" (local path)
- fs.stat(spec, function (er) {
- if (!er) {
- // definitely a local thing
- return addLocal(spec, {}, cb)
- }
-
- maybeAt(spec, cb)
- })
-}
-
-function maybeAt (spec, cb) {
- if (spec.indexOf("@") !== -1) {
- var tmp = spec.split("@")
-
- var name = tmp.shift()
- spec = tmp.join("@")
- add([name, spec], cb)
- } else {
- // already know it's not a url, so must be local
- addLocal(spec, {}, cb)
- }
-}
-
-function needName(er, data) {
+function needName (er, data) {
return er ? er
: (data && !data.name) ? new Error("No name provided")
: null
}
-function needVersion(er, data) {
+function needVersion (er, data) {
return er ? er
: (data && !data.version) ? new Error("No version provided")
: null
diff --git a/deps/npm/lib/cache/add-local-tarball.js b/deps/npm/lib/cache/add-local-tarball.js
index bcb938fa9..f7cd76103 100644
--- a/deps/npm/lib/cache/add-local-tarball.js
+++ b/deps/npm/lib/cache/add-local-tarball.js
@@ -191,7 +191,15 @@ function addTmpTarball_ (tgz, data, shasum, cb) {
var target = path.resolve(root, "package.tgz")
getCacheStat(function (er, cs) {
if (er) return cb(er)
- mkdir(pkg, function (er) {
+ mkdir(pkg, function (er, created) {
+
+ // chown starting from the first dir created by mkdirp,
+ // or the root dir, if none had to be created, so that
+ // we know that we get all the children.
+ function chown (er) {
+ chownr(created || root, cs.uid, cs.gid, done)
+ }
+
if (er) return cb(er)
var read = fs.createReadStream(tgz)
var write = fs.createWriteStream(target)
@@ -199,9 +207,6 @@ function addTmpTarball_ (tgz, data, shasum, cb) {
read.on("error", cb).pipe(write).on("error", cb).on("close", fin)
})
- function chown () {
- chownr(root, cs.uid, cs.gid, done)
- }
})
function done() {
diff --git a/deps/npm/lib/cache/add-local.js b/deps/npm/lib/cache/add-local.js
index 2a6d8cf88..bedf34bac 100644
--- a/deps/npm/lib/cache/add-local.js
+++ b/deps/npm/lib/cache/add-local.js
@@ -13,9 +13,7 @@ var fs = require("graceful-fs")
, lock = locker.lock
, unlock = locker.unlock
, getCacheStat = require("./get-stat.js")
- , addNamed = require("./add-named.js")
, addLocalTarball = require("./add-local-tarball.js")
- , maybeGithub = require("./maybe-github.js")
, sha = require("sha")
module.exports = addLocal
@@ -29,16 +27,12 @@ function addLocal (p, pkgData, cb_) {
function cb (er, data) {
unlock(p, function () {
if (er) {
- // if it doesn't have a / in it, it might be a
- // remote thing.
- if (p.indexOf("/") === -1 && p.charAt(0) !== "."
- && (process.platform !== "win32" || p.indexOf("\\") === -1)) {
- return addNamed(p, "", null, cb_)
- }
log.error("addLocal", "Could not install %s", p)
return cb_(er)
}
- if (data && !data._fromGithub) data._from = p
+ if (data && !data._fromGithub) {
+ data._from = path.relative(npm.prefix, p) || "."
+ }
return cb_(er, data)
})
}
@@ -47,14 +41,8 @@ function addLocal (p, pkgData, cb_) {
if (er) return cb(er)
// figure out if this is a folder or file.
fs.stat(p, function (er, s) {
- if (er) {
- // might be username/project
- // in that case, try it as a github url.
- if (p.split("/").length === 2) {
- return maybeGithub(p, er, cb)
- }
- return cb(er)
- }
+ if (er) return cb(er)
+
if (s.isDirectory()) addLocalDirectory(p, pkgData, null, cb)
else addLocalTarball(p, pkgData, null, cb)
})
diff --git a/deps/npm/lib/cache/add-named.js b/deps/npm/lib/cache/add-named.js
index 7137cc9b5..091d43c01 100644
--- a/deps/npm/lib/cache/add-named.js
+++ b/deps/npm/lib/cache/add-named.js
@@ -13,8 +13,8 @@ var path = require("path")
, locker = require("../utils/locker.js")
, lock = locker.lock
, unlock = locker.unlock
- , maybeGithub = require("./maybe-github.js")
, addRemoteTarball = require("./add-remote-tarball.js")
+ , mapToRegistry = require("../utils/map-to-registry.js")
module.exports = addNamed
@@ -48,7 +48,7 @@ function addNamed (name, version, data, cb_) {
})
}
-function addNameTag (name, tag, data, cb_) {
+function addNameTag (name, tag, data, cb) {
log.info("addNameTag", [name, tag])
var explicit = true
if (!tag) {
@@ -56,17 +56,13 @@ function addNameTag (name, tag, data, cb_) {
tag = npm.config.get("tag")
}
- function cb(er, data) {
- // might be username/project
- // in that case, try it as a github url.
- if (er && tag.split("/").length === 2) {
- return maybeGithub(tag, er, cb_)
- }
- return cb_(er, data)
- }
+ mapToRegistry(name, npm.config, function (er, uri) {
+ if (er) return cb(er)
- var uri = url.resolve(npm.config.get("registry"), name)
- registry.get(uri, null, function (er, data, json, resp) {
+ registry.get(uri, null, next)
+ })
+
+ function next (er, data, json, resp) {
if (!er) {
er = errorResponse(name, resp)
}
@@ -83,7 +79,7 @@ function addNameTag (name, tag, data, cb_) {
er = installTargetsError(tag, data)
return cb(er)
- })
+ }
}
function engineFilter (data) {
@@ -114,22 +110,28 @@ function addNameVersion (name, v, data, cb) {
response = null
return next()
}
- var uri = url.resolve(npm.config.get("registry"), name)
- registry.get(uri, null, function (er, d, json, resp) {
+
+ mapToRegistry(name, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, null, setData)
+ })
+
+ function setData (er, d, json, resp) {
if (!er) {
er = errorResponse(name, resp)
}
if (er) return cb(er)
data = d && d.versions[ver]
if (!data) {
- er = new Error('version not found: ' + name + '@' + ver)
+ er = new Error("version not found: "+name+"@"+ver)
er.package = name
er.statusCode = 404
return cb(er)
}
response = resp
next()
- })
+ }
function next () {
deprCheck(data)
@@ -166,10 +168,9 @@ function addNameVersion (name, v, data, cb) {
return cb(new Error("Cannot fetch: "+dist.tarball))
}
- // use the same protocol as the registry.
- // https registry --> https tarballs, but
- // only if they're the same hostname, or else
- // detached tarballs may not work.
+ // Use the same protocol as the registry. https registry --> https
+ // tarballs, but only if they're the same hostname, or else detached
+ // tarballs may not work.
var tb = url.parse(dist.tarball)
var rp = url.parse(npm.config.get("registry"))
if (tb.hostname === rp.hostname
@@ -179,8 +180,8 @@ function addNameVersion (name, v, data, cb) {
}
tb = url.format(tb)
- // only add non-shasum'ed packages if --forced.
- // only ancient things would lack this for good reasons nowadays.
+ // Only add non-shasum'ed packages if --forced. Only ancient things
+ // would lack this for good reasons nowadays.
if (!dist.shasum && !npm.config.get("force")) {
return cb(new Error("package lacks shasum: " + data._id))
}
@@ -197,15 +198,21 @@ function addNameRange (name, range, data, cb) {
log.silly("addNameRange", {name:name, range:range, hasData:!!data})
if (data) return next()
- var uri = url.resolve(npm.config.get("registry"), name)
- registry.get(uri, null, function (er, d, json, resp) {
+
+ mapToRegistry(name, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, null, setData)
+ })
+
+ function setData (er, d, json, resp) {
if (!er) {
er = errorResponse(name, resp)
}
if (er) return cb(er)
data = d
next()
- })
+ }
function next () {
log.silly( "addNameRange", "number 2"
diff --git a/deps/npm/lib/cache/add-remote-git.js b/deps/npm/lib/cache/add-remote-git.js
index 7743aa4a4..304d2f3f0 100644
--- a/deps/npm/lib/cache/add-remote-git.js
+++ b/deps/npm/lib/cache/add-remote-git.js
@@ -8,9 +8,7 @@ var mkdir = require("mkdirp")
, url = require("url")
, chownr = require("chownr")
, zlib = require("zlib")
- , which = require("which")
, crypto = require("crypto")
- , chmodr = require("chmodr")
, npm = require("../npm.js")
, rm = require("../utils/gently-rm.js")
, inflight = require("inflight")
@@ -28,9 +26,8 @@ var mkdir = require("mkdirp")
// 5. git archive /tmp/random.tgz
// 6. addLocalTarball(/tmp/random.tgz) <gitref> --format=tar --prefix=package/
// silent flag is used if this should error quietly
-module.exports = function addRemoteGit (u, parsed, silent, cb_) {
+module.exports = function addRemoteGit (u, silent, cb_) {
assert(typeof u === "string", "must have git URL")
- assert(typeof parsed === "object", "must have parsed query")
assert(typeof cb_ === "function", "must have callback")
function cb (er, data) {
@@ -41,6 +38,10 @@ module.exports = function addRemoteGit (u, parsed, silent, cb_) {
if (!cb_) return
+ log.verbose("addRemoteGit", "u=%j silent=%j", u, silent)
+ var parsed = url.parse(u, true)
+ log.silly("addRemoteGit", "parsed", parsed)
+
// git is so tricky!
// if the path is like ssh://foo:22/some/path then it works, but
// it needs the ssh://
@@ -62,16 +63,16 @@ module.exports = function addRemoteGit (u, parsed, silent, cb_) {
var co = parsed.hash && parsed.hash.substr(1) || "master"
var v = crypto.createHash("sha1").update(u).digest("hex").slice(0, 8)
- v = u.replace(/[^a-zA-Z0-9]+/g, '-') + '-' + v
+ v = u.replace(/[^a-zA-Z0-9]+/g, "-")+"-"+v
log.verbose("addRemoteGit", [u, co])
var p = path.join(npm.config.get("cache"), "_git-remotes", v)
checkGitDir(p, u, co, origUrl, silent, function(er, data) {
- chmodr(p, npm.modes.file, function(erChmod) {
+ addModeRecursive(p, npm.modes.file, function(erAddMode) {
if (er) return cb(er, data)
- return cb(erChmod, data)
+ return cb(erAddMode, data)
})
})
})
@@ -181,16 +182,20 @@ function archiveGitRemote (p, u, co, origUrl, cb) {
parsed.hash = stdout
resolved = url.format(parsed)
+ if (parsed.protocol !== "git:") {
+ resolved = "git+" + resolved
+ }
+
// https://github.com/npm/npm/issues/3224
// node incorrectly sticks a / at the start of the path
// We know that the host won't change, so split and detect this
var spo = origUrl.split(parsed.host)
var spr = resolved.split(parsed.host)
- if (spo[1].charAt(0) === ':' && spr[1].charAt(0) === '/')
+ if (spo[1].charAt(0) === ":" && spr[1].charAt(0) === "/")
spr[1] = spr[1].slice(1)
resolved = spr.join(parsed.host)
- log.verbose('resolved git url', resolved)
+ log.verbose("resolved git url", resolved)
next()
})
}
@@ -226,8 +231,48 @@ function gitEnv () {
if (gitEnv_) return gitEnv_
gitEnv_ = {}
for (var k in process.env) {
- if (!~['GIT_PROXY_COMMAND','GIT_SSH','GIT_SSL_NO_VERIFY'].indexOf(k) && k.match(/^GIT/)) continue
+ if (!~["GIT_PROXY_COMMAND","GIT_SSH","GIT_SSL_NO_VERIFY"].indexOf(k) && k.match(/^GIT/)) continue
gitEnv_[k] = process.env[k]
}
return gitEnv_
}
+
+// similar to chmodr except it add permissions rather than overwriting them
+// adapted from https://github.com/isaacs/chmodr/blob/master/chmodr.js
+function addModeRecursive(p, mode, cb) {
+ fs.readdir(p, function (er, children) {
+ // Any error other than ENOTDIR means it's not readable, or doesn't exist.
+ // Give up.
+ if (er && er.code !== "ENOTDIR") return cb(er)
+ if (er || !children.length) return addMode(p, mode, cb)
+
+ var len = children.length
+ var errState = null
+ children.forEach(function (child) {
+ addModeRecursive(path.resolve(p, child), mode, then)
+ })
+
+ function then (er) {
+ if (errState) return undefined
+ if (er) return cb(errState = er)
+ if (--len === 0) return addMode(p, dirMode(mode), cb)
+ }
+ })
+}
+
+function addMode(p, mode, cb) {
+ fs.stat(p, function (er, stats) {
+ if (er) return cb(er)
+ mode = stats.mode | mode
+ fs.chmod(p, mode, cb)
+ })
+}
+
+// taken from https://github.com/isaacs/chmodr/blob/master/chmodr.js
+function dirMode(mode) {
+ if (mode & parseInt("0400", 8)) mode |= parseInt("0100", 8)
+ if (mode & parseInt( "040", 8)) mode |= parseInt( "010", 8)
+ if (mode & parseInt( "04", 8)) mode |= parseInt( "01", 8)
+ return mode
+}
+
diff --git a/deps/npm/lib/cache/add-remote-tarball.js b/deps/npm/lib/cache/add-remote-tarball.js
index db9a05d82..2c7d01303 100644
--- a/deps/npm/lib/cache/add-remote-tarball.js
+++ b/deps/npm/lib/cache/add-remote-tarball.js
@@ -4,8 +4,9 @@ var mkdir = require("mkdirp")
, path = require("path")
, sha = require("sha")
, retry = require("retry")
+ , createWriteStream = require("graceful-fs").createWriteStream
, npm = require("../npm.js")
- , fetch = require("../utils/fetch.js")
+ , registry = npm.registry
, inflight = require("inflight")
, locker = require("../utils/locker.js")
, lock = locker.lock
@@ -80,27 +81,39 @@ function addRemoteTarball_(u, tmp, shasum, cb) {
}
function fetchAndShaCheck (u, tmp, shasum, cb) {
- fetch(u, tmp, function (er, response) {
+ registry.fetch(u, null, function (er, response) {
if (er) {
log.error("fetch failed", u)
return cb(er, response)
}
- if (!shasum) {
- // Well, we weren't given a shasum, so at least sha what we have
- // in case we want to compare it to something else later
- return sha.get(tmp, function (er, shasum) {
- cb(er, response, shasum)
- })
- }
+ var tarball = createWriteStream(tmp, { mode : npm.modes.file })
+ tarball.on("error", function (er) {
+ cb(er)
+ tarball.destroy()
+ })
- // validate that the url we just downloaded matches the expected shasum.
- sha.check(tmp, shasum, function (er) {
- if (er && er.message) {
- // add original filename for better debuggability
- er.message = er.message + '\n' + 'From: ' + u
+ tarball.on("finish", function () {
+ if (!shasum) {
+ // Well, we weren't given a shasum, so at least sha what we have
+ // in case we want to compare it to something else later
+ return sha.get(tmp, function (er, shasum) {
+ log.silly("fetchAndShaCheck", "shasum", shasum)
+ cb(er, response, shasum)
+ })
}
- return cb(er, response, shasum)
+
+ // validate that the url we just downloaded matches the expected shasum.
+ log.silly("fetchAndShaCheck", "shasum", shasum)
+ sha.check(tmp, shasum, function (er) {
+ if (er && er.message) {
+ // add original filename for better debuggability
+ er.message = er.message + "\n" + "From: " + u
+ }
+ return cb(er, response, shasum)
+ })
})
+
+ response.pipe(tarball)
})
}
diff --git a/deps/npm/lib/cache/get-stat.js b/deps/npm/lib/cache/get-stat.js
index 913f5af85..372a86d61 100644
--- a/deps/npm/lib/cache/get-stat.js
+++ b/deps/npm/lib/cache/get-stat.js
@@ -24,7 +24,9 @@ module.exports = function getCacheStat (cb) {
}
function makeCacheDir (cb) {
- if (!process.getuid) return mkdir(npm.cache, cb)
+ if (!process.getuid) return mkdir(npm.cache, function (er) {
+ return cb(er, {})
+ })
var uid = +process.getuid()
, gid = +process.getgid()
diff --git a/deps/npm/lib/cache/maybe-github.js b/deps/npm/lib/cache/maybe-github.js
index fee64c5df..5ecdb6915 100644
--- a/deps/npm/lib/cache/maybe-github.js
+++ b/deps/npm/lib/cache/maybe-github.js
@@ -1,29 +1,26 @@
-var url = require("url")
- , assert = require("assert")
+var assert = require("assert")
, log = require("npmlog")
, addRemoteGit = require("./add-remote-git.js")
-module.exports = function maybeGithub (p, er, cb) {
+module.exports = function maybeGithub (p, cb) {
assert(typeof p === "string", "must pass package name")
- assert(er instanceof Error, "must include error")
assert(typeof cb === "function", "must pass callback")
var u = "git://github.com/" + p
- , up = url.parse(u)
log.info("maybeGithub", "Attempting %s from %s", p, u)
- return addRemoteGit(u, up, true, function (er2, data) {
- if (er2) {
+ return addRemoteGit(u, true, function (er, data) {
+ if (er) {
var upriv = "git+ssh://git@github.com:" + p
- , uppriv = url.parse(upriv)
-
log.info("maybeGithub", "Attempting %s from %s", p, upriv)
- return addRemoteGit(upriv, uppriv, false, function (er3, data) {
- if (er3) return cb(er)
+ return addRemoteGit(upriv, false, function (er, data) {
+ if (er) return cb(er)
+
success(upriv, data)
})
}
+
success(u, data)
})
diff --git a/deps/npm/lib/dedupe.js b/deps/npm/lib/dedupe.js
index e6762e15b..74397d0cb 100644
--- a/deps/npm/lib/dedupe.js
+++ b/deps/npm/lib/dedupe.js
@@ -7,7 +7,6 @@
// much better "put pkg X at folder Y" abstraction. Oh well,
// whatever. Perfect enemy of the good, and all that.
-var url = require("url")
var fs = require("fs")
var asyncMap = require("slide").asyncMap
var path = require("path")
@@ -16,6 +15,7 @@ var semver = require("semver")
var rm = require("./utils/gently-rm.js")
var log = require("npmlog")
var npm = require("./npm.js")
+var mapToRegistry = require("./utils/map-to-registry.js")
module.exports = dedupe
@@ -61,7 +61,7 @@ function dedupe_ (dir, filter, unavoidable, dryrun, silent, cb) {
Object.keys(obj.children).forEach(function (k) {
U(obj.children[k])
})
- })
+ })(data)
// then collect them up and figure out who needs them
;(function C (obj) {
@@ -240,13 +240,19 @@ function findVersions (npm, summary, cb) {
var versions = data.versions
var ranges = data.ranges
- var uri = url.resolve(npm.config.get("registry"), name)
- npm.registry.get(uri, null, function (er, data) {
+ mapToRegistry(name, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ npm.registry.get(uri, null, next)
+ })
+
+ function next (er, data) {
var regVersions = er ? [] : Object.keys(data.versions)
var locMatch = bestMatch(versions, ranges)
- var regMatch;
var tag = npm.config.get("tag")
var distTag = data["dist-tags"] && data["dist-tags"][tag]
+
+ var regMatch
if (distTag && data.versions[distTag] && matches(distTag, ranges)) {
regMatch = distTag
} else {
@@ -254,7 +260,7 @@ function findVersions (npm, summary, cb) {
}
cb(null, [[name, has, loc, locMatch, regMatch, locs]])
- })
+ }
}, cb)
}
diff --git a/deps/npm/lib/deprecate.js b/deps/npm/lib/deprecate.js
index 175b69ceb..17dd4eab0 100644
--- a/deps/npm/lib/deprecate.js
+++ b/deps/npm/lib/deprecate.js
@@ -1,5 +1,6 @@
-var url = require("url")
- , npm = require("./npm.js")
+var npm = require("./npm.js")
+ , mapToRegistry = require("./utils/map-to-registry.js")
+ , npa = require("npm-package-arg")
module.exports = deprecate
@@ -8,16 +9,20 @@ deprecate.usage = "npm deprecate <pkg>[@<version>] <message>"
deprecate.completion = function (opts, cb) {
// first, get a list of remote packages this user owns.
// once we have a user account, then don't complete anything.
- var un = npm.config.get("username")
- if (!npm.config.get("username")) return cb()
if (opts.conf.argv.remain.length > 2) return cb()
// get the list of packages by user
- var path = "/-/by-user/"+encodeURIComponent(un)
- , uri = url.resolve(npm.config.get("registry"), path)
- npm.registry.get(uri, { timeout : 60000 }, function (er, list) {
- if (er) return cb()
- console.error(list)
- return cb(null, list[un])
+ var path = "/-/by-user/"
+ mapToRegistry(path, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ var c = npm.config.getCredentialsByURI(uri)
+ if (!(c && c.username)) return cb()
+
+ npm.registry.get(uri + c.username, { timeout : 60000 }, function (er, list) {
+ if (er) return cb()
+ console.error(list)
+ return cb(null, list[c.username])
+ })
})
}
@@ -25,11 +30,15 @@ function deprecate (args, cb) {
var pkg = args[0]
, msg = args[1]
if (msg === undefined) return cb("Usage: " + deprecate.usage)
+
// fetch the data and make sure it exists.
- pkg = pkg.split(/@/)
- var name = pkg.shift()
- , ver = pkg.join("@")
- , uri = url.resolve(npm.config.get("registry"), name)
+ var p = npa(pkg)
+
+ mapToRegistry(p.name, npm.config, next)
+
+ function next (er, uri) {
+ if (er) return cb(er)
- npm.registry.deprecate(uri, ver, msg, cb)
+ npm.registry.deprecate(uri, p.spec, msg, cb)
+ }
}
diff --git a/deps/npm/lib/docs.js b/deps/npm/lib/docs.js
index 77073fbb9..dead3f755 100644
--- a/deps/npm/lib/docs.js
+++ b/deps/npm/lib/docs.js
@@ -5,18 +5,21 @@ docs.usage += "\n"
docs.usage += "npm docs ."
docs.completion = function (opts, cb) {
- var uri = url_.resolve(npm.config.get("registry"), "/-/short")
- registry.get(uri, { timeout : 60000 }, function (er, list) {
- return cb(null, list || [])
+ mapToRegistry("/-/short", npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, { timeout : 60000 }, function (er, list) {
+ return cb(null, list || [])
+ })
})
}
-var url_ = require("url")
- , npm = require("./npm.js")
+var npm = require("./npm.js")
, registry = npm.registry
, opener = require("opener")
, path = require("path")
, log = require("npmlog")
+ , mapToRegistry = require("./utils/map-to-registry.js")
function url (json) {
return json.homepage ? json.homepage : "https://npmjs.org/package/" + json.name
@@ -38,7 +41,7 @@ function docs (args, cb) {
function getDoc (project, cb) {
project = project || '.'
- var package = path.resolve(process.cwd(), "package.json")
+ var package = path.resolve(npm.localPrefix, "package.json")
if (project === '.' || project === './') {
var json
@@ -54,8 +57,13 @@ function getDoc (project, cb) {
return opener(url(json), { command: npm.config.get("browser") }, cb)
}
- var uri = url_.resolve(npm.config.get("registry"), project + "/latest")
- registry.get(uri, { timeout : 3600 }, function (er, json) {
+ mapToRegistry(project, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri + "/latest", { timeout : 3600 }, next)
+ })
+
+ function next (er, json) {
var github = "https://github.com/" + project + "#readme"
if (er) {
@@ -64,5 +72,5 @@ function getDoc (project, cb) {
}
return opener(url(json), { command: npm.config.get("browser") }, cb)
- })
+ }
}
diff --git a/deps/npm/lib/install.js b/deps/npm/lib/install.js
index 9d2c2cfa2..82d872525 100644
--- a/deps/npm/lib/install.js
+++ b/deps/npm/lib/install.js
@@ -34,28 +34,34 @@ install.completion = function (opts, cb) {
// if it starts with https?://, then just give up, because it's a url
// for now, not yet implemented.
var registry = npm.registry
- , uri = url.resolve(npm.config.get("registry"), "-/short")
- registry.get(uri, null, function (er, pkgs) {
- if (er) return cb()
- if (!opts.partialWord) return cb(null, pkgs)
+ mapToRegistry("-/short", npm.config, function (er, uri) {
+ if (er) return cb(er)
- var name = opts.partialWord.split("@").shift()
- pkgs = pkgs.filter(function (p) {
- return p.indexOf(name) === 0
- })
+ registry.get(uri, null, function (er, pkgs) {
+ if (er) return cb()
+ if (!opts.partialWord) return cb(null, pkgs)
- if (pkgs.length !== 1 && opts.partialWord === name) {
- return cb(null, pkgs)
- }
+ var name = npa(opts.partialWord).name
+ pkgs = pkgs.filter(function (p) {
+ return p.indexOf(name) === 0
+ })
- uri = url.resolve(npm.config.get("registry"), pkgs[0])
- registry.get(uri, null, function (er, d) {
- if (er) return cb()
- return cb(null, Object.keys(d["dist-tags"] || {})
- .concat(Object.keys(d.versions || {}))
- .map(function (t) {
- return pkgs[0] + "@" + t
- }))
+ if (pkgs.length !== 1 && opts.partialWord === name) {
+ return cb(null, pkgs)
+ }
+
+ mapToRegistry(pkgs[0], npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, null, function (er, d) {
+ if (er) return cb()
+ return cb(null, Object.keys(d["dist-tags"] || {})
+ .concat(Object.keys(d.versions || {}))
+ .map(function (t) {
+ return pkgs[0] + "@" + t
+ }))
+ })
+ })
})
})
}
@@ -74,9 +80,10 @@ var npm = require("./npm.js")
, mkdir = require("mkdirp")
, lifecycle = require("./utils/lifecycle.js")
, archy = require("archy")
- , isGitUrl = require("./utils/is-git-url.js")
, npmInstallChecks = require("npm-install-checks")
, sortedObject = require("sorted-object")
+ , mapToRegistry = require("./utils/map-to-registry.js")
+ , npa = require("npm-package-arg")
function install (args, cb_) {
var hasArguments = !!args.length
@@ -112,7 +119,7 @@ function install (args, cb_) {
where = args
args = [].concat(cb_) // pass in [] to do default dep-install
cb_ = arguments[2]
- log.verbose("install", "where,what", [where, args])
+ log.verbose("install", "where, what", [where, args])
}
if (!npm.config.get("global")) {
@@ -206,7 +213,7 @@ function findPeerInvalid_ (packageMap, fpiList) {
var pkg = packageMap[packageName]
if (pkg.peerInvalid) {
- var peersDepending = {};
+ var peersDepending = {}
for (var peerName in packageMap) {
var peer = packageMap[peerName]
if (peer.peerDependencies && peer.peerDependencies[packageName]) {
@@ -338,21 +345,33 @@ function save (where, installed, tree, pretty, hasArguments, cb) {
return cb(null, installed, tree, pretty)
}
- var saveBundle = npm.config.get('save-bundle')
- var savePrefix = npm.config.get('save-prefix') || "^";
+ var saveBundle = npm.config.get("save-bundle")
+ var savePrefix = npm.config.get("save-prefix") || "^"
// each item in the tree is a top-level thing that should be saved
// to the package.json file.
// The relevant tree shape is { <folder>: {what:<pkg>} }
var saveTarget = path.resolve(where, "package.json")
- , things = Object.keys(tree).map(function (k) {
- // if "what" was a url, then save that instead.
- var t = tree[k]
- , u = url.parse(t.from)
- , w = t.what.split("@")
- if (u && u.protocol) w[1] = t.from
- return w
- }).reduce(function (set, k) {
+
+ asyncMap(Object.keys(tree), function (k, cb) {
+ // if "what" was a url, then save that instead.
+ var t = tree[k]
+ , u = url.parse(t.from)
+ , a = npa(t.what)
+ , w = [a.name, a.spec]
+
+
+ fs.stat(t.from, function (er){
+ if (!er) {
+ w[1] = "file:" + t.from
+ } else if (u && u.protocol) {
+ w[1] = t.from
+ }
+ cb(null, [w])
+ })
+ }
+ , function (er, arr) {
+ var things = arr.reduce(function (set, k) {
var rangeDescriptor = semver.valid(k[1], true) &&
semver.gte(k[1], "0.1.0", true) &&
!npm.config.get("save-exact")
@@ -361,47 +380,49 @@ function save (where, installed, tree, pretty, hasArguments, cb) {
return set
}, {})
- // don't use readJson, because we don't want to do all the other
- // tricky npm-specific stuff that's in there.
- fs.readFile(saveTarget, function (er, data) {
- // ignore errors here, just don't save it.
- try {
- data = JSON.parse(data.toString("utf8"))
- } catch (ex) {
- er = ex
- }
- if (er) {
- return cb(null, installed, tree, pretty)
- }
+ // don't use readJson, because we don't want to do all the other
+ // tricky npm-specific stuff that's in there.
+ fs.readFile(saveTarget, function (er, data) {
+ // ignore errors here, just don't save it.
+ try {
+ data = JSON.parse(data.toString("utf8"))
+ } catch (ex) {
+ er = ex
+ }
- var deps = npm.config.get("save-optional") ? "optionalDependencies"
- : npm.config.get("save-dev") ? "devDependencies"
- : "dependencies"
+ if (er) {
+ return cb(null, installed, tree, pretty)
+ }
- if (saveBundle) {
- var bundle = data.bundleDependencies || data.bundledDependencies
- delete data.bundledDependencies
- if (!Array.isArray(bundle)) bundle = []
- data.bundleDependencies = bundle.sort()
- }
+ var deps = npm.config.get("save-optional") ? "optionalDependencies"
+ : npm.config.get("save-dev") ? "devDependencies"
+ : "dependencies"
- log.verbose('saving', things)
- data[deps] = data[deps] || {}
- Object.keys(things).forEach(function (t) {
- data[deps][t] = things[t]
if (saveBundle) {
- var i = bundle.indexOf(t)
- if (i === -1) bundle.push(t)
+ var bundle = data.bundleDependencies || data.bundledDependencies
+ delete data.bundledDependencies
+ if (!Array.isArray(bundle)) bundle = []
data.bundleDependencies = bundle.sort()
}
- })
- data[deps] = sortedObject(data[deps])
+ log.verbose("saving", things)
+ data[deps] = data[deps] || {}
+ Object.keys(things).forEach(function (t) {
+ data[deps][t] = things[t]
+ if (saveBundle) {
+ var i = bundle.indexOf(t)
+ if (i === -1) bundle.push(t)
+ data.bundleDependencies = bundle.sort()
+ }
+ })
- data = JSON.stringify(data, null, 2) + "\n"
- fs.writeFile(saveTarget, data, function (er) {
- cb(er, installed, tree, pretty)
+ data[deps] = sortedObject(data[deps])
+
+ data = JSON.stringify(data, null, 2) + "\n"
+ fs.writeFile(saveTarget, data, function (er) {
+ cb(er, installed, tree, pretty)
+ })
})
})
}
@@ -412,22 +433,22 @@ function save (where, installed, tree, pretty, hasArguments, cb) {
// that the submodules are not immediately require()able.
// TODO: Show the complete tree, ls-style, but only if --long is provided
function prettify (tree, installed) {
- if (npm.config.get("json")) {
- function red (set, kv) {
- set[kv[0]] = kv[1]
- return set
- }
+ function red (set, kv) {
+ set[kv[0]] = kv[1]
+ return set
+ }
+ if (npm.config.get("json")) {
tree = Object.keys(tree).map(function (p) {
if (!tree[p]) return null
- var what = tree[p].what.split("@")
- , name = what.shift()
- , version = what.join("@")
+ var what = npa(tree[p].what)
+ , name = what.name
+ , version = what.spec
, o = { name: name, version: version, from: tree[p].from }
o.dependencies = tree[p].children.map(function P (dep) {
- var what = dep.what.split("@")
- , name = what.shift()
- , version = what.join("@")
+ var what = npa(dep.what)
+ , name = what.name
+ , version = what.spec
, o = { version: version, from: dep.from }
o.dependencies = dep.children.map(P).reduce(red, {})
return [name, o]
@@ -615,60 +636,70 @@ function installMany (what, where, context, cb) {
}
function targetResolver (where, context, deps) {
- var alreadyInstalledManually = context.explicit ? [] : null
+ var alreadyInstalledManually = []
+ , resolveLeft = 0
, nm = path.resolve(where, "node_modules")
, parent = context.parent
, wrap = context.wrap
- if (!context.explicit) fs.readdir(nm, function (er, inst) {
- if (er) return alreadyInstalledManually = []
+ if (!context.explicit) readdir(nm)
- // don't even mess with non-package looking things
- inst = inst.filter(function (p) {
- return !p.match(/^[\._-]/)
- })
+ function readdir(name) {
+ resolveLeft++
+ fs.readdir(name, function (er, inst) {
+ if (er) return resolveLeft--
- asyncMap(inst, function (pkg, cb) {
- readJson(path.resolve(nm, pkg, "package.json"), log.warn, function (er, d) {
- if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
- // error means it's not a package, most likely.
- if (er) return cb(null, [])
-
- // if it's a bundled dep, then assume that anything there is valid.
- // otherwise, make sure that it's a semver match with what we want.
- var bd = parent.bundleDependencies
- if (bd && bd.indexOf(d.name) !== -1 ||
- semver.satisfies(d.version, deps[d.name] || "*", true) ||
- deps[d.name] === d._resolved) {
- return cb(null, d.name)
- }
+ // don't even mess with non-package looking things
+ inst = inst.filter(function (p) {
+ if (!p.match(/^[@\._-]/)) return true
+ // scope pacakges
+ var scopepath = path.join(name, p)
+ readdir(scopepath)
+ })
- // see if the package had been previously linked
- fs.lstat(path.resolve(nm, pkg), function(err, s) {
- if (err) return cb(null, [])
- if (s.isSymbolicLink()) {
+ asyncMap(inst, function (pkg, cb) {
+ readJson(path.resolve(name, pkg, "package.json"), log.warn, function (er, d) {
+ if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
+ // error means it's not a package, most likely.
+ if (er) return cb(null, [])
+
+ // if it's a bundled dep, then assume that anything there is valid.
+ // otherwise, make sure that it's a semver match with what we want.
+ var bd = parent.bundleDependencies
+ if (bd && bd.indexOf(d.name) !== -1 ||
+ semver.satisfies(d.version, deps[d.name] || "*", true) ||
+ deps[d.name] === d._resolved) {
return cb(null, d.name)
}
- // something is there, but it's not satisfactory. Clobber it.
- return cb(null, [])
+ // see if the package had been previously linked
+ fs.lstat(path.resolve(nm, pkg), function(err, s) {
+ if (err) return cb(null, [])
+ if (s.isSymbolicLink()) {
+ return cb(null, d.name)
+ }
+
+ // something is there, but it's not satisfactory. Clobber it.
+ return cb(null, [])
+ })
})
+ }, function (er, inst) {
+ // this is the list of things that are valid and should be ignored.
+ alreadyInstalledManually = alreadyInstalledManually.concat(inst)
+ resolveLeft--
})
- }, function (er, inst) {
- // this is the list of things that are valid and should be ignored.
- alreadyInstalledManually = inst
})
- })
+ }
var to = 0
return function resolver (what, cb) {
- if (!alreadyInstalledManually) return setTimeout(function () {
+ if (resolveLeft) return setTimeout(function () {
resolver(what, cb)
}, to++)
// now we know what's been installed here manually,
// or tampered with in some way that npm doesn't want to overwrite.
- if (alreadyInstalledManually.indexOf(what.split("@").shift()) !== -1) {
+ if (alreadyInstalledManually.indexOf(npa(what).name) !== -1) {
log.verbose("already installed", "skipping %s %s", what, where)
return cb(null, [])
}
@@ -692,7 +723,7 @@ function targetResolver (where, context, deps) {
}
if (wrap) {
- var name = what.split(/@/).shift()
+ var name = npa(what).name
if (wrap[name]) {
var wrapTarget = readWrap(wrap[name])
what = name + "@" + wrapTarget
@@ -709,19 +740,16 @@ function targetResolver (where, context, deps) {
// already has a matching copy.
// If it's not a git repo, and the parent already has that pkg, then
// we can skip installing it again.
- cache.add(what, null, false, function (er, data) {
+ var pkgroot = path.resolve(npm.prefix, (parent && parent._from) || "")
+ cache.add(what, null, pkgroot, false, function (er, data) {
if (er && parent && parent.optionalDependencies &&
- parent.optionalDependencies.hasOwnProperty(what.split("@")[0])) {
+ parent.optionalDependencies.hasOwnProperty(npa(what).name)) {
log.warn("optional dep failed, continuing", what)
log.verbose("optional dep failed, continuing", [what, er])
return cb(null, [])
}
- var isGit = false
- , maybeGit = what.split("@").slice(1).join()
-
- if (maybeGit)
- isGit = isGitUrl(url.parse(maybeGit))
+ var isGit = npa(what).type === "git"
if (!er &&
data &&
@@ -733,6 +761,7 @@ function targetResolver (where, context, deps) {
return cb(null, [])
}
+
if (data && !data._from) data._from = what
if (er && parent && parent.name) er.parent = parent.name
return cb(er, data || [])
@@ -771,6 +800,13 @@ function localLink (target, where, context, cb) {
, parent = context.parent
readJson(jsonFile, log.warn, function (er, data) {
+ function thenLink () {
+ npm.commands.link([target.name], function (er, d) {
+ log.silly("localLink", "back from link", [er, d])
+ cb(er, [resultList(target, where, parent && parent._id)])
+ })
+ }
+
if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er || data._id === target._id) {
if (er) {
@@ -781,14 +817,6 @@ function localLink (target, where, context, cb) {
thenLink()
})
} else thenLink()
-
- function thenLink () {
- npm.commands.link([target.name], function (er, d) {
- log.silly("localLink", "back from link", [er, d])
- cb(er, [resultList(target, where, parent && parent._id)])
- })
- }
-
} else {
log.verbose("localLink", "install locally (no link)", target._id)
installOne_(target, where, context, cb)
diff --git a/deps/npm/lib/link.js b/deps/npm/lib/link.js
index 8022fc78d..8c6a93029 100644
--- a/deps/npm/lib/link.js
+++ b/deps/npm/lib/link.js
@@ -10,6 +10,7 @@ var npm = require("./npm.js")
, path = require("path")
, rm = require("./utils/gently-rm.js")
, build = require("./build.js")
+ , npa = require("npm-package-arg")
module.exports = link
@@ -49,25 +50,26 @@ function link (args, cb) {
function linkInstall (pkgs, cb) {
asyncMap(pkgs, function (pkg, cb) {
+ var t = path.resolve(npm.globalDir, "..")
+ , pp = path.resolve(npm.globalDir, pkg)
+ , rp = null
+ , target = path.resolve(npm.dir, pkg)
+
function n (er, data) {
if (er) return cb(er, data)
// install returns [ [folder, pkgId], ... ]
// but we definitely installed just one thing.
var d = data.filter(function (d) { return !d[3] })
+ var what = npa(d[0][0])
pp = d[0][1]
- pkg = path.basename(pp)
+ pkg = what.name
target = path.resolve(npm.dir, pkg)
next()
}
- var t = path.resolve(npm.globalDir, "..")
- , pp = path.resolve(npm.globalDir, pkg)
- , rp = null
- , target = path.resolve(npm.dir, pkg)
-
- // if it's a folder or a random not-installed thing, then
- // link or install it first
- if (pkg.indexOf("/") !== -1 || pkg.indexOf("\\") !== -1) {
+ // if it's a folder, a random not-installed thing, or not a scoped package,
+ // then link or install it first
+ if (pkg[0] !== "@" && (pkg.indexOf("/") !== -1 || pkg.indexOf("\\") !== -1)) {
return fs.lstat(path.resolve(pkg), function (er, st) {
if (er || !st.isDirectory()) {
npm.commands.install(t, pkg, n)
diff --git a/deps/npm/lib/ls.js b/deps/npm/lib/ls.js
index 781b6443b..ed329d19e 100644
--- a/deps/npm/lib/ls.js
+++ b/deps/npm/lib/ls.js
@@ -14,8 +14,8 @@ var npm = require("./npm.js")
, archy = require("archy")
, semver = require("semver")
, url = require("url")
- , isGitUrl = require("./utils/is-git-url.js")
, color = require("ansicolors")
+ , npa = require("npm-package-arg")
ls.usage = "npm ls"
@@ -29,9 +29,9 @@ function ls (args, silent, cb) {
// npm ls 'foo@~1.3' bar 'baz@<2'
if (!args) args = []
else args = args.map(function (a) {
- var nv = a.split("@")
- , name = nv.shift()
- , ver = semver.validRange(nv.join("@")) || ""
+ var p = npa(a)
+ , name = p.name
+ , ver = semver.validRange(p.rawSpec) || ""
return [ name, ver ]
})
@@ -39,6 +39,7 @@ function ls (args, silent, cb) {
var depth = npm.config.get("depth")
var opt = { depth: depth, log: log.warn, dev: true }
readInstalled(dir, opt, function (er, data) {
+ pruneNestedExtraneous(data)
var bfs = bfsify(data, args)
, lite = getLite(bfs)
@@ -75,6 +76,18 @@ function ls (args, silent, cb) {
})
}
+function pruneNestedExtraneous (data, visited) {
+ visited = visited || []
+ visited.push(data)
+ for (var i in data.dependencies) {
+ if (data.dependencies[i].extraneous) {
+ data.dependencies[i].dependencies = {}
+ } else if (visited.indexOf(data.dependencies[i]) === -1) {
+ pruneNestedExtraneous(data.dependencies[i], visited)
+ }
+ }
+}
+
function alphasort (a, b) {
a = a.toLowerCase()
b = b.toLowerCase()
@@ -265,7 +278,7 @@ function makeArchy_ (data, long, dir, depth, parent, d) {
// add giturl to name@version
if (data._resolved) {
- if (isGitUrl(url.parse(data._resolved)))
+ if (npa(data._resolved).type === "git")
out.label += " (" + data._resolved + ")"
}
diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js
index 3139b1d14..c811be5a9 100644
--- a/deps/npm/lib/npm.js
+++ b/deps/npm/lib/npm.js
@@ -46,16 +46,6 @@ try {
var j = JSON.parse(fs.readFileSync(
path.join(__dirname, "../package.json"))+"")
npm.version = j.version
- npm.nodeVersionRequired = j.engines.node
- if (!semver.satisfies(pv, j.engines.node)) {
- log.warn("unsupported version", [""
- ,"npm requires node version: "+j.engines.node
- ,"And you have: "+pv
- ,"which is not satisfactory."
- ,""
- ,"Bad things will likely happen. You have been warned."
- ,""].join("\n"))
- }
} catch (ex) {
try {
log.info("error reading version", ex)
@@ -153,6 +143,7 @@ var commandCache = {}
]
, plumbing = [ "build"
, "unbuild"
+ , "isntall"
, "xmas"
, "substack"
, "visnup"
diff --git a/deps/npm/lib/outdated.js b/deps/npm/lib/outdated.js
index a71df7fe7..fdfd7624d 100644
--- a/deps/npm/lib/outdated.js
+++ b/deps/npm/lib/outdated.js
@@ -28,12 +28,13 @@ var path = require("path")
, asyncMap = require("slide").asyncMap
, npm = require("./npm.js")
, url = require("url")
- , isGitUrl = require("./utils/is-git-url.js")
, color = require("ansicolors")
, styles = require("ansistyles")
, table = require("text-table")
, semver = require("semver")
, os = require("os")
+ , mapToRegistry = require("./utils/map-to-registry.js")
+ , npa = require("npm-package-arg")
function outdated (args, silent, cb) {
if (typeof cb !== "function") cb = silent, silent = false
@@ -43,7 +44,7 @@ function outdated (args, silent, cb) {
if (npm.config.get("json")) {
console.log(makeJSON(list))
} else if (npm.config.get("parseable")) {
- console.log(makeParseable(list));
+ console.log(makeParseable(list))
} else {
var outList = list.map(makePretty)
var outTable = [[ "Package"
@@ -99,7 +100,7 @@ function makePretty (p) {
function ansiTrim (str) {
var r = new RegExp("\x1b(?:\\[(?:\\d+[ABCDEFGJKSTm]|\\d+;\\d+[Hfm]|" +
- "\\d+;\\d+;\\d+m|6n|s|u|\\?25[lh])|\\w)", "g");
+ "\\d+;\\d+;\\d+m|6n|s|u|\\?25[lh])|\\w)", "g")
return str.replace(r, "")
}
@@ -114,7 +115,7 @@ function makeParseable (list) {
, dir = path.resolve(p[0], "node_modules", dep)
, has = p[2]
, want = p[3]
- , latest = p[4];
+ , latest = p[4]
return [ dir
, dep + "@" + want
@@ -264,20 +265,25 @@ function shouldUpdate (args, dir, dep, has, req, depth, cb) {
return skip()
}
- if (isGitUrl(url.parse(req)))
+ if (npa(req).type === "git")
return doIt("git", "git")
// search for the latest package
- var uri = url.resolve(npm.config.get("registry"), dep)
- npm.registry.get(uri, null, function (er, d) {
+ mapToRegistry(dep, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ npm.registry.get(uri, null, updateDeps)
+ })
+
+ function updateDeps (er, d) {
if (er) return cb()
- if (!d || !d['dist-tags'] || !d.versions) return cb()
- var l = d.versions[d['dist-tags'].latest]
+ if (!d || !d["dist-tags"] || !d.versions) return cb()
+ var l = d.versions[d["dist-tags"].latest]
if (!l) return cb()
var r = req
- if (d['dist-tags'][req])
- r = d['dist-tags'][req]
+ if (d["dist-tags"][req])
+ r = d["dist-tags"][req]
if (semver.validRange(r, true)) {
// some kind of semver range.
@@ -290,13 +296,13 @@ function shouldUpdate (args, dir, dep, has, req, depth, cb) {
}
// We didn't find the version in the doc. See if cache can find it.
- cache.add(dep, req, false, onCacheAdd)
+ cache.add(dep, req, null, false, onCacheAdd)
function onCacheAdd(er, d) {
// if this fails, then it means we can't update this thing.
// it's probably a thing that isn't published.
if (er) {
- if (er.code && er.code === 'ETARGET') {
+ if (er.code && er.code === "ETARGET") {
// no viable version found
return skip(er)
}
@@ -315,6 +321,5 @@ function shouldUpdate (args, dir, dep, has, req, depth, cb) {
else
skip()
}
-
- })
+ }
}
diff --git a/deps/npm/lib/owner.js b/deps/npm/lib/owner.js
index 34dbbc247..2fdee7adb 100644
--- a/deps/npm/lib/owner.js
+++ b/deps/npm/lib/owner.js
@@ -5,6 +5,12 @@ owner.usage = "npm owner add <username> <pkg>"
+ "\nnpm owner rm <username> <pkg>"
+ "\nnpm owner ls <pkg>"
+var npm = require("./npm.js")
+ , registry = npm.registry
+ , log = require("npmlog")
+ , readJson = require("read-package-json")
+ , mapToRegistry = require("./utils/map-to-registry.js")
+
owner.completion = function (opts, cb) {
var argv = opts.conf.argv.remain
if (argv.length > 4) return cb()
@@ -14,65 +20,78 @@ owner.completion = function (opts, cb) {
else subs.push("ls", "list")
return cb(null, subs)
}
- var un = encodeURIComponent(npm.config.get("username"))
- var theUser, uri
- switch (argv[2]) {
- case "ls":
- if (argv.length > 3) return cb()
- uri = url.resolve(npm.config.get("registry"), "-/short")
- return registry.get(uri, null, cb)
-
- case "rm":
- if (argv.length > 3) {
- theUser = encodeURIComponent(argv[3])
- uri = url.resolve(npm.config.get("registry"), "-/by-user/"+theUser+"|"+un)
- console.error(uri)
- return registry.get(uri, null, function (er, d) {
+
+ npm.commands.whoami([], true, function (er, username) {
+ if (er) return cb()
+
+ var un = encodeURIComponent(username)
+ var byUser, theUser
+ switch (argv[2]) {
+ case "ls":
+ if (argv.length > 3) return cb()
+ return mapToRegistry("-/short", npm.config, function (er, uri) {
if (er) return cb(er)
- // return the intersection
- return cb(null, d[theUser].filter(function (p) {
- // kludge for server adminery.
- return un === "isaacs" || d[un].indexOf(p) === -1
- }))
+
+ registry.get(uri, null, cb)
})
- }
- // else fallthrough
- case "add":
- if (argv.length > 3) {
- theUser = encodeURIComponent(argv[3])
- uri = url.resolve(npm.config.get("registry"), "-/by-user/"+theUser+"|"+un)
- console.error(uri)
- return registry.get(uri, null, function (er, d) {
- console.error(uri, er || d)
- // return mine that they're not already on.
+
+ case "rm":
+ if (argv.length > 3) {
+ theUser = encodeURIComponent(argv[3])
+ byUser = "-/by-user/" + theUser + "|" + un
+ return mapToRegistry(byUser, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ console.error(uri)
+ registry.get(uri, null, function (er, d) {
+ if (er) return cb(er)
+ // return the intersection
+ return cb(null, d[theUser].filter(function (p) {
+ // kludge for server adminery.
+ return un === "isaacs" || d[un].indexOf(p) === -1
+ }))
+ })
+ })
+ }
+ // else fallthrough
+ case "add":
+ if (argv.length > 3) {
+ theUser = encodeURIComponent(argv[3])
+ byUser = "-/by-user/" + theUser + "|" + un
+ return mapToRegistry(byUser, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ console.error(uri)
+ registry.get(uri, null, function (er, d) {
+ console.error(uri, er || d)
+ // return mine that they're not already on.
+ if (er) return cb(er)
+ var mine = d[un] || []
+ , theirs = d[theUser] || []
+ return cb(null, mine.filter(function (p) {
+ return theirs.indexOf(p) === -1
+ }))
+ })
+ })
+ }
+ // just list all users who aren't me.
+ return mapToRegistry("-/users", npm.config, function (er, uri) {
if (er) return cb(er)
- var mine = d[un] || []
- , theirs = d[theUser] || []
- return cb(null, mine.filter(function (p) {
- return theirs.indexOf(p) === -1
- }))
+
+ registry.get(uri, null, function (er, list) {
+ if (er) return cb()
+ return cb(null, Object.keys(list).filter(function (n) {
+ return n !== un
+ }))
+ })
})
- }
- // just list all users who aren't me.
- uri = url.resolve(npm.config.get("registry"), "-/users")
- return registry.get(uri, null, function (er, list) {
- if (er) return cb()
- return cb(null, Object.keys(list).filter(function (n) {
- return n !== un
- }))
- })
- default:
- return cb()
- }
+ default:
+ return cb()
+ }
+ })
}
-var npm = require("./npm.js")
- , registry = npm.registry
- , log = require("npmlog")
- , readJson = require("read-package-json")
- , url = require("url")
-
function owner (args, cb) {
var action = args.shift()
switch (action) {
@@ -90,18 +109,23 @@ function ls (pkg, cb) {
ls(pkg, cb)
})
- var uri = url.resolve(npm.config.get("registry"), pkg)
- registry.get(uri, null, function (er, data) {
- var msg = ""
- if (er) {
- log.error("owner ls", "Couldn't get owner data", pkg)
- return cb(er)
- }
- var owners = data.maintainers
- if (!owners || !owners.length) msg = "admin party!"
- else msg = owners.map(function (o) { return o.name +" <"+o.email+">" }).join("\n")
- console.log(msg)
- cb(er, owners)
+ mapToRegistry(pkg, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, null, function (er, data) {
+ var msg = ""
+ if (er) {
+ log.error("owner ls", "Couldn't get owner data", pkg)
+ return cb(er)
+ }
+ var owners = data.maintainers
+ if (!owners || !owners.length) msg = "admin party!"
+ else msg = owners.map(function (o) {
+ return o.name + " <" + o.email + ">"
+ }).join("\n")
+ console.log(msg)
+ cb(er, owners)
+ })
})
}
@@ -120,7 +144,7 @@ function add (user, pkg, cb) {
var o = owners[i]
if (o.name === u.name) {
log.info( "owner add"
- , "Already a package owner: "+o.name+" <"+o.email+">")
+ , "Already a package owner: " + o.name + " <" + o.email + ">")
return false
}
}
@@ -145,7 +169,7 @@ function rm (user, pkg, cb) {
return !match
})
if (!found) {
- log.info("owner rm", "Not a package owner: "+user)
+ log.info("owner rm", "Not a package owner: " + user)
return false
}
if (!m.length) return new Error(
@@ -156,15 +180,19 @@ function rm (user, pkg, cb) {
function mutate (pkg, user, mutation, cb) {
if (user) {
- var uri = url.resolve(npm.config.get("registry"), "-/user/org.couchdb.user:"+user)
- registry.get(uri, null, mutate_)
+ var byUser = "-/user/org.couchdb.user:" + user
+ mapToRegistry(byUser, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, null, mutate_)
+ })
} else {
mutate_(null, null)
}
function mutate_ (er, u) {
if (!er && user && (!u || u.error)) er = new Error(
- "Couldn't get user data for "+user+": "+JSON.stringify(u))
+ "Couldn't get user data for " + user + ": " + JSON.stringify(u))
if (er) {
log.error("owner mutate", "Error getting user data for %s", user)
@@ -172,27 +200,34 @@ function mutate (pkg, user, mutation, cb) {
}
if (u) u = { "name" : u.name, "email" : u.email }
- var uri = url.resolve(npm.config.get("registry"), pkg)
- registry.get(uri, null, function (er, data) {
- if (er) {
- log.error("owner mutate", "Error getting package data for %s", pkg)
- return cb(er)
- }
- var m = mutation(u, data.maintainers)
- if (!m) return cb() // handled
- if (m instanceof Error) return cb(m) // error
- data = { _id : data._id
- , _rev : data._rev
- , maintainers : m
- }
- var uri = url.resolve(npm.config.get("registry"), pkg+"/-rev/"+data._rev)
- registry.request("PUT", uri, { body : data }, function (er, data) {
- if (!er && data.error) er = new Error(
- "Failed to update package metadata: "+JSON.stringify(data))
+ mapToRegistry(pkg, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, null, function (er, data) {
if (er) {
- log.error("owner mutate", "Failed to update package metadata")
+ log.error("owner mutate", "Error getting package data for %s", pkg)
+ return cb(er)
}
- cb(er, data)
+ var m = mutation(u, data.maintainers)
+ if (!m) return cb() // handled
+ if (m instanceof Error) return cb(m) // error
+ data = { _id : data._id
+ , _rev : data._rev
+ , maintainers : m
+ }
+ var dataPath = pkg + "/-rev/" + data._rev
+ mapToRegistry(dataPath, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.request("PUT", uri, { body : data }, function (er, data) {
+ if (!er && data.error) er = new Error(
+ "Failed to update package metadata: " + JSON.stringify(data))
+ if (er) {
+ log.error("owner mutate", "Failed to update package metadata")
+ }
+ cb(er, data)
+ })
+ })
})
})
}
@@ -207,5 +242,5 @@ function readLocalPkg (cb) {
}
function unknown (action, cb) {
- cb("Usage: \n"+owner.usage)
+ cb("Usage: \n" + owner.usage)
}
diff --git a/deps/npm/lib/pack.js b/deps/npm/lib/pack.js
index ea94dd154..f955cb71a 100644
--- a/deps/npm/lib/pack.js
+++ b/deps/npm/lib/pack.js
@@ -40,9 +40,14 @@ function printFiles (files, cb) {
// add to cache, then cp to the cwd
function pack_ (pkg, cb) {
- cache.add(pkg, null, false, function (er, data) {
+ cache.add(pkg, null, null, false, function (er, data) {
if (er) return cb(er)
- var fname = path.resolve(data._id.replace(/@/g, "-") + ".tgz")
+
+ var name = data.name
+ // scoped packages get special treatment
+ if (name[0] === "@") name = name.substr(1).replace(/\//g, "-")
+
+ var fname = name + "-" + data.version + ".tgz"
, cached = path.resolve( npm.cache
, data.name
, data.version
diff --git a/deps/npm/lib/publish.js b/deps/npm/lib/publish.js
index ccad3ea82..701dc2b92 100644
--- a/deps/npm/lib/publish.js
+++ b/deps/npm/lib/publish.js
@@ -1,7 +1,8 @@
module.exports = publish
-var npm = require("./npm.js")
+var url = require("url")
+ , npm = require("./npm.js")
, log = require("npmlog")
, path = require("path")
, readJson = require("read-package-json")
@@ -9,6 +10,7 @@ var npm = require("./npm.js")
, chain = require("slide").chain
, Conf = require("npmconf").Conf
, RegClient = require("npm-registry-client")
+ , mapToRegistry = require("./utils/map-to-registry.js")
publish.usage = "npm publish <tarball>"
+ "\nnpm publish <folder>"
@@ -22,7 +24,10 @@ publish.completion = function (opts, cb) {
}
function publish (args, isRetry, cb) {
- if (typeof cb !== "function") cb = isRetry, isRetry = false
+ if (typeof cb !== "function") {
+ cb = isRetry
+ isRetry = false
+ }
if (args.length === 0) args = ["."]
if (args.length !== 1) return cb(publish.usage)
@@ -47,15 +52,15 @@ function publish (args, isRetry, cb) {
// That means that we can run publish/postpublish in the dir, rather than
// in the cache dir.
function cacheAddPublish (dir, didPre, isRetry, cb) {
- npm.commands.cache.add(dir, null, false, function (er, data) {
+ npm.commands.cache.add(dir, null, null, false, function (er, data) {
if (er) return cb(er)
log.silly("publish", data)
var cachedir = path.resolve( npm.cache
, data.name
, data.version
, "package" )
- chain
- ( [ !didPre && [lifecycle, data, "prepublish", cachedir]
+ chain([ !didPre &&
+ [lifecycle, data, "prepublish", cachedir]
, [publish_, dir, data, isRetry, cachedir]
, [lifecycle, data, "publish", didPre ? dir : cachedir]
, [lifecycle, data, "postpublish", didPre ? dir : cachedir] ]
@@ -66,48 +71,61 @@ function cacheAddPublish (dir, didPre, isRetry, cb) {
function publish_ (arg, data, isRetry, cachedir, cb) {
if (!data) return cb(new Error("no package.json file found"))
- // check for publishConfig hash
var registry = npm.registry
- var registryURI = npm.config.get("registry")
+ var config = npm.config
+
+ // check for publishConfig hash
if (data.publishConfig) {
- var pubConf = new Conf(npm.config)
- pubConf.save = npm.config.save.bind(npm.config)
+ config = new Conf(npm.config)
+ config.save = npm.config.save.bind(npm.config)
// don't modify the actual publishConfig object, in case we have
// to set a login token or some other data.
- pubConf.unshift(Object.keys(data.publishConfig).reduce(function (s, k) {
+ config.unshift(Object.keys(data.publishConfig).reduce(function (s, k) {
s[k] = data.publishConfig[k]
return s
}, {}))
- registry = new RegClient(pubConf)
- registryURI = pubConf.get("registry")
+ registry = new RegClient(config)
}
data._npmVersion = npm.version
- data._npmUser = { name: npm.config.get("username")
- , email: npm.config.get("email") }
delete data.modules
- if (data.private) return cb(new Error
- ("This package has been marked as private\n"
- +"Remove the 'private' field from the package.json to publish it."))
-
- var tarball = cachedir + ".tgz"
- registry.publish(registryURI, data, tarball, function (er) {
- if (er && er.code === "EPUBLISHCONFLICT"
- && npm.config.get("force") && !isRetry) {
- log.warn("publish", "Forced publish over "+data._id)
- return npm.commands.unpublish([data._id], function (er) {
- // ignore errors. Use the force. Reach out with your feelings.
- // but if it fails again, then report the first error.
- publish([arg], er || true, cb)
- })
- }
- // report the unpublish error if this was a retry and unpublish failed
- if (er && isRetry && isRetry !== true) return cb(isRetry)
+ if (data.private) return cb(
+ new Error(
+ "This package has been marked as private\n" +
+ "Remove the 'private' field from the package.json to publish it."
+ )
+ )
+
+ mapToRegistry(data.name, config, function (er, registryURI) {
if (er) return cb(er)
- console.log("+ " + data._id)
- cb()
+
+ var tarball = cachedir + ".tgz"
+
+ // we just want the base registry URL in this case
+ var registryBase = url.resolve(registryURI, ".")
+ log.verbose("publish", "registryBase", registryBase)
+
+ var c = config.getCredentialsByURI(registryBase)
+ data._npmUser = {name: c.username, email: c.email}
+
+ registry.publish(registryBase, data, tarball, function (er) {
+ if (er && er.code === "EPUBLISHCONFLICT"
+ && npm.config.get("force") && !isRetry) {
+ log.warn("publish", "Forced publish over " + data._id)
+ return npm.commands.unpublish([data._id], function (er) {
+ // ignore errors. Use the force. Reach out with your feelings.
+ // but if it fails again, then report the first error.
+ publish([arg], er || true, cb)
+ })
+ }
+ // report the unpublish error if this was a retry and unpublish failed
+ if (er && isRetry && isRetry !== true) return cb(isRetry)
+ if (er) return cb(er)
+ console.log("+ " + data._id)
+ cb()
+ })
})
}
diff --git a/deps/npm/lib/rebuild.js b/deps/npm/lib/rebuild.js
index e296451b7..ab372c6ec 100644
--- a/deps/npm/lib/rebuild.js
+++ b/deps/npm/lib/rebuild.js
@@ -5,6 +5,7 @@ var readInstalled = require("read-installed")
, semver = require("semver")
, log = require("npmlog")
, npm = require("./npm.js")
+ , npa = require("npm-package-arg")
rebuild.usage = "npm rebuild [<name>[@<version>] [name[@<version>] ...]]"
@@ -46,9 +47,9 @@ function filter (data, args, set, seen) {
else if (data.name && data._id) {
for (var i = 0, l = args.length; i < l; i ++) {
var arg = args[i]
- , nv = arg.split("@")
- , n = nv.shift()
- , v = nv.join("@")
+ , nv = npa(arg)
+ , n = nv.name
+ , v = nv.rawSpec
if (n !== data.name) continue
if (!semver.satisfies(data.version, v, true)) continue
pass = true
diff --git a/deps/npm/lib/repo.js b/deps/npm/lib/repo.js
index d209c3ca8..c6db8e37b 100644
--- a/deps/npm/lib/repo.js
+++ b/deps/npm/lib/repo.js
@@ -5,9 +5,12 @@ repo.usage = "npm repo <pkgname>"
repo.completion = function (opts, cb) {
if (opts.conf.argv.remain.length > 2) return cb()
- var uri = url_.resolve(npm.config.get("registry"), "/-/short")
- registry.get(uri, { timeout : 60000 }, function (er, list) {
- return cb(null, list || [])
+ mapToRegistry("/-/short", npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, { timeout : 60000 }, function (er, list) {
+ return cb(null, list || [])
+ })
})
}
@@ -19,10 +22,12 @@ var npm = require("./npm.js")
, path = require("path")
, readJson = require("read-package-json")
, fs = require("fs")
- , url_ = require('url')
+ , url_ = require("url")
+ , mapToRegistry = require("./utils/map-to-registry.js")
+ , npa = require("npm-package-arg")
function repo (args, cb) {
- var n = args.length && args[0].split("@").shift() || '.'
+ var n = args.length && npa(args[0]).name || "."
fs.stat(n, function (er, s) {
if (er && er.code === "ENOENT") return callRegistry(n, cb)
else if (er) return cb(er)
@@ -35,8 +40,8 @@ function repo (args, cb) {
}
function getUrlAndOpen (d, cb) {
- var r = d.repository;
- if (!r) return cb(new Error('no repository'));
+ var r = d.repository
+ if (!r) return cb(new Error('no repository'))
// XXX remove this when npm@v1.3.10 from node 0.10 is deprecated
// from https://github.com/npm/npm-www/issues/418
if (githubUserRepo(r.url))
@@ -52,10 +57,13 @@ function getUrlAndOpen (d, cb) {
}
function callRegistry (n, cb) {
- var uri = url_.resolve(npm.config.get("registry"), n + "/latest")
- registry.get(uri, { timeout : 3600 }, function (er, d) {
+ mapToRegistry(n, npm.config, function (er, uri) {
if (er) return cb(er)
- getUrlAndOpen(d, cb)
+
+ registry.get(uri + "/latest", { timeout : 3600 }, function (er, d) {
+ if (er) return cb(er)
+ getUrlAndOpen(d, cb)
+ })
})
}
diff --git a/deps/npm/lib/run-script.js b/deps/npm/lib/run-script.js
index 25e98f01d..6cb7bf7fb 100644
--- a/deps/npm/lib/run-script.js
+++ b/deps/npm/lib/run-script.js
@@ -8,7 +8,7 @@ var lifecycle = require("./utils/lifecycle.js")
, log = require("npmlog")
, chain = require("slide").chain
-runScript.usage = "npm run-script [<pkg>] <command>"
+runScript.usage = "npm run-script <command> [-- <args>]"
runScript.completion = function (opts, cb) {
@@ -21,7 +21,7 @@ runScript.completion = function (opts, cb) {
if (argv.length === 3) {
// either specified a script locally, in which case, done,
// or a package, in which case, complete against its scripts
- var json = path.join(npm.prefix, "package.json")
+ var json = path.join(npm.localPrefix, "package.json")
return readJson(json, function (er, d) {
if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
if (er) d = {}
@@ -30,7 +30,7 @@ runScript.completion = function (opts, cb) {
if (scripts.indexOf(argv[2]) !== -1) return cb()
// ok, try to find out which package it was, then
var pref = npm.config.get("global") ? npm.config.get("prefix")
- : npm.prefix
+ : npm.localPrefix
var pkgDir = path.resolve( pref, "node_modules"
, argv[2], "package.json" )
readJson(pkgDir, function (er, d) {
@@ -54,7 +54,7 @@ runScript.completion = function (opts, cb) {
})
if (npm.config.get("global")) scripts = [], next()
- else readJson(path.join(npm.prefix, "package.json"), function (er, d) {
+ else readJson(path.join(npm.localPrefix, "package.json"), function (er, d) {
if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
d = d || {}
scripts = Object.keys(d.scripts || {})
@@ -69,18 +69,18 @@ runScript.completion = function (opts, cb) {
function runScript (args, cb) {
if (!args.length) return list(cb)
- var pkgdir = args.length === 1 ? process.cwd()
- : path.resolve(npm.dir, args[0])
- , cmd = args.pop()
+
+ var pkgdir = npm.localPrefix
+ , cmd = args.shift()
readJson(path.resolve(pkgdir, "package.json"), function (er, d) {
if (er) return cb(er)
- run(d, pkgdir, cmd, cb)
+ run(d, pkgdir, cmd, args, cb)
})
}
function list(cb) {
- var json = path.join(npm.prefix, 'package.json')
+ var json = path.join(npm.localPrefix, 'package.json')
return readJson(json, function(er, d) {
if (er && er.code !== 'ENOENT' && er.code !== 'ENOTDIR') return cb(er)
if (er) d = {}
@@ -109,7 +109,7 @@ function list(cb) {
})
}
-function run (pkg, wd, cmd, cb) {
+function run (pkg, wd, cmd, args, cb) {
var cmds = []
if (!pkg.scripts) pkg.scripts = {}
if (cmd === "restart") {
@@ -124,7 +124,21 @@ function run (pkg, wd, cmd, cb) {
}
log.verbose("run-script", cmds)
chain(cmds.map(function (c) {
+ // pass cli arguments after -- to script.
+ if (pkg.scripts[c]) pkg.scripts[c] = pkg.scripts[c] + joinArgs(args)
+
// when running scripts explicitly, assume that they're trusted.
return [lifecycle, pkg, c, wd, true]
}), cb)
}
+
+// join arguments after '--' and pass them to script,
+// handle special characters such as ', ", ' '.
+function joinArgs (args) {
+ var joinedArgs = ''
+ args.forEach(function(arg, i) {
+ if (arg.match(/[ '"]/)) arg = '"' + arg.replace(/"/g, '\\"') + '"'
+ joinedArgs += ' ' + arg
+ })
+ return joinedArgs
+}
diff --git a/deps/npm/lib/search.js b/deps/npm/lib/search.js
index e7892350c..3be8b0d27 100644
--- a/deps/npm/lib/search.js
+++ b/deps/npm/lib/search.js
@@ -1,10 +1,10 @@
module.exports = exports = search
-var url = require("url")
- , npm = require("./npm.js")
+var npm = require("./npm.js")
, registry = npm.registry
, columnify = require('columnify')
+ , mapToRegistry = require("./utils/map-to-registry.js")
search.usage = "npm search [some search terms ...]"
@@ -63,10 +63,13 @@ function getFilteredData (staleness, args, notArgs, cb) {
follow : true,
staleOk : true
}
- var uri = url.resolve(npm.config.get("registry"), "-/all")
- registry.get(uri, opts, function (er, data) {
+ mapToRegistry("-/all", npm.config, function (er, uri) {
if (er) return cb(er)
- return cb(null, filter(data, args, notArgs))
+
+ registry.get(uri, opts, function (er, data) {
+ if (er) return cb(er)
+ return cb(null, filter(data, args, notArgs))
+ })
})
}
diff --git a/deps/npm/lib/star.js b/deps/npm/lib/star.js
index 9c0b4ea9e..123c4ebbb 100644
--- a/deps/npm/lib/star.js
+++ b/deps/npm/lib/star.js
@@ -1,19 +1,22 @@
module.exports = star
-var url = require("url")
- , npm = require("./npm.js")
+var npm = require("./npm.js")
, registry = npm.registry
, log = require("npmlog")
, asyncMap = require("slide").asyncMap
+ , mapToRegistry = require("./utils/map-to-registry.js")
star.usage = "npm star <package> [pkg, pkg, ...]\n"
+ "npm unstar <package> [pkg, pkg, ...]"
star.completion = function (opts, cb) {
- var uri = url.resolve(npm.config.get("registry"), "-/short")
- registry.get(uri, { timeout : 60000 }, function (er, list) {
- return cb(null, list || [])
+ mapToRegistry("-/short", npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, { timeout : 60000 }, function (er, list) {
+ return cb(null, list || [])
+ })
})
}
@@ -24,13 +27,16 @@ function star (args, cb) {
, using = !(npm.command.match(/^un/))
if (!using) s = u
asyncMap(args, function (pkg, cb) {
- var uri = url.resolve(npm.config.get("registry"), pkg)
- registry.star(uri, using, function (er, data, raw, req) {
- if (!er) {
- console.log(s + " "+pkg)
- log.verbose("star", data)
- }
- cb(er, data, raw, req)
+ mapToRegistry(pkg, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.star(uri, using, function (er, data, raw, req) {
+ if (!er) {
+ console.log(s + " "+pkg)
+ log.verbose("star", data)
+ }
+ cb(er, data, raw, req)
+ })
})
}, cb)
}
diff --git a/deps/npm/lib/stars.js b/deps/npm/lib/stars.js
index f0d2ef73a..dee5c152a 100644
--- a/deps/npm/lib/stars.js
+++ b/deps/npm/lib/stars.js
@@ -2,23 +2,26 @@ module.exports = stars
stars.usage = "npm stars [username]"
-var url = require("url")
- , npm = require("./npm.js")
+var npm = require("./npm.js")
, registry = npm.registry
, log = require("npmlog")
+ , mapToRegistry = require("./utils/map-to-registry.js")
function stars (args, cb) {
- var name = args.length === 1 ? args[0] : npm.config.get("username")
- , uri = url.resolve(npm.config.get("registry"), name)
- registry.stars(uri, showstars)
+ npm.commands.whoami([], true, function (er, username) {
+ var name = args.length === 1 ? args[0] : username
+ mapToRegistry("", npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.stars(uri, name, showstars)
+ })
+ })
function showstars (er, data) {
- if (er) {
- return cb(er)
- }
+ if (er) return cb(er)
if (data.rows.length === 0) {
- log.warn('stars', 'user has not starred any packages.')
+ log.warn("stars", "user has not starred any packages.")
} else {
data.rows.forEach(function(a) {
console.log(a.value)
diff --git a/deps/npm/lib/submodule.js b/deps/npm/lib/submodule.js
index 2231ced9c..eab4d21b0 100644
--- a/deps/npm/lib/submodule.js
+++ b/deps/npm/lib/submodule.js
@@ -9,7 +9,6 @@ var npm = require("./npm.js")
, git = require("./utils/git.js")
, asyncMap = require("slide").asyncMap
, chain = require("slide").chain
- , which = require("which")
submodule.usage = "npm submodule <pkg>"
@@ -23,7 +22,7 @@ function submodule (args, cb) {
if (args.length === 0) return cb(submodule.usage)
asyncMap(args, function (arg, cb) {
- cache.add(arg, null, false, cb)
+ cache.add(arg, null, null, false, cb)
}, function (er, pkgs) {
if (er) return cb(er)
chain(pkgs.map(function (pkg) { return function (cb) {
@@ -71,7 +70,7 @@ function addSubmodule (name, url, cb) {
var getSubmodules = function (cb) {
var args = [ "submodule", "status" ]
-
+
git.whichAndExec(args, function _(er, stdout) {
if (er) return cb(er)
var res = stdout.trim().split(/\n/).map(function (line) {
diff --git a/deps/npm/lib/tag.js b/deps/npm/lib/tag.js
index 1d04ad1f7..47e9a8c0a 100644
--- a/deps/npm/lib/tag.js
+++ b/deps/npm/lib/tag.js
@@ -5,16 +5,30 @@ tag.usage = "npm tag <project>@<version> [<tag>]"
tag.completion = require("./unpublish.js").completion
-var url = require("url")
- , npm = require("./npm.js")
+var npm = require("./npm.js")
, registry = npm.registry
+ , mapToRegistry = require("./utils/map-to-registry.js")
+ , npa = require("npm-package-arg")
+ , semver = require("semver")
function tag (args, cb) {
- var thing = (args.shift() || "").split("@")
- , project = thing.shift()
- , version = thing.join("@")
+ var thing = npa(args.shift() || "")
+ , project = thing.name
+ , version = thing.rawSpec
, t = args.shift() || npm.config.get("tag")
+
+ t = t.trim()
+
if (!project || !version || !t) return cb("Usage:\n"+tag.usage)
- var uri = url.resolve(npm.config.get("registry"), project)
- registry.tag(uri, version, t, cb)
+
+ if (semver.validRange(t)) {
+ var er = new Error("Tag name must not be a valid SemVer range: " + t)
+ return cb(er)
+ }
+
+ mapToRegistry(project, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.tag(uri, version, t, cb)
+ })
}
diff --git a/deps/npm/lib/unbuild.js b/deps/npm/lib/unbuild.js
index b594f28a9..797762436 100644
--- a/deps/npm/lib/unbuild.js
+++ b/deps/npm/lib/unbuild.js
@@ -2,7 +2,6 @@ module.exports = unbuild
unbuild.usage = "npm unbuild <folder>\n(this is plumbing)"
var readJson = require("read-package-json")
- , rm = require("./utils/gently-rm.js")
, gentlyRm = require("./utils/gently-rm.js")
, npm = require("./npm.js")
, path = require("path")
@@ -15,7 +14,7 @@ var readJson = require("read-package-json")
// args is a list of folders.
// remove any bins/etc, and then delete the folder.
function unbuild (args, silent, cb) {
- if (typeof silent === 'function') cb = silent, silent = false
+ if (typeof silent === "function") cb = silent, silent = false
asyncMap(args, unbuild_(silent), cb)
}
@@ -28,7 +27,7 @@ function unbuild_ (silent) { return function (folder, cb_) {
log.verbose(folder.substr(npm.prefix.length + 1), "unbuild")
readJson(path.resolve(folder, "package.json"), function (er, pkg) {
// if no json, then just trash it, but no scripts or whatever.
- if (er) return rm(folder, cb)
+ if (er) return gentlyRm(folder, false, cb)
readJson.cache.del(folder)
chain
( [ [lifecycle, pkg, "preuninstall", folder, false, true]
@@ -39,7 +38,7 @@ function unbuild_ (silent) { return function (folder, cb_) {
}
, [rmStuff, pkg, folder]
, [lifecycle, pkg, "postuninstall", folder, false, true]
- , [rm, folder] ]
+ , [gentlyRm, folder, undefined] ]
, cb )
})
}}
@@ -66,8 +65,8 @@ function rmBins (pkg, folder, parent, top, cb) {
log.verbose([binRoot, pkg.bin], "binRoot")
asyncMap(Object.keys(pkg.bin), function (b, cb) {
if (process.platform === "win32") {
- chain([ [rm, path.resolve(binRoot, b) + ".cmd"]
- , [rm, path.resolve(binRoot, b) ] ], cb)
+ chain([ [gentlyRm, path.resolve(binRoot, b) + ".cmd", undefined]
+ , [gentlyRm, path.resolve(binRoot, b), undefined] ], cb)
} else {
gentlyRm( path.resolve(binRoot, b)
, !npm.config.get("force") && folder
diff --git a/deps/npm/lib/unpublish.js b/deps/npm/lib/unpublish.js
index 225c1c3c4..2566cd5ae 100644
--- a/deps/npm/lib/unpublish.js
+++ b/deps/npm/lib/unpublish.js
@@ -1,40 +1,51 @@
module.exports = unpublish
-var url = require("url")
- , log = require("npmlog")
+var log = require("npmlog")
, npm = require("./npm.js")
, registry = npm.registry
, readJson = require("read-package-json")
, path = require("path")
+ , mapToRegistry = require("./utils/map-to-registry.js")
+ , npa = require("npm-package-arg")
unpublish.usage = "npm unpublish <project>[@<version>]"
unpublish.completion = function (opts, cb) {
if (opts.conf.argv.remain.length >= 3) return cb()
- var un = encodeURIComponent(npm.config.get("username"))
- if (!un) return cb()
- var uri = url.resolve(npm.config.get("registry"), "-/by-user/"+un)
- registry.get(uri, null, function (er, pkgs) {
- // do a bit of filtering at this point, so that we don't need
- // to fetch versions for more than one thing, but also don't
- // accidentally a whole project.
- pkgs = pkgs[un]
- if (!pkgs || !pkgs.length) return cb()
- var partial = opts.partialWord.split("@")
- , pp = partial.shift()
- pkgs = pkgs.filter(function (p) {
- return p.indexOf(pp) === 0
- })
- if (pkgs.length > 1) return cb(null, pkgs)
- var uri = url.resolve(npm.config.get("registry"), pkgs[0])
- registry.get(uri, null, function (er, d) {
+ npm.commands.whoami([], true, function (er, username) {
+ if (er) return cb()
+
+ var un = encodeURIComponent(username)
+ if (!un) return cb()
+ var byUser = "-/by-user/" + un
+ mapToRegistry(byUser, npm.config, function (er, uri) {
if (er) return cb(er)
- var vers = Object.keys(d.versions)
- if (!vers.length) return cb(null, pkgs)
- return cb(null, vers.map(function (v) {
- return pkgs[0]+"@"+v
- }))
+
+ registry.get(uri, null, function (er, pkgs) {
+ // do a bit of filtering at this point, so that we don't need
+ // to fetch versions for more than one thing, but also don't
+ // accidentally a whole project.
+ pkgs = pkgs[un]
+ if (!pkgs || !pkgs.length) return cb()
+ var pp = npa(opts.partialWord).name
+ pkgs = pkgs.filter(function (p) {
+ return p.indexOf(pp) === 0
+ })
+ if (pkgs.length > 1) return cb(null, pkgs)
+ mapToRegistry(pkgs[0], npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, null, function (er, d) {
+ if (er) return cb(er)
+ var vers = Object.keys(d.versions)
+ if (!vers.length) return cb(null, pkgs)
+ return cb(null, vers.map(function (v) {
+ return pkgs[0] + "@" + v
+ }))
+ })
+ })
+ })
})
})
}
@@ -42,23 +53,25 @@ unpublish.completion = function (opts, cb) {
function unpublish (args, cb) {
if (args.length > 1) return cb(unpublish.usage)
- var thing = args.length ? args.shift().split("@") : []
- , project = thing.shift()
- , version = thing.join("@")
+ var thing = args.length ? npa(args[0]) : {}
+ , project = thing.name
+ , version = thing.rawSpec
+ log.silly("unpublish", "args[0]", args[0])
+ log.silly("unpublish", "thing", thing)
if (!version && !npm.config.get("force")) {
return cb("Refusing to delete entire project.\n"
- +"Run with --force to do this.\n"
- +unpublish.usage)
+ + "Run with --force to do this.\n"
+ + unpublish.usage)
}
- if (!project || path.resolve(project) === npm.prefix) {
+ if (!project || path.resolve(project) === npm.localPrefix) {
// if there's a package.json in the current folder, then
// read the package name and version out of that.
- var cwdJson = path.join(process.cwd(), "package.json")
+ var cwdJson = path.join(npm.localPrefix, "package.json")
return readJson(cwdJson, function (er, data) {
if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
- if (er) return cb("Usage:\n"+unpublish.usage)
+ if (er) return cb("Usage:\n" + unpublish.usage)
gotProject(data.name, data.version, cb)
})
}
@@ -79,7 +92,10 @@ function gotProject (project, version, cb_) {
return cb(er)
}
- var uri = url.resolve(npm.config.get("registry"), project)
- registry.unpublish(uri, version, cb)
+ mapToRegistry(project, npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.unpublish(uri, version, cb)
+ })
})
}
diff --git a/deps/npm/lib/utils/error-handler.js b/deps/npm/lib/utils/error-handler.js
index 5c4f4c99e..788d3f8cc 100644
--- a/deps/npm/lib/utils/error-handler.js
+++ b/deps/npm/lib/utils/error-handler.js
@@ -24,13 +24,18 @@ process.on("exit", function (code) {
}
if (wroteLogFile) {
- log.error("", [""
- ,"Additional logging details can be found in:"
+ // just a line break
+ if (log.levels[log.level] <= log.levels.error) console.error("")
+
+ log.error("",
+ ["Please include the following file with any support request:"
," " + path.resolve("npm-debug.log")
].join("\n"))
wroteLogFile = false
}
- log.error("not ok", "code", code)
+ if (code) {
+ log.error("code", code)
+ }
}
var doExit = npm.config.get("_exit")
@@ -87,7 +92,6 @@ function exit (code, noLog) {
function errorHandler (er) {
- var printStack = false
// console.error("errorHandler", er)
if (!npm.config || !npm.config.loaded) {
// logging won't work unless we pretend that it's ready
@@ -112,13 +116,55 @@ function errorHandler (er) {
var m = er.code || er.message.match(/^(?:Error: )?(E[A-Z]+)/)
if (m && !er.code) er.code = m
+ ; [ "type"
+ , "fstream_path"
+ , "fstream_unc_path"
+ , "fstream_type"
+ , "fstream_class"
+ , "fstream_finish_call"
+ , "fstream_linkpath"
+ , "stack"
+ , "fstream_stack"
+ , "statusCode"
+ , "pkgid"
+ ].forEach(function (k) {
+ var v = er[k]
+ if (!v) return
+ if (k === "fstream_stack") v = v.join("\n")
+ log.verbose(k, v)
+ })
+
+ log.verbose("cwd", process.cwd())
+
+ var os = require("os")
+ // log.error("System", os.type() + " " + os.release())
+ // log.error("command", process.argv.map(JSON.stringify).join(" "))
+ // log.error("node -v", process.version)
+ // log.error("npm -v", npm.version)
+ log.error("", os.type() + " " + os.release())
+ log.error("argv", process.argv.map(JSON.stringify).join(" "))
+ log.error("node", process.version)
+ log.error("npm ", "v" + npm.version)
+
+ ; [ "file"
+ , "path"
+ , "code"
+ , "errno"
+ , "syscall"
+ ].forEach(function (k) {
+ var v = er[k]
+ if (v) log.error(k, v)
+ })
+
+ // just a line break
+ if (log.levels[log.level] <= log.levels.error) console.error("")
+
switch (er.code) {
case "ECONNREFUSED":
log.error("", er)
log.error("", ["\nIf you are behind a proxy, please make sure that the"
,"'proxy' config is set properly. See: 'npm help config'"
].join("\n"))
- printStack = true
break
case "EACCES":
@@ -126,7 +172,6 @@ function errorHandler (er) {
log.error("", er)
log.error("", ["\nPlease try running this command again as root/Administrator."
].join("\n"))
- printStack = true
break
case "ELIFECYCLE":
@@ -160,24 +205,22 @@ function errorHandler (er) {
].join("\n"), "JSON.parse")
break
+ // TODO(isaacs)
+ // Add a special case here for E401 and E403 explaining auth issues?
+
case "E404":
var msg = [er.message]
if (er.pkgid && er.pkgid !== "-") {
msg.push("", "'"+er.pkgid+"' is not in the npm registry."
- ,"You should bug the author to publish it")
+ ,"You should bug the author to publish it (or use the name yourself!)")
if (er.parent) {
msg.push("It was specified as a dependency of '"+er.parent+"'")
}
- if (er.pkgid.match(/^node[\.\-]|[\.\-]js$/)) {
- var s = er.pkgid.replace(/^node[\.\-]|[\.\-]js$/g, "")
- if (s !== er.pkgid) {
- s = s.replace(/[^a-z0-9]/g, ' ')
- msg.push("\nMaybe try 'npm search " + s + "'")
- }
- }
msg.push("\nNote that you can also install from a"
- ,"tarball, folder, or http url, or git url.")
+ ,"tarball, folder, http url, or git url.")
}
+ // There's no need to have 404 in the message as well.
+ msg[0] = msg[0].replace(/^404\s+/, "")
log.error("404", msg.join("\n"))
break
@@ -185,9 +228,6 @@ function errorHandler (er) {
log.error("publish fail", ["Cannot publish over existing version."
,"Update the 'version' field in package.json and try again."
,""
- ,"If the previous version was published in error, see:"
- ," npm help unpublish"
- ,""
,"To automatically increment version numbers, see:"
," npm help version"
].join("\n"))
@@ -295,50 +335,13 @@ function errorHandler (er) {
break
default:
- log.error("", er.stack || er.message || er)
- log.error("", ["If you need help, you may report this *entire* log,"
- ,"including the npm and node versions, at:"
+ log.error("", er.message || er)
+ log.error("", ["", "If you need help, you may report this error at:"
," <http://github.com/npm/npm/issues>"
].join("\n"))
- printStack = false
break
}
- var os = require("os")
- // just a line break
- if (log.levels[log.level] <= log.levels.error) console.error("")
- log.error("System", os.type() + " " + os.release())
- log.error("command", process.argv
- .map(JSON.stringify).join(" "))
- log.error("cwd", process.cwd())
- log.error("node -v", process.version)
- log.error("npm -v", npm.version)
-
- ; [ "file"
- , "path"
- , "type"
- , "syscall"
- , "fstream_path"
- , "fstream_unc_path"
- , "fstream_type"
- , "fstream_class"
- , "fstream_finish_call"
- , "fstream_linkpath"
- , "code"
- , "errno"
- , "stack"
- , "fstream_stack"
- ].forEach(function (k) {
- var v = er[k]
- if (k === "stack") {
- if (!printStack) return
- if (!v) v = er.message
- }
- if (!v) return
- if (k === "fstream_stack") v = v.join("\n")
- log.error(k, v)
- })
-
exit(typeof er.errno === "number" ? er.errno : 1)
}
@@ -350,17 +353,16 @@ function writeLogFile (cb) {
var fs = require("graceful-fs")
, fstr = fs.createWriteStream("npm-debug.log")
- , util = require("util")
, os = require("os")
, out = ""
log.record.forEach(function (m) {
var pref = [m.id, m.level]
if (m.prefix) pref.push(m.prefix)
- pref = pref.join(' ')
+ pref = pref.join(" ")
m.message.trim().split(/\r?\n/).map(function (line) {
- return (pref + ' ' + line).trim()
+ return (pref + " " + line).trim()
}).forEach(function (line) {
out += line + os.EOL
})
diff --git a/deps/npm/lib/utils/fetch.js b/deps/npm/lib/utils/fetch.js
deleted file mode 100644
index f6e5166ff..000000000
--- a/deps/npm/lib/utils/fetch.js
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * Fetch an HTTP url to a local file.
- **/
-
-var request = require("request")
- , fs = require("graceful-fs")
- , npm = require("../npm.js")
- , url = require("url")
- , log = require("npmlog")
- , path = require("path")
- , mkdir = require("mkdirp")
- , chownr = require("chownr")
- , regHost
- , once = require("once")
- , crypto = require("crypto")
-
-module.exports = fetch
-
-function fetch (remote, local, headers, cb) {
- if (typeof cb !== "function") cb = headers, headers = {}
- cb = once(cb)
- log.verbose("fetch", "to=", local)
- mkdir(path.dirname(local), function (er, made) {
- if (er) return cb(er)
- fetch_(remote, local, headers, cb)
- })
-}
-
-function fetch_ (remote, local, headers, cb) {
- var fstr = fs.createWriteStream(local, { mode : npm.modes.file })
- var response = null
-
- fstr.on("error", function (er) {
- cb(er)
- fstr.destroy()
- })
-
- var req = makeRequest(remote, fstr, headers)
- req.on("response", function (res) {
- log.http(res.statusCode, remote)
- response = res
- response.resume()
- // Work around bug in node v0.10.0 where the CryptoStream
- // gets stuck and never starts reading again.
- if (process.version === "v0.10.0") {
- response.resume = function (orig) { return function() {
- var ret = orig.apply(response, arguments)
- if (response.socket.encrypted)
- response.socket.encrypted.read(0)
- return ret
- }}(response.resume)
- }
- })
-
- fstr.on("close", function () {
- var er
- if (response && response.statusCode && response.statusCode >= 400) {
- er = new Error(response.statusCode + " "
- + require("http").STATUS_CODES[response.statusCode])
- }
- cb(er, response)
- })
-}
-
-function makeRequest (remote, fstr, headers) {
- remote = url.parse(remote)
- log.http("GET", remote.href)
- regHost = regHost || url.parse(npm.config.get("registry")).host
-
- if (remote.host === regHost && npm.config.get("always-auth")) {
- remote.auth = new Buffer( npm.config.get("_auth")
- , "base64" ).toString("utf8")
- if (!remote.auth) return fstr.emit("error", new Error(
- "Auth required and none provided. Please run 'npm adduser'"))
- }
-
- var proxy
- if (remote.protocol !== "https:" || !(proxy = npm.config.get("https-proxy"))) {
- proxy = npm.config.get("proxy")
- }
-
- var sessionToken = npm.registry.sessionToken
- if (!sessionToken) {
- sessionToken = crypto.randomBytes(8).toString("hex")
- npm.registry.sessionToken = sessionToken
- }
-
- var ca = remote.host === regHost ? npm.config.get("ca") : undefined
- var opts = { url: remote
- , proxy: proxy
- , strictSSL: npm.config.get("strict-ssl")
- , rejectUnauthorized: npm.config.get("strict-ssl")
- , ca: ca
- , headers:
- { "user-agent": npm.config.get("user-agent")
- , "npm-session": sessionToken
- , referer: npm.registry.refer
- }
- }
- var req = request(opts)
- req.on("error", function (er) {
- fstr.emit("error", er)
- })
- req.pipe(fstr)
- return req
-}
diff --git a/deps/npm/lib/utils/gently-rm.js b/deps/npm/lib/utils/gently-rm.js
index 241740fed..d43d0725e 100644
--- a/deps/npm/lib/utils/gently-rm.js
+++ b/deps/npm/lib/utils/gently-rm.js
@@ -3,54 +3,159 @@
module.exports = gentlyRm
-var rimraf = require("rimraf")
- , fs = require("graceful-fs")
- , npm = require("../npm.js")
- , path = require("path")
+var npm = require("../npm.js")
+ , log = require("npmlog")
+ , resolve = require("path").resolve
+ , dirname = require("path").dirname
+ , lstat = require("graceful-fs").lstat
+ , readlink = require("graceful-fs").readlink
+ , isInside = require("path-is-inside")
+ , vacuum = require("fs-vacuum")
+ , rimraf = require("rimraf")
+ , some = require("async-some")
-function gentlyRm (p, gently, cb) {
- if (!cb) cb = gently, gently = null
+function gentlyRm (path, gently, cb) {
+ if (!cb) {
+ cb = gently
+ gently = null
+ }
// never rm the root, prefix, or bin dirs.
// just a safety precaution.
- p = path.resolve(p)
- if (p === npm.dir ||
- p === npm.root ||
- p === npm.bin ||
- p === npm.prefix ||
- p === npm.globalDir ||
- p === npm.globalRoot ||
- p === npm.globalBin ||
- p === npm.globalPrefix) {
- return cb(new Error("May not delete: " + p))
+ var prefixes = [
+ npm.dir, npm.root, npm.bin, npm.prefix,
+ npm.globalDir, npm.globalRoot, npm.globalBin, npm.globalPrefix
+ ]
+
+ var resolved = resolve(path)
+ if (prefixes.indexOf(resolved) !== -1) {
+ log.verbose("gentlyRm", resolved, "is part of npm and can't be removed")
+ return cb(new Error("May not delete: "+resolved))
}
- if (npm.config.get("force") || !gently) {
- return rimraf(p, cb)
+ var options = {log : log.silly.bind(log, "gentlyRm")}
+ if (npm.config.get("force") || !gently) options.purge = true
+
+ if (!gently) {
+ log.verbose("gentlyRm", "vacuuming", resolved)
+ return vacuum(resolved, options, cb)
}
- gently = path.resolve(gently)
+ var parent = resolve(gently)
+ log.verbose("gentlyRm", "verifying that", parent, "is managed by npm")
+ some(prefixes, isManaged(parent), function (er, matched) {
+ if (er) return cb(er)
+
+ if (!matched) {
+ log.verbose("gentlyRm", parent, "is not managed by npm")
+ return clobberFail(resolved, parent, cb)
+ }
+
+ log.silly("gentlyRm", parent, "is managed by npm")
+
+ if (isInside(resolved, parent)) {
+ log.silly("gentlyRm", resolved, "is under", parent)
+ log.verbose("gentlyRm", "vacuuming", resolved, "up to", parent)
+ options.base = parent
+ return vacuum(resolved, options, cb)
+ }
+
+ log.silly("gentlyRm", resolved, "is not under", parent)
+ log.silly("gentlyRm", "checking to see if", resolved, "is a link")
+ lstat(resolved, function (er, stat) {
+ if (er) {
+ if (er.code === "ENOENT") return cb(null)
+ return cb(er)
+ }
+
+ if (!stat.isSymbolicLink()) {
+ log.verbose("gentlyRm", resolved, "is outside", parent, "and not a link")
+ return clobberFail(resolved, parent, cb)
+ }
+
+ log.silly("gentlyRm", resolved, "is a link")
+ readlink(resolved, function (er, link) {
+ if (er) {
+ if (er.code === "ENOENT") return cb(null)
+ return cb(er)
+ }
- // lstat it, see if it's a symlink.
- fs.lstat(p, function (er, s) {
- if (er) return rimraf(p, cb)
- if (!s.isSymbolicLink()) next(null, path.resolve(p))
- realish(p, next)
+ var source = resolve(dirname(resolved), link)
+ if (isInside(source, parent)) {
+ log.silly("gentlyRm", source, "inside", parent)
+ log.verbose("gentlyRm", "vacuuming", resolved)
+ return vacuum(resolved, options, cb)
+ }
+
+ log.silly("gentlyRm", "checking to see if", source, "is managed by npm")
+ some(prefixes, isManaged(source), function (er, matched) {
+ if (er) return cb(er)
+
+ if (matched) {
+ log.silly("gentlyRm", source, "is under", matched)
+ log.verbose("gentlyRm", "removing", resolved)
+ rimraf(resolved, cb)
+ }
+
+ log.verbose("gentlyRm", source, "is not managed by npm")
+ return clobberFail(path, parent, cb)
+ })
+ })
+ })
})
+}
- function next (er, rp) {
- if (rp && rp.indexOf(gently) !== 0) {
- return clobberFail(p, gently, cb)
+var resolvedPaths = {}
+function isManaged (target) {
+ return predicate
+
+ function predicate (path, cb) {
+ if (!path) {
+ log.verbose("isManaged", "no path")
+ return cb(null, false)
+ }
+
+ path = resolve(path)
+
+ // if the path has already been memoized, return immediately
+ var resolved = resolvedPaths[path]
+ if (resolved) {
+ var inside = isInside(target, resolved)
+ log.silly("isManaged", target, inside ? "is" : "is not", "inside", resolved)
+
+ return cb(null, inside && path)
}
- rimraf(p, cb)
+
+ // otherwise, check the path
+ lstat(path, function (er, stat) {
+ if (er) {
+ if (er.code === "ENOENT") return cb(null, false)
+
+ return cb(er)
+ }
+
+ // if it's not a link, cache & test the path itself
+ if (!stat.isSymbolicLink()) return cacheAndTest(path, path, target, cb)
+
+ // otherwise, cache & test the link's source
+ readlink(path, function (er, source) {
+ if (er) {
+ if (er.code === "ENOENT") return cb(null, false)
+
+ return cb(er)
+ }
+
+ cacheAndTest(resolve(path, source), path, target, cb)
+ })
+ })
}
-}
-function realish (p, cb) {
- fs.readlink(p, function (er, r) {
- if (er) return cb(er)
- return cb(null, path.resolve(path.dirname(p), r))
- })
+ function cacheAndTest (resolved, source, target, cb) {
+ resolvedPaths[source] = resolved
+ var inside = isInside(target, resolved)
+ log.silly("cacheAndTest", target, inside ? "is" : "is not", "inside", resolved)
+ cb(null, inside && source)
+ }
}
function clobberFail (p, g, cb) {
diff --git a/deps/npm/lib/utils/is-git-url.js b/deps/npm/lib/utils/is-git-url.js
deleted file mode 100644
index 7ded4b602..000000000
--- a/deps/npm/lib/utils/is-git-url.js
+++ /dev/null
@@ -1,13 +0,0 @@
-module.exports = isGitUrl
-
-function isGitUrl (url) {
- switch (url.protocol) {
- case "git:":
- case "git+http:":
- case "git+https:":
- case "git+rsync:":
- case "git+ftp:":
- case "git+ssh:":
- return true
- }
-}
diff --git a/deps/npm/lib/utils/lifecycle.js b/deps/npm/lib/utils/lifecycle.js
index 8bcb99689..c0eb83dfb 100644
--- a/deps/npm/lib/utils/lifecycle.js
+++ b/deps/npm/lib/utils/lifecycle.js
@@ -71,11 +71,6 @@ function lifecycle_ (pkg, stage, wd, env, unsafe, failOk, cb) {
, p = wd.split("node_modules")
, acc = path.resolve(p.shift())
- // first add the directory containing the `node` executable currently
- // running, so that any lifecycle script that invoke "node" will execute
- // this same one.
- pathArr.unshift(path.dirname(process.execPath))
-
p.forEach(function (pp) {
pathArr.unshift(path.join(acc, "node_modules", ".bin"))
acc = path.join(acc, "node_modules", pp)
@@ -353,13 +348,9 @@ function makeEnv (data, prefix, env) {
function cmd (stage) {
function CMD (args, cb) {
- if (args.length) {
- chain(args.map(function (p) {
- return [npm.commands, "run-script", [p, stage]]
- }), cb)
- } else npm.commands["run-script"]([stage], cb)
+ npm.commands["run-script"]([stage].concat(args), cb)
}
- CMD.usage = "npm "+stage+" <name>"
+ CMD.usage = "npm "+stage+" [-- <args>]"
var installedShallow = require("./completion/installed-shallow.js")
CMD.completion = function (opts, cb) {
installedShallow(opts, function (d) {
diff --git a/deps/npm/lib/utils/map-to-registry.js b/deps/npm/lib/utils/map-to-registry.js
new file mode 100644
index 000000000..cf665e4f6
--- /dev/null
+++ b/deps/npm/lib/utils/map-to-registry.js
@@ -0,0 +1,54 @@
+var url = require("url")
+
+var log = require("npmlog")
+ , npa = require("npm-package-arg")
+
+module.exports = mapToRegistry
+
+function mapToRegistry(name, config, cb) {
+ var uri
+ var scopedRegistry
+
+ // the name itself takes precedence
+ var data = npa(name)
+ if (data.scope) {
+ // the name is definitely scoped, so escape now
+ name = name.replace("/", "%2f")
+
+ log.silly("mapToRegistry", "scope", data.scope)
+
+ scopedRegistry = config.get(data.scope + ":registry")
+ if (scopedRegistry) {
+ log.silly("mapToRegistry", "scopedRegistry (scoped package)", scopedRegistry)
+ uri = url.resolve(scopedRegistry, name)
+ }
+ else {
+ log.verbose("mapToRegistry", "no registry URL found for scope", data.scope)
+ }
+ }
+
+ // ...then --scope=@scope or --scope=scope
+ var scope = config.get("scope")
+ if (!uri && scope) {
+ // I'm an enabler, sorry
+ if (scope.charAt(0) !== "@") scope = "@" + scope
+
+ scopedRegistry = config.get(scope + ":registry")
+ if (scopedRegistry) {
+ log.silly("mapToRegistry", "scopedRegistry (scope in config)", scopedRegistry)
+ uri = url.resolve(scopedRegistry, name)
+ }
+ else {
+ log.verbose("mapToRegistry", "no registry URL found for scope", scope)
+ }
+ }
+
+ // ...and finally use the default registry
+ if (!uri) {
+ uri = url.resolve(config.get("registry"), name)
+ }
+
+ log.verbose("mapToRegistry", "name", name)
+ log.verbose("mapToRegistry", "uri", uri)
+ cb(null, uri)
+}
diff --git a/deps/npm/lib/version.js b/deps/npm/lib/version.js
index 95d5ff2ee..5091ab9e2 100644
--- a/deps/npm/lib/version.js
+++ b/deps/npm/lib/version.js
@@ -23,7 +23,7 @@ version.usage = "npm version [<newversion> | major | minor | patch | prerelease
function version (args, silent, cb_) {
if (typeof cb_ !== "function") cb_ = silent, silent = false
if (args.length > 1) return cb_(version.usage)
- fs.readFile(path.join(process.cwd(), "package.json"), function (er, data) {
+ fs.readFile(path.join(npm.localPrefix, "package.json"), function (er, data) {
if (!args.length) {
var v = {}
Object.keys(process.versions).forEach(function (k) {
@@ -63,7 +63,7 @@ function version (args, silent, cb_) {
if (data.version === newVer) return cb_(new Error("Version not changed"))
data.version = newVer
- fs.stat(path.join(process.cwd(), ".git"), function (er, s) {
+ fs.stat(path.join(npm.localPrefix, ".git"), function (er, s) {
function cb (er) {
if (!er && !silent) console.log("v" + newVer)
cb_(er)
@@ -111,7 +111,7 @@ function checkGit (data, cb) {
}
function write (data, cb) {
- fs.writeFile( path.join(process.cwd(), "package.json")
+ fs.writeFile( path.join(npm.localPrefix, "package.json")
, new Buffer(JSON.stringify(data, null, 2) + "\n")
, cb )
}
diff --git a/deps/npm/lib/view.js b/deps/npm/lib/view.js
index 33bf550dd..43d09cbbc 100644
--- a/deps/npm/lib/view.js
+++ b/deps/npm/lib/view.js
@@ -4,21 +4,26 @@ module.exports = view
view.usage = "npm view pkg[@version] [<field>[.subfield]...]"
view.completion = function (opts, cb) {
- var uri
if (opts.conf.argv.remain.length <= 2) {
- uri = url.resolve(npm.config.get("registry"), "-/short")
- return registry.get(uri, null, cb)
+ return mapToRegistry("-/short", npm.config, function (er, uri) {
+ if (er) return cb(er)
+
+ registry.get(uri, null, cb)
+ })
}
// have the package, get the fields.
var tag = npm.config.get("tag")
- uri = url.resolve(npm.config.get("registry"), opts.conf.argv.remain[2])
- registry.get(uri, null, function (er, d) {
+ mapToRegistry(opts.conf.argv.remain[2], npm.config, function (er, uri) {
if (er) return cb(er)
- var dv = d.versions[d["dist-tags"][tag]]
- , fields = []
- d.versions = Object.keys(d.versions).sort(semver.compareLoose)
- fields = getFields(d).concat(getFields(dv))
- cb(null, fields)
+
+ registry.get(uri, null, function (er, d) {
+ if (er) return cb(er)
+ var dv = d.versions[d["dist-tags"][tag]]
+ , fields = []
+ d.versions = Object.keys(d.versions).sort(semver.compareLoose)
+ fields = getFields(d).concat(getFields(dv))
+ cb(null, fields)
+ })
})
function getFields (d, f, pref) {
@@ -42,71 +47,75 @@ view.completion = function (opts, cb) {
}
}
-var url = require("url")
- , npm = require("./npm.js")
+var npm = require("./npm.js")
, registry = npm.registry
, log = require("npmlog")
, util = require("util")
, semver = require("semver")
+ , mapToRegistry = require("./utils/map-to-registry.js")
+ , npa = require("npm-package-arg")
function view (args, silent, cb) {
if (typeof cb !== "function") cb = silent, silent = false
if (!args.length) return cb("Usage: "+view.usage)
var pkg = args.shift()
- , nv = pkg.split("@")
- , name = nv.shift()
- , version = nv.join("@") || npm.config.get("tag")
+ , nv = npa(pkg)
+ , name = nv.name
+ , version = nv.rawSpec || npm.config.get("tag")
if (name === ".") return cb(view.usage)
// get the data about this package
- var uri = url.resolve(npm.config.get("registry"), name)
- registry.get(uri, null, function (er, data) {
+ mapToRegistry(name, npm.config, function (er, uri) {
if (er) return cb(er)
- if (data["dist-tags"] && data["dist-tags"].hasOwnProperty(version)) {
- version = data["dist-tags"][version]
- }
- if (data.time && data.time.unpublished) {
- var u = data.time.unpublished
- er = new Error("Unpublished by " + u.name + " on " + u.time)
- er.statusCode = 404
- er.code = "E404"
- er.pkgid = data._id
- return cb(er, data)
- }
+ registry.get(uri, null, function (er, data) {
+ if (er) return cb(er)
+ if (data["dist-tags"] && data["dist-tags"].hasOwnProperty(version)) {
+ version = data["dist-tags"][version]
+ }
+ if (data.time && data.time.unpublished) {
+ var u = data.time.unpublished
+ er = new Error("Unpublished by " + u.name + " on " + u.time)
+ er.statusCode = 404
+ er.code = "E404"
+ er.pkgid = data._id
+ return cb(er, data)
+ }
- var results = []
- , error = null
- , versions = data.versions || {}
- data.versions = Object.keys(versions).sort(semver.compareLoose)
- if (!args.length) args = [""]
- // remove readme unless we asked for it
- if (-1 === args.indexOf("readme")) {
- delete data.readme
- }
+ var results = []
+ , error = null
+ , versions = data.versions || {}
+ data.versions = Object.keys(versions).sort(semver.compareLoose)
+ if (!args.length) args = [""]
+
+ // remove readme unless we asked for it
+ if (-1 === args.indexOf("readme")) {
+ delete data.readme
+ }
- Object.keys(versions).forEach(function (v) {
- if (semver.satisfies(v, version, true)) args.forEach(function (args) {
- // remove readme unless we asked for it
- if (-1 === args.indexOf("readme")) {
- delete versions[v].readme
- }
- results.push(showFields(data, versions[v], args))
+ Object.keys(versions).forEach(function (v) {
+ if (semver.satisfies(v, version, true)) args.forEach(function (args) {
+ // remove readme unless we asked for it
+ if (-1 === args.indexOf("readme")) {
+ delete versions[v].readme
+ }
+ results.push(showFields(data, versions[v], args))
+ })
})
- })
- results = results.reduce(reducer, {})
- var retval = results
+ results = results.reduce(reducer, {})
+ var retval = results
- if (args.length === 1 && args[0] === "") {
- retval = cleanBlanks(retval)
- log.silly("cleanup", retval)
- }
+ if (args.length === 1 && args[0] === "") {
+ retval = cleanBlanks(retval)
+ log.silly("cleanup", retval)
+ }
- if (error || silent) cb(error, retval)
- else printData(results, data._id, cb.bind(null, error, retval))
+ if (error || silent) cb(error, retval)
+ else printData(results, data._id, cb.bind(null, error, retval))
+ })
})
}
diff --git a/deps/npm/lib/whoami.js b/deps/npm/lib/whoami.js
index f1c67e2b0..b33f93743 100644
--- a/deps/npm/lib/whoami.js
+++ b/deps/npm/lib/whoami.js
@@ -1,13 +1,39 @@
-module.exports = whoami
-
var npm = require("./npm.js")
-whoami.usage = "npm whoami\n(just prints the 'username' config)"
+module.exports = whoami
+
+whoami.usage = "npm whoami\n(just prints username according to given registry)"
function whoami (args, silent, cb) {
- if (typeof cb !== "function") cb = silent, silent = false
- var me = npm.config.get("username")
- var msg = me ? me : "Not authed. Run 'npm adduser'"
+ // FIXME: need tighter checking on this, but is a breaking change
+ if (typeof cb !== "function") {
+ cb = silent
+ silent = false
+ }
+
+ var registry = npm.config.get("registry")
+ if (!registry) return cb(new Error("no default registry set"))
+
+ var credentials = npm.config.getCredentialsByURI(registry)
+ if (credentials) {
+ if (credentials.username) {
+ if (!silent) console.log(credentials.username)
+ return process.nextTick(cb.bind(this, null, credentials.username))
+ }
+ else if (credentials.token) {
+ return npm.registry.whoami(registry, function (er, username) {
+ if (er) return cb(er)
+
+ if (!silent) console.log(username)
+ cb(null, username)
+ })
+ }
+ }
+
+ // At this point, if they have a credentials object, it doesn't
+ // have a token or auth in it. Probably just the default
+ // registry.
+ var msg = "Not authed. Run 'npm adduser'"
if (!silent) console.log(msg)
- process.nextTick(cb.bind(this, null, me))
+ process.nextTick(cb.bind(this, null, msg))
}