diff options
-rw-r--r-- | lib/install.js | 61 | ||||
-rw-r--r-- | lib/install/deps.js | 74 | ||||
-rw-r--r-- | lib/uninstall.js | 18 | ||||
-rw-r--r-- | test/tap/no-scan-full-global-dir.js | 77 |
4 files changed, 160 insertions, 70 deletions
diff --git a/lib/install.js b/lib/install.js index cf6916d34..b422764ac 100644 --- a/lib/install.js +++ b/lib/install.js @@ -116,6 +116,7 @@ var readShrinkwrap = require('./install/read-shrinkwrap.js') var recalculateMetadata = require('./install/deps.js').recalculateMetadata var loadDeps = require('./install/deps.js').loadDeps var loadDevDeps = require('./install/deps.js').loadDevDeps +var getAllMetadata = require('./install/deps.js').getAllMetadata var loadRequestedDeps = require('./install/deps.js').loadRequestedDeps var loadExtraneous = require('./install/deps.js').loadExtraneous var pruneTree = require('./install/prune-tree.js') @@ -284,6 +285,14 @@ Installer.prototype.run = function (cb) { }) } +Installer.prototype.loadArgMetadata = function (next) { + var self = this + getAllMetadata(this.args, this.currentTree, iferr(next, function (args) { + self.args = args + next() + })) +} + Installer.prototype.newTracker = function (tracker, name, size) { validate('OS', [tracker, name]) if (size) validate('N', [size]) @@ -305,10 +314,15 @@ Installer.prototype.finishTracker = function (name, cb) { Installer.prototype.loadCurrentTree = function (cb) { validate('F', arguments) log.silly('install', 'loadCurrentTree') - chain([ - [this, this.readLocalPackageData], - [this, this.normalizeTree, log.newGroup('normalizeTree')] - ], cb) + var todo = [] + if (this.global) { + todo.push([this, this.readGlobalPackageData]) + } else { + todo.push([this, this.readLocalPackageData]) + } + todo.push( + [this, this.normalizeTree, log.newGroup('normalizeTree')]) + chain(todo, cb) } Installer.prototype.loadIdealTree = function (cb) { @@ -345,9 +359,6 @@ Installer.prototype.loadAllDepsIntoIdealTree = function (cb) { if (installNewModules) { steps.push([loadRequestedDeps, this.args, this.idealTree, saveDeps, cg.newGroup('loadRequestedDeps')]) - if (this.global) { - steps.push([this, this.filterGlobalTrees]) - } } else { steps.push( [loadDeps, this.idealTree, cg.newGroup('loadDeps')]) @@ -361,20 +372,6 @@ Installer.prototype.loadAllDepsIntoIdealTree = function (cb) { chain(steps, cb) } -Installer.prototype.filterGlobalTrees = function (cb) { - validate('F', arguments) - log.silly('install', 'filterGlobalTrees') - var modules = {} - this.idealTree.children = this.idealTree.children.filter(function (child) { - if (child.isGlobal) { modules[child.package.name] = true } - return child.isGlobal - }) - this.currentTree.children = this.currentTree.children.filter(function (child) { - return modules[child.package.name] - }) - cb() -} - Installer.prototype.generateActionsToTake = function (cb) { validate('F', arguments) log.silly('install', 'generateActionsToTake') @@ -541,6 +538,26 @@ Installer.prototype.saveToDependencies = function (cb) { saveRequested(this.args, this.idealTree, cb) } +Installer.prototype.readGlobalPackageData = function (cb) { + validate('F', arguments) + log.silly('install', 'readGlobalPackageData') + var self = this + this.currentTree = new readPackageTree.Node(null, this.where, this.where, null, {}) + this.loadArgMetadata(iferr(cb, function () { + mkdirp(self.where, iferr(cb, function () { + asyncMap(self.args, function (pkg, done) { + readPackageTree(path.resolve(self.where, 'node_modules', pkg.name), function (err, subTree) { + if (subTree) { + subTree.parent = self.currentTree + self.currentTree.children.push(subTree) + } + done() + }) + }, cb) + })) + })) +} + Installer.prototype.readLocalPackageData = function (cb) { validate('F', arguments) log.silly('install', 'readLocalPackageData') @@ -565,7 +582,7 @@ Installer.prototype.readLocalPackageData = function (cb) { } catch (ex) { return cb(ex) } - return cb() + return this.loadArgMetadata(cb) }) })) })) diff --git a/lib/install/deps.js b/lib/install/deps.js index b4335f086..a95558267 100644 --- a/lib/install/deps.js +++ b/lib/install/deps.js @@ -114,7 +114,7 @@ function addRequiredDep (tree, child) { } function matchingDep (tree, name) { - if (tree.package.dependencies[name]) return tree.package.dependencies[name] + if (tree.package.dependencies && tree.package.dependencies[name]) return tree.package.dependencies[name] if (tree.package.devDependencies && tree.package.devDependencies[name]) return tree.package.devDependencies[name] return } @@ -129,11 +129,8 @@ function getShrinkwrap (tree, name) { return tree.package._shrinkwrap && tree.package._shrinkwrap.dependencies && tree.package._shrinkwrap.dependencies[name] } -// Add a list of args to tree's top level dependencies -exports.loadRequestedDeps = function (args, tree, saveToDependencies, log, next) { - validate('AOOF', [args, tree, log, next]) - asyncMap(args, function (spec, done) { - var depLoaded = andAddParentToErrors(tree, done) +exports.getAllMetadata = function (args, tree, next) { + asyncMap( args, function (spec, done) { if (spec.lastIndexOf('@') <= 0) { var sw = getShrinkwrap(tree, spec) if (sw) { @@ -151,33 +148,40 @@ exports.loadRequestedDeps = function (args, tree, saveToDependencies, log, next) } } } - fetchPackageMetadata(spec, packageRelativePath(tree), log.newGroup('fetchMetadata'), iferr(depLoaded, function (pkg) { - tree.children = tree.children.filter(function (child) { - return child.package.name !== pkg.name - }) - resolveWithNewModule(pkg, tree, log.newGroup('loadRequestedDeps'), iferr(depLoaded, function (child, tracker) { - validate('OO', arguments) - if (npm.config.get('global')) { - child.isGlobal = true - } - if (saveToDependencies) { - tree.package[saveToDependencies][child.package.name] = child.package._requested.spec - } - if (saveToDependencies && saveToDependencies !== 'devDependencies') { - tree.package.dependencies[child.package.name] = child.package._requested.spec - } + fetchPackageMetadata(spec, packageRelativePath(tree), done) + }, next) +} + +// Add a list of args to tree's top level dependencies +exports.loadRequestedDeps = function (args, tree, saveToDependencies, log, next) { + validate('AOOF', [args, tree, log, next]) + asyncMap(args, function (pkg, done) { + var depLoaded = andAddParentToErrors(tree, done) + tree.children = tree.children.filter(function (child) { + return child.package.name !== pkg.name + }) + resolveWithNewModule(pkg, tree, log.newGroup('loadRequestedDeps'), iferr(depLoaded, function (child, tracker) { + validate('OO', arguments) + if (npm.config.get('global')) { + child.isGlobal = true + } + if (saveToDependencies) { + tree.package[saveToDependencies][child.package.name] = child.package._requested.spec + } + if (saveToDependencies && saveToDependencies !== 'devDependencies') { + tree.package.dependencies[child.package.name] = child.package._requested.spec + } + child.directlyRequested = true + child.save = saveToDependencies + + // For things the user asked to install, that aren't a dependency (or + // won't be when we're done), flag it as "depending" on the user + // themselves, so we don't remove it as a dep that no longer exists + if (!addRequiredDep(tree, child)) { + child.package._requiredBy = union(child.package._requiredBy, ['#USER']) child.directlyRequested = true - child.save = saveToDependencies - - // For things the user asked to install, that aren't a dependency (or - // won't be when we're done), flag it as "depending" on the user - // themselves, so we don't remove it as a dep that no longer exists - if (!addRequiredDep(tree, child)) { - child.package._requiredBy = union(child.package._requiredBy, ['#USER']) - child.directlyRequested = true - } - depLoaded(null, child, tracker) - })) + } + depLoaded(null, child, tracker) })) }, andForEachChild(loadDeps, andFinishTracker(log, next))) } @@ -186,15 +190,15 @@ exports.loadRequestedDeps = function (args, tree, saveToDependencies, log, next) // gives this a consistent interface with loadDeps et al exports.removeDeps = function (args, tree, saveToDependencies, log, next) { validate('AOOF', [args, tree, log, next]) - args.forEach(function (name) { + args.forEach(function (pkg) { if (saveToDependencies) { - var toRemove = tree.children.filter(function (child) { return child.package.name === name }) + var toRemove = tree.children.filter(function (child) { return child.package.name === pkg.name }) tree.removed = union(tree.removed || [], toRemove) toRemove.forEach(function (parent) { parent.save = saveToDependencies }) } - tree.children = tree.children.filter(function (child) { return child.package.name !== name }) + tree.children = tree.children.filter(function (child) { return child.package.name !== pkg.name }) }) log.finish() next() diff --git a/lib/uninstall.js b/lib/uninstall.js index abc55fe66..03a0a5630 100644 --- a/lib/uninstall.js +++ b/lib/uninstall.js @@ -53,6 +53,11 @@ function Uninstaller (where, dryrun, args) { } util.inherits(Uninstaller, Installer) +Uninstaller.prototype.loadArgMetadata = function (next) { + this.args = this.args.map(function (arg) { return {name: arg} }) + next() +} + Uninstaller.prototype.loadAllDepsIntoIdealTree = function (cb) { validate('F', arguments) log.silly('uninstall', 'loadAllDepsIntoIdealtree') @@ -66,16 +71,3 @@ Uninstaller.prototype.loadAllDepsIntoIdealTree = function (cb) { [loadExtraneous, this.idealTree, cg.newGroup('loadExtraneous')]) chain(steps, cb) } - -Uninstaller.prototype.normalizeTree = function (log, cb) { - validate('OF', arguments) - log.silly('uninstall', 'normalizeTree') - // If we're looking globally only look at the one package we're operating on - if (npm.config.get('global')) { - var args = this.args - this.currentTree.children = this.currentTree.children.filter(function (child) { - return args.filter(function (arg) { return arg === child.package.name }).length - }) - } - Installer.prototype.normalizeTree.call(this, log, cb) -} diff --git a/test/tap/no-scan-full-global-dir.js b/test/tap/no-scan-full-global-dir.js new file mode 100644 index 000000000..b03f4fa59 --- /dev/null +++ b/test/tap/no-scan-full-global-dir.js @@ -0,0 +1,77 @@ +'use strict' +var test = require('tap').test +var requireInject = require('require-inject') +var path = require('path') +var log = require('npmlog') +var inherits = require('inherits') + +var packages = { + abc: {package: {name: 'abc'}, path: path.join(__dirname, 'node_modules', 'abc')}, + def: {package: {name: 'def'}, path: path.join(__dirname, 'node_modules', 'def')}, + ghi: {package: {name: 'ghi'}, path: path.join(__dirname, 'node_modules', 'ghi')}, + jkl: {package: {name: 'jkl'}, path: path.join(__dirname, 'node_modules', 'jkl')} +} +var dir = {} +dir[__dirname] ={ children: [ packages.abc, packages.def, packages.ghi, packages.jkl ] } +dir[packages.abc.path] = packages.abc +dir[packages.def.path] = packages.def +dir[packages.ghi.path] = packages.ghi +dir[packages.jkl.path] = packages.jkl + +var rpt = function (root, cb) { + cb(null, dir[root]) +} +rpt.Node = function () { + this.children = [] +} + +var npm = requireInject.installGlobally('../../lib/npm.js', { + 'read-package-tree': rpt +}) + +test('setup', function (t) { + npm.load(function () { + t.pass('npm loaded') + t.end() + }) +}) + +function loadArgMetadata (cb) { + this.args = this.args.map(function (arg) { return {name: arg} }) + cb() +} + +test('installer', function (t) { + t.plan(1) + var Installer = require('../../lib/install.js').Installer + var TestInstaller = function () { + Installer.apply(this, arguments) + this.global = true + } + inherits(TestInstaller, Installer) + TestInstaller.prototype.loadArgMetadata = loadArgMetadata + + var inst = new TestInstaller(__dirname, false, ['def', 'abc']) + inst.loadCurrentTree(function () { + var kids = inst.currentTree.children.map(function (child) { return child.package.name }) + t.isDeeply(kids, ['def', 'abc']) + t.end() + }) +}) + +test('uninstaller', function (t) { + t.plan(1) + var Uninstaller = require('../../lib/uninstall.js').Uninstaller + var TestUninstaller = function () { + Uninstaller.apply(this, arguments) + this.global = true + } + inherits(TestUninstaller, Uninstaller) + + var uninst = new TestUninstaller(__dirname, false, ['ghi', 'jkl']) + uninst.loadCurrentTree(function () { + var kids = uninst.currentTree.children.map(function (child) { return child.package.name }) + t.isDeeply(kids, ['ghi', 'jkl']) + t.end() + }) +}) |