diff options
Diffstat (limited to 'deps/npm/lib')
-rw-r--r-- | deps/npm/lib/cache.js | 91 | ||||
-rw-r--r-- | deps/npm/lib/dedupe.js | 22 | ||||
-rw-r--r-- | deps/npm/lib/install.js | 4 | ||||
-rw-r--r-- | deps/npm/lib/link.js | 6 | ||||
-rw-r--r-- | deps/npm/lib/ls.js | 3 | ||||
-rw-r--r-- | deps/npm/lib/npm.js | 10 | ||||
-rw-r--r-- | deps/npm/lib/outdated.js | 109 | ||||
-rw-r--r-- | deps/npm/lib/prune.js | 3 | ||||
-rw-r--r-- | deps/npm/lib/rebuild.js | 3 | ||||
-rw-r--r-- | deps/npm/lib/shrinkwrap.js | 17 | ||||
-rw-r--r-- | deps/npm/lib/unbuild.js | 2 | ||||
-rw-r--r-- | deps/npm/lib/utils/completion/installed-deep.js | 8 | ||||
-rw-r--r-- | deps/npm/lib/utils/gently-rm.js | 16 | ||||
-rw-r--r-- | deps/npm/lib/utils/tar.js | 2 | ||||
-rw-r--r-- | deps/npm/lib/view.js | 2 |
15 files changed, 221 insertions, 77 deletions
diff --git a/deps/npm/lib/cache.js b/deps/npm/lib/cache.js index cc4546083..3b9a46f69 100644 --- a/deps/npm/lib/cache.js +++ b/deps/npm/lib/cache.js @@ -64,7 +64,7 @@ var mkdir = require("mkdirp") , fetch = require("./utils/fetch.js") , npm = require("./npm.js") , fs = require("graceful-fs") - , rm = require("rimraf") + , rm = require("./utils/gently-rm.js") , readJson = require("read-package-json") , registry = npm.registry , log = require("npmlog") @@ -249,16 +249,48 @@ function add (args, cb) { var p = url.parse(spec) || {} log.verbose("parsed url", p) - // it could be that we got name@http://blah + // 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 && spec.indexOf("@") !== -1) { - spec = spec.split("@") - name = spec.shift() - spec = spec.join("@") - return add([name, spec], cb) + if (!name && !p.protocol) { + if (spec.indexOf("/") !== -1 || + process.platform === "win32" && spec.indexOf("\\") !== -1) { + return maybeFile(spec, p, cb) + } else if (spec.indexOf("@") !== -1) { + return maybeAt(spec, cb) + } } + add_(name, spec, p, cb) +} + +function maybeFile (spec, p, cb) { + fs.stat(spec, function (er, stat) { + if (!er) { + // definitely a local thing + addLocal(spec, cb) + } else if (er && spec.indexOf("@") !== -1) { + // bar@baz/loofa + maybeAt(spec, cb) + } else { + // Already know it's not a url, so must be local + addLocal(spec, cb) + } + }) +} + +function maybeAt (spec, cb) { + var tmp = spec.split("@") + + // split name@2.3.4 only if name is a valid package name, + // don't split in case of "./test@example.com/" (local path) + var name = tmp.shift() + spec = tmp.join("@") + return add([name, spec], cb) +} + +function add_ (name, spec, p, cb) { switch (p.protocol) { case "http:": case "https:": @@ -378,41 +410,40 @@ function addRemoteGit (u, parsed, name, silent, cb_) { iF.push(cb_) if (iF.length > 1) return + // git is so tricky! + // if the path is like ssh://foo:22/some/path then it works, but + // it needs the ssh:// + // If the path is like ssh://foo:some/path then it works, but + // only if you remove the ssh:// + var origUrl = u + u = u.replace(/^git\+/, "") + .replace(/#.*$/, "") + + // ssh paths that are scp-style urls don't need the ssh:// + if (parsed.pathname.match(/^\/?:/)) { + u = u.replace(/^ssh:\/\//, "") + } + function cb (er, data) { unlock(u, function () { var c while (c = iF.shift()) c(er, data) - delete inFlightURLs[u] + delete inFlightURLs[origUrl] }) } - var p, co // cachePath, git-ref we want to check out - lock(u, function (er) { if (er) return cb(er) // figure out what we should check out. var co = parsed.hash && parsed.hash.substr(1) || "master" - // git is so tricky! - // if the path is like ssh://foo:22/some/path then it works, but - // it needs the ssh:// - // If the path is like ssh://foo:some/path then it works, but - // only if you remove the ssh:// - var origUrl = u - u = u.replace(/^git\+/, "") - .replace(/#.*$/, "") - - // ssh paths that are scp-style urls don't need the ssh:// - if (parsed.pathname.match(/^\/?:/)) { - u = u.replace(/^ssh:\/\//, "") - } var v = crypto.createHash("sha1").update(u).digest("hex").slice(0, 8) v = u.replace(/[^a-zA-Z0-9]+/g, '-') + '-' + v log.verbose("addRemoteGit", [u, co]) - p = path.join(npm.config.get("cache"), "_git-remotes", v) + 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) { @@ -1263,9 +1294,15 @@ function lock (u, cb) { function unlock (u, cb) { var lf = lockFileName(u) - if (!myLocks[lf]) return process.nextTick(cb) - myLocks[lf] = false - lockFile.unlock(lockFileName(u), cb) + , locked = myLocks[lf] + if (locked === false) { + return process.nextTick(cb) + } else if (locked === true) { + myLocks[lf] = false + lockFile.unlock(lockFileName(u), cb) + } else { + throw new Error("Attempt to unlock " + u + ", which hasn't been locked") + } } function needName(er, data) { diff --git a/deps/npm/lib/dedupe.js b/deps/npm/lib/dedupe.js index ce161a46c..55823d967 100644 --- a/deps/npm/lib/dedupe.js +++ b/deps/npm/lib/dedupe.js @@ -16,7 +16,7 @@ var util = require("util") var RegClient = require("npm-registry-client") var npmconf = require("npmconf") var semver = require("semver") -var rimraf = require("rimraf") +var rm = require("./utils/gently-rm.js") var log = require("npmlog") var npm = require("./npm.js") @@ -208,7 +208,7 @@ function installAndRetest (set, filter, dir, unavoidable, silent, cb) { }, function (er, installed) { if (er) return cb(er) - asyncMap(remove, rimraf, function (er) { + asyncMap(remove, rm, function (er) { if (er) return cb(er) remove.forEach(function (r) { log.info("rm", r) @@ -249,10 +249,10 @@ function findVersions (npm, summary, cb) { var regVersions = er ? [] : Object.keys(data.versions) var locMatch = bestMatch(versions, ranges) var regMatch; - var tag = npm.config.get("tag"); - var distTags = data["dist-tags"]; - if (distTags && distTags[tag] && data.versions[distTags[tag]]) { - regMatch = distTags[tag] + var tag = npm.config.get("tag") + var distTag = data["dist-tags"] && data["dist-tags"][tag] + if (distTag && data.versions[distTag] && matches(distTag, ranges)) { + regMatch = distTag } else { regMatch = bestMatch(regVersions, ranges) } @@ -262,11 +262,15 @@ function findVersions (npm, summary, cb) { }, cb) } +function matches (version, ranges) { + return !ranges.some(function (r) { + return !semver.satisfies(version, r, true) + }) +} + function bestMatch (versions, ranges) { return versions.filter(function (v) { - return !ranges.some(function (r) { - return !semver.satisfies(v, r, true) - }) + return matches(v, ranges) }).sort(semver.compareLoose).pop() } diff --git a/deps/npm/lib/install.js b/deps/npm/lib/install.js index f0604a9ce..92a490785 100644 --- a/deps/npm/lib/install.js +++ b/deps/npm/lib/install.js @@ -187,7 +187,7 @@ function install (args, cb_) { } function findPeerInvalid (where, cb) { - readInstalled(where, log.warn, function (er, data) { + readInstalled(where, { log: log.warn }, function (er, data) { if (er) return cb(er) cb(null, findPeerInvalid_(data.dependencies, [])) @@ -351,7 +351,7 @@ function save (where, installed, tree, pretty, hasArguments, cb) { }).reduce(function (set, k) { var rangeDescriptor = semver.valid(k[1], true) && semver.gte(k[1], "0.1.0", true) - ? "~" : "" + ? "^" : "" set[k[0]] = rangeDescriptor + k[1] return set }, {}) diff --git a/deps/npm/lib/link.js b/deps/npm/lib/link.js index 4ecd64ac3..562846550 100644 --- a/deps/npm/lib/link.js +++ b/deps/npm/lib/link.js @@ -8,7 +8,7 @@ var npm = require("./npm.js") , asyncMap = require("slide").asyncMap , chain = require("slide").chain , path = require("path") - , rm = require("rimraf") + , rm = require("./utils/gently-rm.js") , build = require("./build.js") module.exports = link @@ -121,6 +121,10 @@ function linkPkg (folder, cb_) { return cb_(er, [[d && d._id, target, null, null]]) } if (er) return cb(er) + if (!d.name) { + er = new Error("Package must have a name field to be linked") + return cb(er) + } var target = path.resolve(npm.globalDir, d.name) rm(target, function (er) { if (er) return cb(er) diff --git a/deps/npm/lib/ls.js b/deps/npm/lib/ls.js index 194aae635..dc56b0ef2 100644 --- a/deps/npm/lib/ls.js +++ b/deps/npm/lib/ls.js @@ -36,7 +36,8 @@ function ls (args, silent, cb) { }) var depth = npm.config.get("depth") - readInstalled(dir, depth, log.warn, function (er, data) { + var opt = { depth: depth, log: log.warn } + readInstalled(dir, opt, function (er, data) { var bfs = bfsify(data, args) , lite = getLite(bfs) diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js index 858a5e8c4..7b3826290 100644 --- a/deps/npm/lib/npm.js +++ b/deps/npm/lib/npm.js @@ -31,7 +31,15 @@ var EventEmitter = require("events").EventEmitter , chain = slide.chain , RegClient = require("npm-registry-client") -npm.config = {loaded: false} +npm.config = { + loaded: false, + get: function() { + throw new Error('npm.load() required') + }, + set: function() { + throw new Error('npm.load() required') + } +} // /usr/local is often a read-only fs, which is not // well handled by node or mkdirp. Just double-check diff --git a/deps/npm/lib/outdated.js b/deps/npm/lib/outdated.js index 5eb49737f..6ca348726 100644 --- a/deps/npm/lib/outdated.js +++ b/deps/npm/lib/outdated.js @@ -9,6 +9,9 @@ Does the following: If no packages are specified, then run for all installed packages. +--parseable creates output like this: +<fullpath>:<name@wanted>:<name@installed>:<name@latest> + */ module.exports = outdated @@ -29,6 +32,8 @@ var path = require("path") , color = require("ansicolors") , styles = require("ansistyles") , table = require("text-table") + , semver = require("semver") + , os = require("os") function outdated (args, silent, cb) { if (typeof cb !== "function") cb = silent, silent = false @@ -37,14 +42,23 @@ function outdated (args, silent, cb) { if (er || silent) return cb(er, list) if (npm.config.get("json")) { console.log(makeJSON(list)) + } else if (npm.config.get("parseable")) { + console.log(makeParseable(list)); } else { var outList = list.map(makePretty) - var outTable = [[ styles.underline("Package") - , styles.underline("Current") - , styles.underline("Wanted") - , styles.underline("Latest") - , styles.underline("Location") + var outTable = [[ "Package" + , "Current" + , "Wanted" + , "Latest" + , "Location" ]].concat(outList) + + if (npm.color) { + outTable[0] = outTable[0].map(function(heading) { + return styles.underline(heading) + }) + } + var tableOpts = { align: ["l", "r", "r", "r", "l"] , stringLength: function(s) { return ansiTrim(s).length } } @@ -54,37 +68,34 @@ function outdated (args, silent, cb) { }) } -// [[ dir, dep, has, want ]] +// [[ dir, dep, has, want, latest ]] function makePretty (p) { var parseable = npm.config.get("parseable") - , long = npm.config.get("long") , dep = p[1] , dir = path.resolve(p[0], "node_modules", dep) , has = p[2] , want = p[3] , latest = p[4] - // XXX add --json support - // Should match (more or less) the output of ls --json - - if (parseable) { - var str = dir - if (npm.config.get("long")) { - str += ":" + dep + "@" + want - + ":" + (has ? (dep + "@" + has) : "MISSING") - } - return str - } - if (!npm.config.get("global")) { dir = path.relative(process.cwd(), dir) } - return [ has === want ? color.yellow(dep) : color.red(dep) - , (has || "MISSING") - , color.green(want) - , color.magenta(latest) - , color.brightBlack(dirToPrettyLocation(dir)) - ] + + var columns = [ dep + , has || "MISSING" + , want + , latest + , dirToPrettyLocation(dir) + ] + + if (npm.color) { + columns[0] = color[has === want ? "yellow" : "red"](columns[0]) // dep + columns[2] = color.green(columns[2]) // want + columns[3] = color.magenta(columns[3]) // latest + columns[4] = color.brightBlack(columns[4]) // dir + } + + return columns } function ansiTrim (str) { @@ -98,6 +109,22 @@ function dirToPrettyLocation (dir) { .replace(/[[/\\]node_modules[/\\]/g, " > ") } +function makeParseable (list) { + return list.map(function (p) { + var dep = p[1] + , dir = path.resolve(p[0], "node_modules", dep) + , has = p[2] + , want = p[3] + , latest = p[4]; + + return [ dir + , dep + "@" + want + , (has ? (dep + "@" + has) : "MISSING") + , dep + "@" + latest + ].join(":") + }).join(os.EOL) +} + function makeJSON (list) { var out = {} list.forEach(function (p) { @@ -222,10 +249,33 @@ function shouldUpdate (args, dir, dep, has, req, depth, cb) { var registry = npm.registry // search for the latest package - registry.get(dep + "/latest", function (er, l) { + registry.get(dep, function (er, d) { if (er) return cb() - // so, we can conceivably update this. find out if we need to. - cache.add(dep, req, function (er, d) { + if (!d || !d['dist-tags'] || !d.versions) return cb() + var l = d.versions[d['dist-tags'].latest] + if (!l) return cb() + + // set to true if found in doc + var found = false + + var r = req + if (d['dist-tags'][req]) + r = d['dist-tags'][req] + + if (semver.validRange(r, true)) { + // some kind of semver range. + // see if it's in the doc. + var vers = Object.keys(d.versions) + var v = semver.maxSatisfying(vers, r, true) + if (v) { + return onCacheAdd(null, d.versions[v]) + } + } + + // We didn't find the version in the doc. See if cache can find it. + cache.add(dep, req, 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) { @@ -247,6 +297,7 @@ function shouldUpdate (args, dir, dep, has, req, depth, cb) { doIt(d.version, l.version) else skip() - }) + } + }) } diff --git a/deps/npm/lib/prune.js b/deps/npm/lib/prune.js index 0e13da13b..8fa3e5d50 100644 --- a/deps/npm/lib/prune.js +++ b/deps/npm/lib/prune.js @@ -21,7 +21,8 @@ function prune (args, cb) { }) function next() { - readInstalled(npm.prefix, npm.config.get("depth"), function (er, data) { + var opt = { depth: npm.config.get("depth"), dev: npm.config.get("production") } + readInstalled(npm.prefix, opt, function (er, data) { if (er) return cb(er) prune_(args, data, cb) }) diff --git a/deps/npm/lib/rebuild.js b/deps/npm/lib/rebuild.js index 7cea3efff..a156acccf 100644 --- a/deps/npm/lib/rebuild.js +++ b/deps/npm/lib/rebuild.js @@ -14,7 +14,8 @@ rebuild.usage = "npm rebuild [<name>[@<version>] [name[@<version>] ...]]" rebuild.completion = require("./utils/completion/installed-deep.js") function rebuild (args, cb) { - readInstalled(npm.prefix, npm.config.get("depth"), function (er, data) { + var opt = { depth: npm.config.get("depth") } + readInstalled(npm.prefix, opt, function (er, data) { log.info("readInstalled", typeof data) if (er) return cb(er) var set = filter(data, args) diff --git a/deps/npm/lib/shrinkwrap.js b/deps/npm/lib/shrinkwrap.js index 14711df26..4aed5964e 100644 --- a/deps/npm/lib/shrinkwrap.js +++ b/deps/npm/lib/shrinkwrap.js @@ -38,6 +38,11 @@ function shrinkwrap_ (pkginfo, silent, dev, cb) { return cb(er) if (data.devDependencies) { Object.keys(data.devDependencies).forEach(function (dep) { + if (data.dependencies && data.dependencies[dep]) { + // do not exclude the dev dependency if it's also listed as a dependency + return + } + log.warn("shrinkwrap", "Excluding devDependency: %s", dep) delete pkginfo.dependencies[dep] }) @@ -51,6 +56,9 @@ function shrinkwrap_ (pkginfo, silent, dev, cb) { function save (pkginfo, silent, cb) { + // copy the keys over in a well defined order + // because javascript objects serialize arbitrarily + pkginfo.dependencies = copyOrder(pkginfo.dependencies) try { var swdata = JSON.stringify(pkginfo, null, 2) + "\n" } catch (er) { @@ -67,3 +75,12 @@ function save (pkginfo, silent, cb) { cb(null, pkginfo) }) } + +function copyOrder(obj) { + var result = {} + var keys = Object.keys(obj).sort() + keys.forEach(function (key) { + result[key] = obj[key] + }) + return result +} diff --git a/deps/npm/lib/unbuild.js b/deps/npm/lib/unbuild.js index 57688f069..0384a733e 100644 --- a/deps/npm/lib/unbuild.js +++ b/deps/npm/lib/unbuild.js @@ -2,7 +2,7 @@ module.exports = unbuild unbuild.usage = "npm unbuild <folder>\n(this is plumbing)" var readJson = require("read-package-json") - , rm = require("rimraf") + , rm = require("./utils/gently-rm.js") , gentlyRm = require("./utils/gently-rm.js") , npm = require("./npm.js") , path = require("path") diff --git a/deps/npm/lib/utils/completion/installed-deep.js b/deps/npm/lib/utils/completion/installed-deep.js index b49d7bb77..99e320788 100644 --- a/deps/npm/lib/utils/completion/installed-deep.js +++ b/deps/npm/lib/utils/completion/installed-deep.js @@ -6,12 +6,16 @@ var npm = require("../../npm.js") function installedDeep (opts, cb) { var local , global + , depth = npm.config.get("depth") + , opt = { depth: depth } + if (npm.config.get("global")) local = [], next() - else readInstalled(npm.prefix, npm.config.get("depth"), function (er, data) { + else readInstalled(npm.prefix, opt, function (er, data) { local = getNames(data || {}) next() }) - readInstalled(npm.config.get("prefix"), npm.config.get("depth"), function (er, data) { + + readInstalled(npm.config.get("prefix"), opt, function (er, data) { global = getNames(data || {}) next() }) diff --git a/deps/npm/lib/utils/gently-rm.js b/deps/npm/lib/utils/gently-rm.js index f24309a08..241740fed 100644 --- a/deps/npm/lib/utils/gently-rm.js +++ b/deps/npm/lib/utils/gently-rm.js @@ -9,6 +9,22 @@ var rimraf = require("rimraf") , path = require("path") function gentlyRm (p, 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)) + } + if (npm.config.get("force") || !gently) { return rimraf(p, cb) } diff --git a/deps/npm/lib/utils/tar.js b/deps/npm/lib/utils/tar.js index 378415eb1..b73c134e4 100644 --- a/deps/npm/lib/utils/tar.js +++ b/deps/npm/lib/utils/tar.js @@ -6,7 +6,7 @@ var npm = require("../npm.js") , path = require("path") , log = require("npmlog") , uidNumber = require("uid-number") - , rm = require("rimraf") + , rm = require("./gently-rm.js") , readJson = require("read-package-json") , cache = require("../cache.js") , myUid = process.getuid && process.getuid() diff --git a/deps/npm/lib/view.js b/deps/npm/lib/view.js index babd072f7..f7ba5a954 100644 --- a/deps/npm/lib/view.js +++ b/deps/npm/lib/view.js @@ -56,7 +56,7 @@ function view (args, silent, cb) { if (name === ".") return cb(view.usage) // get the data about this package - registry.get(name, 600, function (er, data) { + registry.get(name, function (er, data) { if (er) return cb(er) if (data["dist-tags"].hasOwnProperty(version)) { version = data["dist-tags"][version] |