Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorisaacs <i@izs.me>2011-04-19 04:25:27 +0400
committerisaacs <i@izs.me>2011-04-19 04:49:09 +0400
commit23fab365362e51a328f7d20c8d39766ee7906fad (patch)
tree9b7b07b42c50a16d060af1393d53d54a5d7f3b1e /lib
parentc97d874289abc3d013f3a9c566fc11ce765fbd89 (diff)
#817 Update adds missing deps, and downgrades if necessary
Diffstat (limited to 'lib')
-rw-r--r--lib/outdated.js228
-rw-r--r--lib/update.js9
2 files changed, 106 insertions, 131 deletions
diff --git a/lib/outdated.js b/lib/outdated.js
index 2f3293bb1..9e1e2717a 100644
--- a/lib/outdated.js
+++ b/lib/outdated.js
@@ -18,8 +18,7 @@ outdated.usage = "npm outdated [<pkg> [<pkg> ...]]"
outdated.completion = require("./utils/completion/installed-deep")
-var readInstalled = require("./utils/read-installed")
- , path = require("path")
+var path = require("path")
, fs = require("./utils/graceful-fs")
, readJson = require("./utils/read-json")
, cache = require("./cache")
@@ -27,151 +26,122 @@ var readInstalled = require("./utils/read-installed")
, npm = require("../npm")
, log = require("./utils/log")
, semver = require("semver")
+ , relativize = require("./utils/relativize")
-// outdated(pref)
-// deps = pref/package.json dependencies, or {<pref/node_modules/*>:"*"}
-// asyncMap over deps
-// if exists and (up to date
-// or (not in args and args is not empty))
-// return outdated(prefix/node_modules/d)
-// else if (in args or args is empty)
-// return [prefix, d]
-
-
-// for each thing in prefix/node_modules/*
-// if there's a newer one, report it
-// otherwise, check its children
-var output
function outdated (args, silent, cb) {
if (typeof cb !== "function") cb = silent, silent = false
- var pref = npm.prefix
- if (npm.config.get("global")) pref = path.resolve(pref, "lib")
- outdated_(pref, args, function (er, list) {
- if (er) return cb(er)
- if (list.length && !silent) {
- var outList = list.map(function (ww) {
- return ww[1] + ": "+ww[3] + (ww[2] ? " (currently: "+ww[2]+")":"")
- })
- output = output || require("./utils/output")
- output.write(outList.join("\n"), function (e) {
- cb(e, list)
- })
- } else cb(null, list)
+ var dir = npm.prefix
+ if (npm.config.get("global")) dir = path.resolve(dir, "lib")
+ outdated_(args, dir, {}, function (er, list) {
+ function cb_ (er) { cb(er, list) }
+
+ if (er || silent) return cb_(er)
+ var outList = list.map(makePretty)
+ require("./utils/output").write(outList.join("\n"), cb_)
})
}
-function outdated_ (prefix, args, cb) {
- log(prefix, "outdated_ about to getDeps")
- getDeps(prefix, function (er, deps) {
- log([prefix, er, deps], "back from getDeps")
- if (er) return cb(er)
- // now deps is a "dependencies" object, {<name>:<req version>}
- asyncMap(Object.keys(deps), function (dep, cb) {
- var req = deps[dep]
- log([prefix, dep, req], "outdated_")
- validateDep(prefix, args, dep, req, function (er, exists, needsUpdate) {
- if (er) return cb(er)
- log([prefix, dep, req, exists, needsUpdate], "outdated_")
- var dir = path.resolve(prefix, "node_modules", dep)
- if (needsUpdate) return cb(null, [[ prefix
- , dep
- , exists
- , dir ]])
- else if (!exists) return cb(null, [])
- else outdated_(path.resolve(prefix, "node_modules", dep), args, cb)
- })
- }, cb)
- })
-}
-
-// return cb with (er, currentVersion or false, needsUpdate boolean)
-function validateDep (prefix, args, dep, req, cb) {
- var canUpdate = args.length === 0 ? true : args.indexOf(dep) !== -1
- , current = -1
- , latest
- , needsUpdate = false
-
- readJson(path.resolve(prefix, "node_modules", dep,"package.json")
- ,function (er, data) {
- if (er) current = false
- else current = data.version
- log("back from readJson", "validateDep "+dep)
- next()
- })
+// [[ dir, dep, has, want ]]
+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]
+ if (parseable) {
+ var str = dir
+ if (npm.config.get("long")) {
+ str += ":" + dep + "@" + want
+ + ":" + (has ? (dep + "@" + has) : "MISSING")
+ }
+ return str
+ }
- // only check for newer version if we can update this thing.
- if (canUpdate) {
- log([dep, req], "about to check")
- cache.add(dep, req, function (er, data) {
- if (er) {
- // ignore 404 errors, since it's probably just that they installed
- // something locally. other errors indicate something is wrong.
- if (er.errno !== npm.E404) return next(er)
- canUpdate = false
- return next()
- }
- latest = data.version
- log([dep, req, latest, current], "dep, req, latest, current")
- next()
- })
- } else next()
-
- var errState
- function next (er) {
- log([dep, req, current, latest, canUpdate, er], "validateDep next")
- if (errState) return log("error state")
- if (er) return cb(errState = er)
- if (canUpdate && !latest) return log("waiting for latest")
- if (current === -1) return log("waiting for current")
- // now we know the current version (or false if it's not there)
- // and have the version that it ought to be.
- var needsUpdate = canUpdate && semver.gt(latest, current)
- cb(null, current, needsUpdate)
+ if (!npm.config.get("global")) {
+ dir = relativize(dir, process.cwd()+"/x")
}
+ return dep + "@" + want + " " + dir
+ + " current=" + (has || "MISSING")
}
-// deps is the package.json dependencies,
-// plus any node_modules/* that aren't in the dependencies.
-function getDeps (prefix, cb) {
- var jsonDeps
- , folderDeps
-
- readJson(path.resolve(prefix, "package.json"), function (er, data) {
- if (er) jsonDeps = {}
- else jsonDeps = data.dependencies || {}
- next()
+function outdated_ (args, dir, parentHas, cb) {
+ // get the deps from package.json, or {<dir/node_modules/*>:"*"}
+ // asyncMap over deps:
+ // shouldHave = cache.add(dep, req).version
+ // if has === shouldHave then
+ // return outdated(args, dir/node_modules/dep, parentHas + has)
+ // else if dep in args or args is empty
+ // return [dir, dep, has, shouldHave]
+
+ var deps = null
+ readJson(path.resolve(dir, "package.json"), function (er, d) {
+ deps = (er) ? true : d.dependencies
+ return next()
})
- var dir = path.resolve(prefix, "node_modules")
- fs.readdir(dir, function (er, list) {
- if (er) list = []
- log(list, "readdir")
- list = list.filter(function (l) {
- return l.charAt(0) !== "."
- })
- asyncMap(list, function (l, cb) {
- fs.lstat(path.resolve(dir, l), function (er, st) {
- if (er) return cb(null, [])
- if (!st.isDirectory()) return cb(null, [])
- return cb(null, l)
+ var has = null
+ fs.readdir(path.resolve(dir, "node_modules"), function (er, pkgs) {
+ if (er) {
+ has = Object.create(parentHas)
+ return next()
+ }
+ asyncMap(pkgs, function (pkg, cb) {
+ readJson( path.resolve(dir, "node_modules", pkg, "package.json")
+ , function (er, d) {
+ cb(null, er ? [] : [[d.name, d.version]])
})
- }, function (er, list) {
- log(list, "asyncMapped over dir")
+ }, function (er, pvs) {
if (er) return cb(er)
- folderDeps = list.reduce(function (l, r) {
- l[r] = "*"
- return l
- }, {}) || {}
+ has = Object.create(parentHas)
+ pvs.forEach(function (pv) {
+ has[pv[0]] = pv[1]
+ })
next()
})
})
function next () {
- log([jsonDeps, folderDeps], "getDeps next")
- if (!jsonDeps || !folderDeps) return
- Object.keys(jsonDeps).forEach(function (d) {
- folderDeps[d] = jsonDeps[d]
- })
- return cb(null, folderDeps)
+ if (!has || !deps) return
+ if (deps === true) {
+ deps = Object.keys(has).reduce(function (l, r) {
+ l[r] = "*"
+ return l
+ }, {})
+ }
+ // now get what we should have, based on the dep.
+ // if has[dep] !== shouldHave[dep], then cb with the data
+ // otherwise dive into the folder
+ asyncMap(Object.keys(deps), function (dep, cb) {
+ shouldUpdate(args, dir, dep, has, deps[dep], cb)
+ }, cb)
}
}
+
+function shouldUpdate (args, dir, dep, has, req, cb) {
+ // look up the most recent version.
+ // if that's what we already have, or if it's not on the args list,
+ // then dive into it. Otherwise, cb() with the data.
+
+ function skip () {
+ outdated_( args
+ , path.resolve(dir, "node_modules", dep)
+ , has
+ , cb )
+ }
+
+ function doIt (shouldHave) {
+ cb(null, [[ dir, dep, has[dep], shouldHave ]])
+ }
+
+ if (args.length && args.indexOf(dep) === -1) {
+ return skip()
+ }
+
+ // so, we can conceivably update this. find out if we need to.
+ cache.add(dep, req, function (er, d) {
+ // if this fails, then it means we can't update this thing.
+ // it's probably a thing that isn't published.
+ return (er || d.version === has[dep]) ? skip() : doIt(d.version)
+ })
+}
diff --git a/lib/update.js b/lib/update.js
index fd9e963f4..6416435e4 100644
--- a/lib/update.js
+++ b/lib/update.js
@@ -20,10 +20,15 @@ function update (args, cb) {
npm.commands.outdated(args, true, function (er, outdated) {
log(outdated, "outdated updating")
if (er) return cb(er)
+
asyncMap(outdated, function (ww, cb) {
+ // [[ dir, dep, has, want ]]
var where = ww[0]
- , what = ww[1]
- log([where, what], "updating")
+ , dep = ww[1]
+ , want = ww[3]
+ , what = dep + "@" + want
+
+ log.warn([where, what], "updating")
npm.commands.install(where, what, cb)
}, cb)
})