1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
/*
npm outdated [pkg]
Does the following:
1. check for a new version of pkg
If no packages are specified, then run for all installed
packages.
*/
module.exports = outdated
outdated.usage = "npm outdated [<pkg> [<pkg> ...]]"
outdated.completion = require("./utils/completion/installed-deep.js")
var path = require("path")
, fs = require("graceful-fs")
, readJson = require("./utils/read-json.js")
, cache = require("./cache.js")
, asyncMap = require("slide").asyncMap
, npm = require("./npm.js")
, semver = require("semver")
, relativize = require("./utils/relativize.js")
function outdated (args, silent, cb) {
if (typeof cb !== "function") cb = silent, silent = false
var dir = path.resolve(npm.dir, "..")
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.js").write(outList.join("\n"), cb_)
})
}
// [[ 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]
// 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 = relativize(dir, process.cwd()+"/x")
}
return dep + "@" + want + " " + dir
+ " current=" + (has || "MISSING")
}
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 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, pvs) {
if (er) return cb(er)
has = Object.create(parentHas)
pvs.forEach(function (pv) {
has[pv[0]] = pv[1]
})
next()
})
})
function next () {
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)
})
}
|