diff options
Diffstat (limited to 'node_modules/read-package-tree/rpt.js')
-rw-r--r-- | node_modules/read-package-tree/rpt.js | 158 |
1 files changed, 100 insertions, 58 deletions
diff --git a/node_modules/read-package-tree/rpt.js b/node_modules/read-package-tree/rpt.js index acd91bd8c..522989763 100644 --- a/node_modules/read-package-tree/rpt.js +++ b/node_modules/read-package-tree/rpt.js @@ -6,6 +6,23 @@ var once = require('once') var readdir = require('readdir-scoped-modules') var debug = require('debuglog')('rpt') +function asyncForEach (items, todo, done) { + var remaining = items.length + if (remaining === 0) return done() + var seenErr + items.forEach(function (item) { + todo(item, handleComplete) + }) + function handleComplete (err) { + if (seenErr) return + if (err) { + seenErr = true + return done(err) + } + if (--remaining === 0) done() + } +} + function dpath (p) { if (!p) return '' if (p.indexOf(process.cwd()) === 0) { @@ -77,30 +94,47 @@ Link.prototype.realpath = '' function loadNode (logical, physical, cache, cb) { debug('loadNode', dpath(logical)) - fs.realpath(physical, function (er, real) { + return fs.realpath(physical, thenReadPackageJson) + + var realpath + function thenReadPackageJson (er, real) { if (er) return cb(er) debug('realpath l=%j p=%j real=%j', dpath(logical), dpath(physical), dpath(real)) - var pj = path.resolve(real, 'package.json') - rpj(pj, function (er, pkg) { - pkg = pkg || null - var node - if (physical === real) { - node = new Node(pkg, logical, physical, er, cache) - } else { - node = new Link(pkg, logical, physical, real, er, cache) - } - - cb(null, node) - }) - }) + var pj = path.join(real, 'package.json') + realpath = real + return rpj(pj, thenCreateNode) + } + function thenCreateNode (er, pkg) { + pkg = pkg || null + var node + if (physical === realpath) { + node = new Node(pkg, logical, physical, er, cache) + } else { + node = new Link(pkg, logical, physical, realpath, er, cache) + } + + cb(null, node) + } } function loadChildren (node, cache, filterWith, cb) { debug('loadChildren', dpath(node.path)) - // don't let it be called more than once + // needed 'cause we process all kids async-like and errors + // short circuit, so we have to be sure that after an error + // the cbs from other kids don't result in calling cb a second + // (or more) time. cb = once(cb) - var nm = path.resolve(node.path, 'node_modules') - readdir(nm, function (er, kids) { + var nm = path.join(node.path, 'node_modules') + var rm + return fs.realpath(path.join(node.path, 'node_modules'), thenReaddir) + + function thenReaddir (er, real_nm) { + if (er) return cb(null, node) + rm = real_nm + readdir(nm, thenLoadKids) + } + + function thenLoadKids (er, kids) { // If there are no children, that's fine, just return if (er) return cb(null, node) @@ -108,26 +142,25 @@ function loadChildren (node, cache, filterWith, cb) { return kid[0] !== '.' && (!filterWith || filterWith(node, kid)) }) - var l = kids . length - if (l === 0) return cb(null, node) - - kids.forEach(function (kid) { - var kidPath = path.resolve(nm, kid) - var kidRealPath = path.resolve(node.realpath,'node_modules',kid) - loadNode(kidPath, kidRealPath, cache, then) - }) - - function then (er, kid) { - if (er) return cb(er) - + asyncForEach(kids, thenLoadNode, thenSortChildren) + } + function thenLoadNode (kid, done) { + var kidPath = path.join(nm, kid) + var kidRealPath = path.join(rm, kid) + loadNode(kidPath, kidRealPath, cache, andAddNode(done)) + } + function andAddNode (done) { + return function (er, kid) { + if (er) return done(er) node.children.push(kid) kid.parent = node - if (--l === 0) { - sortChildren(node) - return cb(null, node) - } + done() } - }) + } + function thenSortChildren (er) { + sortChildren(node) + cb(er, node) + } } function sortChildren (node) { @@ -147,27 +180,25 @@ function loadTree (node, did, cache, filterWith, cb) { did[node.realpath] = true + // needed 'cause we process all kids async-like and errors + // short circuit, so we have to be sure that after an error + // the cbs from other kids don't result in calling cb a second + // (or more) time. cb = once(cb) - loadChildren(node, cache, filterWith, function (er, node) { + return loadChildren(node, cache, filterWith, thenProcessChildren) + + function thenProcessChildren (er, node) { if (er) return cb(er) var kids = node.children.filter(function (kid) { return !did[kid.realpath] }) - var l = kids.length - if (l === 0) return cb(null, node) - - kids.forEach(function (kid, index) { - loadTree(kid, did, cache, filterWith, then) - }) - - function then (er, kid) { - if (er) return cb(er) - - if (--l === 0) cb(null, node) - } - }) + return asyncForEach(kids, loadTreeForKid, cb) + } + function loadTreeForKid (kid, done) { + loadTree(kid, did, cache, filterWith, done) + } } function rpt (root, filterWith, cb) { @@ -175,16 +206,27 @@ function rpt (root, filterWith, cb) { cb = filterWith filterWith = null } - fs.realpath(root, function (er, realRoot) { + var cache = Object.create(null) + var topErr + var tree + return fs.realpath(root, thenLoadNode) + + function thenLoadNode (er, realRoot) { if (er) return cb(er) debug('rpt', dpath(realRoot)) - var cache = Object.create(null) - loadNode(root, realRoot, cache, function (er, node) { - // if there's an error, it's fine, as long as we got a node - if (!node) return cb(er) - loadTree(node, {}, cache, filterWith, function (lter, tree) { - cb(er && er.code !== 'ENOENT' ? er : lter, tree) - }) - }) - }) + loadNode(root, realRoot, cache, thenLoadTree) + } + function thenLoadTree(er, node) { + // even if there's an error, it's fine, as long as we got a node + if (node) { + topErr = er + tree = node + loadTree(node, {}, cache, filterWith, thenHandleErrors) + } else { + cb(er) + } + } + function thenHandleErrors (er) { + cb(topErr && topErr.code !== 'ENOENT' ? topErr : er, tree) + } } |