aboutsummaryrefslogtreecommitdiff
path: root/deps/npm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/lib')
-rw-r--r--deps/npm/lib/config/cmd-list.js1
-rw-r--r--deps/npm/lib/config/defaults.js5
-rw-r--r--deps/npm/lib/config/pacote.js127
-rw-r--r--deps/npm/lib/fetch-package-metadata.js9
-rw-r--r--deps/npm/lib/install.js85
-rw-r--r--deps/npm/lib/install/action/extract.js11
-rw-r--r--deps/npm/lib/install/action/finalize.js5
-rw-r--r--deps/npm/lib/install/action/preinstall.js3
-rw-r--r--deps/npm/lib/install/action/refresh-package-json.js8
-rw-r--r--deps/npm/lib/install/deps.js91
-rw-r--r--deps/npm/lib/install/inflate-shrinkwrap.js37
-rw-r--r--deps/npm/lib/install/is-extraneous.js10
-rw-r--r--deps/npm/lib/install/mutate-into-logical-tree.js3
-rw-r--r--deps/npm/lib/install/read-shrinkwrap.js17
-rw-r--r--deps/npm/lib/install/save.js37
-rw-r--r--deps/npm/lib/pack.js118
-rw-r--r--deps/npm/lib/prune.js3
-rw-r--r--deps/npm/lib/publish.js12
-rw-r--r--deps/npm/lib/shrinkwrap.js36
-rw-r--r--deps/npm/lib/uninstall.js82
-rw-r--r--deps/npm/lib/utils/error-handler.js10
-rw-r--r--deps/npm/lib/utils/link.js2
-rw-r--r--deps/npm/lib/utils/package-integrity.js21
-rw-r--r--deps/npm/lib/utils/tar.js19
24 files changed, 411 insertions, 341 deletions
diff --git a/deps/npm/lib/config/cmd-list.js b/deps/npm/lib/config/cmd-list.js
index a1abe80fb0..c54d105247 100644
--- a/deps/npm/lib/config/cmd-list.js
+++ b/deps/npm/lib/config/cmd-list.js
@@ -37,6 +37,7 @@ var affordances = {
'info': 'view',
'show': 'view',
'find': 'search',
+ 'add': 'install',
'unlink': 'uninstall',
'remove': 'uninstall',
'rm': 'uninstall',
diff --git a/deps/npm/lib/config/defaults.js b/deps/npm/lib/config/defaults.js
index 517d82ae1e..da019ac4d6 100644
--- a/deps/npm/lib/config/defaults.js
+++ b/deps/npm/lib/config/defaults.js
@@ -178,6 +178,7 @@ Object.defineProperty(exports, 'defaults', {get: function () {
'onload-script': false,
only: null,
optional: true,
+ 'package-lock': true,
parseable: false,
'prefer-offline': false,
'prefer-online': false,
@@ -200,6 +201,7 @@ Object.defineProperty(exports, 'defaults', {get: function () {
'save-exact': false,
'save-optional': false,
'save-prefix': '^',
+ 'save-prod': false,
scope: '',
'scripts-prepend-node-path': 'warn-only',
searchopts: '',
@@ -304,6 +306,7 @@ exports.types = {
'onload-script': [null, String],
only: [null, 'dev', 'development', 'prod', 'production'],
optional: Boolean,
+ 'package-lock': Boolean,
parseable: Boolean,
'prefer-offline': Boolean,
'prefer-online': Boolean,
@@ -321,6 +324,7 @@ exports.types = {
'save-exact': Boolean,
'save-optional': Boolean,
'save-prefix': String,
+ 'save-prod': Boolean,
scope: String,
'scripts-prepend-node-path': [false, true, 'auto', 'warn-only'],
searchopts: String,
@@ -404,6 +408,7 @@ exports.shorthands = {
D: ['--save-dev'],
E: ['--save-exact'],
O: ['--save-optional'],
+ P: ['--save-prod'],
y: ['--yes'],
n: ['--no-yes'],
B: ['--save-bundle'],
diff --git a/deps/npm/lib/config/pacote.js b/deps/npm/lib/config/pacote.js
index 13b7b53f52..705544fe3c 100644
--- a/deps/npm/lib/config/pacote.js
+++ b/deps/npm/lib/config/pacote.js
@@ -1,25 +1,24 @@
'use strict'
-const BB = require('bluebird')
+const Buffer = require('safe-buffer').Buffer
-const cp = require('child_process')
const npm = require('../npm')
const log = require('npmlog')
-const packToStream = require('../utils/tar').packToStream
+let pack
const path = require('path')
-const pipe = BB.promisify(require('mississippi').pipe)
-const readJson = BB.promisify(require('read-package-json'))
-const PassThrough = require('stream').PassThrough
let effectiveOwner
module.exports = pacoteOpts
function pacoteOpts (moreOpts) {
+ if (!pack) {
+ pack = require('../pack.js')
+ }
const ownerStats = calculateOwner()
const opts = {
cache: path.join(npm.config.get('cache'), '_cacache'),
defaultTag: npm.config.get('tag'),
- dirPacker: prepareAndPack,
+ dirPacker: pack.packGitDep,
hashAlgorithm: 'sha1',
localAddress: npm.config.get('local-address'),
log: log,
@@ -44,17 +43,34 @@ function pacoteOpts (moreOpts) {
}
if (ownerStats.uid || ownerStats.gid) {
- Object.assign(opts, ownerStats, {
- cacheUid: ownerStats.uid,
- cacheGid: ownerStats.gid
- })
+ Object.assign(opts, ownerStats)
}
npm.config.keys.forEach(function (k) {
- if (k[0] === '/' && k.match(/.*:_authToken$/)) {
+ const authMatch = k[0] === '/' && k.match(
+ /(.*):(_authToken|username|_password|password|email|always-auth)$/
+ )
+ if (authMatch) {
+ const nerfDart = authMatch[1]
+ const key = authMatch[2]
+ const val = npm.config.get(k)
if (!opts.auth) { opts.auth = {} }
- opts.auth[k.replace(/:_authToken$/, '')] = {
- token: npm.config.get(k)
+ if (!opts.auth[nerfDart]) {
+ opts.auth[nerfDart] = {
+ alwaysAuth: !!npm.config.get('always-auth')
+ }
+ }
+ if (key === '_authToken') {
+ opts.auth[nerfDart].token = val
+ } else if (key.match(/password$/i)) {
+ opts.auth[nerfDart].password =
+ // the config file stores password auth already-encoded. pacote expects
+ // the actual username/password pair.
+ Buffer.from(val, 'base64').toString('utf8')
+ } else if (key === 'always-auth') {
+ opts.auth[nerfDart].alwaysAuth = val === 'false' ? false : !!val
+ } else {
+ opts.auth[nerfDart][key] = val
}
}
if (k[0] === '@') {
@@ -90,86 +106,3 @@ function calculateOwner () {
return effectiveOwner
}
-
-const PASSTHROUGH_OPTS = [
- 'always-auth',
- 'auth-type',
- 'ca',
- 'cafile',
- 'cert',
- 'git',
- 'local-address',
- 'maxsockets',
- 'offline',
- 'prefer-offline',
- 'prefer-online',
- 'proxy',
- 'https-proxy',
- 'registry',
- 'send-metrics',
- 'sso-poll-frequency',
- 'sso-type',
- 'strict-ssl'
-]
-
-function prepareAndPack (manifest, dir) {
- const stream = new PassThrough()
- readJson(path.join(dir, 'package.json')).then((pkg) => {
- if (pkg.scripts && pkg.scripts.prepare) {
- log.verbose('prepareGitDep', `${manifest._spec}: installing devDeps and running prepare script.`)
- const cliArgs = PASSTHROUGH_OPTS.reduce((acc, opt) => {
- if (npm.config.get(opt, 'cli') != null) {
- acc.push(`--${opt}=${npm.config.get(opt)}`)
- }
- return acc
- }, [])
- const child = cp.spawn(process.env.NODE || process.execPath, [
- require.main.filename,
- 'install',
- '--ignore-prepublish',
- '--no-progress',
- '--no-save'
- ].concat(cliArgs), {
- cwd: dir,
- env: process.env
- })
- let errData = []
- let errDataLen = 0
- let outData = []
- let outDataLen = 0
- child.stdout.on('data', (data) => {
- outData.push(data)
- outDataLen += data.length
- log.gauge.pulse('preparing git package')
- })
- child.stderr.on('data', (data) => {
- errData.push(data)
- errDataLen += data.length
- log.gauge.pulse('preparing git package')
- })
- return BB.fromNode((cb) => {
- child.on('error', cb)
- child.on('exit', (code, signal) => {
- if (code > 0) {
- const err = new Error(`${signal}: npm exited with code ${code} while attempting to build ${manifest._requested}. Clone the repository manually and run 'npm install' in it for more information.`)
- err.code = code
- err.signal = signal
- cb(err)
- } else {
- cb()
- }
- })
- }).then(() => {
- if (outDataLen > 0) log.silly('prepareGitDep', '1>', Buffer.concat(outData, outDataLen).toString())
- if (errDataLen > 0) log.silly('prepareGitDep', '2>', Buffer.concat(errData, errDataLen).toString())
- }, (err) => {
- if (outDataLen > 0) log.error('prepareGitDep', '1>', Buffer.concat(outData, outDataLen).toString())
- if (errDataLen > 0) log.error('prepareGitDep', '2>', Buffer.concat(errData, errDataLen).toString())
- throw err
- })
- }
- }).then(() => {
- return pipe(packToStream(manifest, dir), stream)
- }).catch((err) => stream.emit('error', err))
- return stream
-}
diff --git a/deps/npm/lib/fetch-package-metadata.js b/deps/npm/lib/fetch-package-metadata.js
index 45d6acbfae..cca6dc64f4 100644
--- a/deps/npm/lib/fetch-package-metadata.js
+++ b/deps/npm/lib/fetch-package-metadata.js
@@ -12,7 +12,7 @@ const npmlog = require('npmlog')
const limit = require('call-limit')
const tempFilename = require('./utils/temp-filename')
const pacote = require('pacote')
-const pacoteOpts = require('./config/pacote')
+let pacoteOpts
const isWindows = require('./utils/is-windows.js')
function andLogAndFinish (spec, tracker, done) {
@@ -52,7 +52,9 @@ function fetchPackageMetadata (spec, where, opts, done) {
err.code = 'EWINDOWSPATH'
return logAndFinish(err)
}
-
+ if (!pacoteOpts) {
+ pacoteOpts = require('./config/pacote')
+ }
pacote.manifest(dep, pacoteOpts({
annotate: true,
fullMetadata: opts.fullMetadata,
@@ -83,6 +85,9 @@ function fetchPackageMetadata (spec, where, opts, done) {
module.exports.addBundled = addBundled
function addBundled (pkg, next) {
validate('OF', arguments)
+ if (!pacoteOpts) {
+ pacoteOpts = require('./config/pacote')
+ }
if (pkg._bundled !== undefined) return next(null, pkg)
if (!pkg.bundleDependencies && pkg._requested.type !== 'directory') return next(null, pkg)
diff --git a/deps/npm/lib/install.js b/deps/npm/lib/install.js
index c567f624f9..5d111b32c8 100644
--- a/deps/npm/lib/install.js
+++ b/deps/npm/lib/install.js
@@ -29,7 +29,7 @@ install.usage = usage(
'\nnpm install <tarball url>' +
'\nnpm install <git:// url>' +
'\nnpm install <github username>/<github project>',
- '[--save|--save-dev|--save-optional] [--save-exact]'
+ '[--save-prod|--save-dev|--save-optional] [--save-exact] [--no-save]'
)
install.completion = function (opts, cb) {
@@ -98,6 +98,7 @@ var path = require('path')
// dependencies
var log = require('npmlog')
var readPackageTree = require('read-package-tree')
+var readPackageJson = require('read-package-json')
var chain = require('slide').chain
var asyncMap = require('slide').asyncMap
var archy = require('archy')
@@ -137,10 +138,11 @@ var doReverseSerialActions = require('./install/actions.js').doReverseSerial
var doParallelActions = require('./install/actions.js').doParallel
var doOneAction = require('./install/actions.js').doOne
var removeObsoleteDep = require('./install/deps.js').removeObsoleteDep
+var removeExtraneous = require('./install/deps.js').removeExtraneous
+var computeVersionSpec = require('./install/deps.js').computeVersionSpec
var packageId = require('./utils/package-id.js')
var moduleName = require('./utils/module-name.js')
var errorMessage = require('./utils/error-message.js')
-var removeDeps = require('./install/deps.js').removeDeps
var isExtraneous = require('./install/is-extraneous.js')
function unlockCB (lockPath, name, cb) {
@@ -202,6 +204,11 @@ function Installer (where, dryrun, args) {
this.where = where
this.dryrun = dryrun
this.args = args
+ // fakechildren are children created from the lockfile and lack relationship data
+ // the only exist when the tree does not match the lockfile
+ // this is fine when doing full tree installs/updates but not ok when modifying only
+ // a few deps via `npm install` or `npm uninstall`.
+ this.fakeChildren = true
this.currentTree = null
this.idealTree = null
this.differences = []
@@ -245,6 +252,11 @@ Installer.prototype.run = function (_cb) {
var installSteps = []
var postInstallSteps = []
+ if (!this.dryrun) {
+ installSteps.push(
+ [this.newTracker(log, 'runTopLevelLifecycles', 2)],
+ [this, this.runPreinstallTopLevelLifecycles])
+ }
installSteps.push(
[this.newTracker(log, 'loadCurrentTree', 4)],
[this, this.loadCurrentTree],
@@ -265,9 +277,6 @@ Installer.prototype.run = function (_cb) {
[this, this.debugActions, 'decomposeActions', 'todo'])
if (!this.dryrun) {
installSteps.push(
- [this.newTracker(log, 'runTopLevelLifecycles', 2)],
- [this, this.runPreinstallTopLevelLifecycles],
-
[this.newTracker(log, 'executeActions', 8)],
[this, this.executeActions],
[this, this.finishTracker, 'executeActions'])
@@ -313,9 +322,9 @@ Installer.prototype.run = function (_cb) {
}
Installer.prototype.loadArgMetadata = function (next) {
- var self = this
- getAllMetadata(this.args, this.currentTree, process.cwd(), iferr(next, function (args) {
- self.args = args
+ getAllMetadata(this.args, this.currentTree, process.cwd(), iferr(next, (args) => {
+ this.args = args
+ if (args.length) this.fakeChildren = false
next()
}))
}
@@ -354,6 +363,14 @@ var flatNameFromTree = require('./install/flatten-tree.js').flatNameFromTree
Installer.prototype.normalizeCurrentTree = function (cb) {
this.currentTree.isTop = true
normalizeTree(this.currentTree)
+ // If the user didn't have a package.json then fill in deps with what was on disk
+ if (this.currentTree.error) {
+ for (let child of this.currentTree.children) {
+ if (!child.fakeChild && isExtraneous(child)) {
+ this.currentTree.package.dependencies[child.package.name] = computeVersionSpec(this.currentTree, child)
+ }
+ }
+ }
return cb()
function normalizeTree (tree) {
@@ -386,9 +403,9 @@ Installer.prototype.loadIdealTree = function (cb) {
Installer.prototype.pruneIdealTree = function (cb) {
var toPrune = this.idealTree.children
- .filter((n) => !n.fromShrinkwrap && isExtraneous(n))
+ .filter((n) => !n.fakeChild && isExtraneous(n))
.map((n) => ({name: moduleName(n)}))
- return removeDeps(toPrune, this.idealTree, null, log.newGroup('pruneDeps'), cb)
+ return removeExtraneous(toPrune, this.idealTree, cb)
}
Installer.prototype.loadAllDepsIntoIdealTree = function (cb) {
@@ -400,14 +417,14 @@ Installer.prototype.loadAllDepsIntoIdealTree = function (cb) {
var installNewModules = !!this.args.length
var steps = []
+ const depsToPreload = Object.assign({},
+ this.dev ? this.idealTree.package.devDependencies : {},
+ this.prod ? this.idealTree.package.dependencies : {}
+ )
if (installNewModules) {
steps.push([validateArgs, this.idealTree, this.args])
steps.push([loadRequestedDeps, this.args, this.idealTree, saveDeps, cg.newGroup('loadRequestedDeps')])
} else {
- const depsToPreload = Object.assign({},
- this.dev ? this.idealTree.package.devDependencies : {},
- this.prod ? this.idealTree.package.dependencies : {}
- )
if (this.prod || this.dev) {
steps.push(
[prefetchDeps, this.idealTree, depsToPreload, cg.newGroup('prefetchDeps')])
@@ -549,13 +566,16 @@ Installer.prototype.runPreinstallTopLevelLifecycles = function (cb) {
if (this.failing) return cb()
if (!this.topLevelLifecycles) return cb()
log.silly('install', 'runPreinstallTopLevelLifecycles')
- var steps = []
- var trackLifecycle = this.progress.runTopLevelLifecycles
- steps.push(
- [doOneAction, 'preinstall', this.idealTree.path, this.idealTree, trackLifecycle.newGroup('preinstall:.')]
- )
- chain(steps, cb)
+ readPackageJson(path.join(this.where, 'package.json'), log, false, (err, data) => {
+ if (err) return cb()
+ this.currentTree = createNode({
+ isTop: true,
+ package: data,
+ path: this.where
+ })
+ doOneAction('preinstall', this.where, this.currentTree, log.newGroup('preinstall:.'), cb)
+ })
}
Installer.prototype.runPostinstallTopLevelLifecycles = function (cb) {
@@ -581,7 +601,7 @@ Installer.prototype.saveToDependencies = function (cb) {
validate('F', arguments)
if (this.failing) return cb()
log.silly('install', 'saveToDependencies')
- saveRequested(this.args, this.idealTree, cb)
+ saveRequested(this.idealTree, cb)
}
Installer.prototype.readGlobalPackageData = function (cb) {
@@ -655,7 +675,7 @@ function isLink (child) {
Installer.prototype.loadShrinkwrap = function (cb) {
validate('F', arguments)
log.silly('install', 'loadShrinkwrap')
- readShrinkwrap.andInflate(this.idealTree, cb)
+ readShrinkwrap.andInflate(this.idealTree, {fakeChildren: this.fakeChildren}, cb)
}
Installer.prototype.getInstalledModules = function () {
@@ -693,21 +713,22 @@ Installer.prototype.printInstalled = function (cb) {
validate('F', arguments)
if (this.failing) return cb()
log.silly('install', 'printInstalled')
+ const diffs = this.differences.concat((this.idealTree.removedChildren || []).map((r) => ['remove', r]))
if (npm.config.get('json')) {
- return this.printInstalledForJSON(cb)
+ return this.printInstalledForJSON(diffs, cb)
} else if (npm.config.get('parseable')) {
- return this.printInstalledForParseable(cb)
+ return this.printInstalledForParseable(diffs, cb)
} else {
- return this.printInstalledForHuman(cb)
+ return this.printInstalledForHuman(diffs, cb)
}
}
-Installer.prototype.printInstalledForHuman = function (cb) {
+Installer.prototype.printInstalledForHuman = function (diffs, cb) {
var removed = 0
var added = 0
var updated = 0
var moved = 0
- this.differences.forEach(function (action) {
+ diffs.forEach(function (action) {
var mutation = action[0]
if (mutation === 'remove') {
++removed
@@ -743,7 +764,7 @@ Installer.prototype.printInstalledForHuman = function (cb) {
}
}
-Installer.prototype.printInstalledForJSON = function (cb) {
+Installer.prototype.printInstalledForJSON = function (diffs, cb) {
var result = {
added: [],
removed: [],
@@ -764,7 +785,7 @@ Installer.prototype.printInstalledForJSON = function (cb) {
}
result.warnings.push(message)
})
- this.differences.forEach(function (action) {
+ diffs.forEach(function (action) {
var mutation = action[0]
var child = action[1]
var record = recordAction(action)
@@ -805,9 +826,9 @@ Installer.prototype.printInstalledForJSON = function (cb) {
}
}
-Installer.prototype.printInstalledForParseable = function (cb) {
+Installer.prototype.printInstalledForParseable = function (diffs, cb) {
var self = this
- this.differences.forEach(function (action) {
+ diffs.forEach(function (action) {
var mutation = action[0]
var child = action[1]
if (mutation === 'move') {
@@ -819,7 +840,7 @@ Installer.prototype.printInstalledForParseable = function (cb) {
mutation + '\t' +
moduleName(child) + '\t' +
(child.package ? child.package.version : '') + '\t' +
- path.relative(self.where, child.path) + '\t' +
+ (child.path ? path.relative(self.where, child.path) : '') + '\t' +
(previousVersion || '') + '\t' +
(previousPath || ''))
})
diff --git a/deps/npm/lib/install/action/extract.js b/deps/npm/lib/install/action/extract.js
index 7839177850..437d7e57f7 100644
--- a/deps/npm/lib/install/action/extract.js
+++ b/deps/npm/lib/install/action/extract.js
@@ -10,22 +10,19 @@ const moduleName = require('../../utils/module-name.js')
const moduleStagingPath = require('../module-staging-path.js')
const move = BB.promisify(require('../../utils/move.js'))
const npa = require('npm-package-arg')
-const npm = require('../../npm.js')
const packageId = require('../../utils/package-id.js')
const pacote = require('pacote')
-const pacoteOpts = require('../../config/pacote')
+let pacoteOpts
const path = require('path')
module.exports = extract
function extract (staging, pkg, log) {
log.silly('extract', packageId(pkg))
- const up = npm.config.get('unsafe-perm')
- const user = up ? null : npm.config.get('user')
- const group = up ? null : npm.config.get('group')
const extractTo = moduleStagingPath(staging, pkg)
+ if (!pacoteOpts) {
+ pacoteOpts = require('../../config/pacote')
+ }
const opts = pacoteOpts({
- uid: user,
- gid: group,
integrity: pkg.package._integrity
})
return pacote.extract(
diff --git a/deps/npm/lib/install/action/finalize.js b/deps/npm/lib/install/action/finalize.js
index 1e86475710..ba38e602f8 100644
--- a/deps/npm/lib/install/action/finalize.js
+++ b/deps/npm/lib/install/action/finalize.js
@@ -23,10 +23,11 @@ module.exports = function (staging, pkg, log) {
const requested = pkg.package._requested || getRequested(pkg)
if (requested.type === 'directory') {
+ const relative = path.relative(path.dirname(pkg.path), pkg.realpath)
return makeParentPath(pkg.path)
- .then(() => symlink(pkg.realpath, pkg.path, 'junction'))
+ .then(() => symlink(relative, pkg.path, 'junction'))
.catch((ex) => {
- return rimraf(pkg.path).then(() => symlink(pkg.realpath, pkg.path, 'junction'))
+ return rimraf(pkg.path).then(() => symlink(relative, pkg.path, 'junction'))
})
} else {
return makeParentPath(pkg.realpath)
diff --git a/deps/npm/lib/install/action/preinstall.js b/deps/npm/lib/install/action/preinstall.js
index a6f85b0a5a..a16082ef73 100644
--- a/deps/npm/lib/install/action/preinstall.js
+++ b/deps/npm/lib/install/action/preinstall.js
@@ -1,9 +1,8 @@
'use strict'
var lifecycle = require('../../utils/lifecycle.js')
var packageId = require('../../utils/package-id.js')
-var moduleStagingPath = require('../module-staging-path.js')
module.exports = function (staging, pkg, log, next) {
log.silly('preinstall', packageId(pkg))
- lifecycle(pkg.package, 'preinstall', moduleStagingPath(staging, pkg), false, false, next)
+ lifecycle(pkg.package, 'preinstall', pkg.path, false, false, next)
}
diff --git a/deps/npm/lib/install/action/refresh-package-json.js b/deps/npm/lib/install/action/refresh-package-json.js
index 337be0caf2..6910803451 100644
--- a/deps/npm/lib/install/action/refresh-package-json.js
+++ b/deps/npm/lib/install/action/refresh-package-json.js
@@ -10,13 +10,13 @@ module.exports = function (staging, pkg, log) {
return readJson(path.join(pkg.path, 'package.json'), false).then((metadata) => {
Object.keys(pkg.package).forEach(function (key) {
- if (key !== '_injectedFromShrinkwrap' && !isEmpty(pkg.package[key])) {
+ if (!isEmpty(pkg.package[key])) {
metadata[key] = pkg.package[key]
- if (key === '_resolved' && metadata[key] == null && pkg.package._injectedFromShrinkwrap) {
- metadata[key] = pkg.package._injectedFromShrinkwrap.resolved
- }
}
})
+ if (metadata._resolved == null && pkg.fakeChild) {
+ metadata._resolved = pkg.fakeChild.resolved
+ }
// These two sneak in and it's awful
delete metadata.readme
delete metadata.readmeFilename
diff --git a/deps/npm/lib/install/deps.js b/deps/npm/lib/install/deps.js
index 3f3433535f..c0fe905d4b 100644
--- a/deps/npm/lib/install/deps.js
+++ b/deps/npm/lib/install/deps.js
@@ -183,7 +183,9 @@ function packageRelativePath (tree) {
if (!tree) return ''
var requested = tree.package._requested || {}
var isLocal = requested.type === 'directory' || requested.type === 'file'
- return isLocal ? requested.fetchSpec : tree.path
+ return isLocal ? requested.fetchSpec
+ : (tree.isLink || tree.isInLink) && !preserveSymlinks() ? tree.realpath
+ : tree.path
}
function matchingDep (tree, name) {
@@ -227,14 +229,24 @@ exports.loadRequestedDeps = function (args, tree, saveToDependencies, log, next)
}
var childName = moduleName(child)
child.saveSpec = computeVersionSpec(tree, child)
- if (saveToDependencies) {
- tree.package[getSaveType(tree, child)][childName] = child.saveSpec
- }
- if (getSaveType(tree, child) === 'optionalDependencies') {
- tree.package.dependencies[childName] = child.saveSpec
- }
child.userRequired = true
- child.save = saveToDependencies
+ child.save = getSaveType(tree, child)
+ const types = ['dependencies', 'devDependencies', 'optionalDependencies']
+ if (child.save) {
+ tree.package[child.save][childName] = child.saveSpec
+ // Astute readers might notice that this exact same code exists in
+ // save.js under a different guise. That code is responsible for deps
+ // being removed from the final written `package.json`. The removal in
+ // this function is specifically to prevent "installed as both X and Y"
+ // warnings when moving an existing dep between different dep fields.
+ //
+ // Or, try it by removing this loop, and do `npm i -P x && npm i -D x`
+ for (let saveType of types) {
+ if (child.save !== saveType) {
+ delete tree.package[saveType][childName]
+ }
+ }
+ }
// 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
@@ -246,9 +258,17 @@ exports.loadRequestedDeps = function (args, tree, saveToDependencies, log, next)
}, andForEachChild(loadDeps, andFinishTracker(log, next)))
}
+module.exports.computeVersionSpec = computeVersionSpec
function computeVersionSpec (tree, child) {
validate('OO', arguments)
- var requested = child.package._requested
+ var requested
+ if (child.package._requested) {
+ requested = child.package._requested
+ } else if (child.package._from) {
+ requested = npa(child.package._from)
+ } else {
+ requested = npa.resolve(child.package.name, child.package.version)
+ }
if (requested.registry) {
var version = child.package.version
var rangeDescriptor = ''
@@ -275,26 +295,38 @@ function noModuleNameMatches (name) {
// while this implementation does not require async calling, doing so
// 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 (pkg) {
+exports.removeDeps = function (args, tree, saveToDependencies, next) {
+ validate('AOSF|AOZF', [args, tree, saveToDependencies, next])
+ for (let pkg of args) {
var pkgName = moduleName(pkg)
var toRemove = tree.children.filter(moduleNameMatches(pkgName))
var pkgToRemove = toRemove[0] || createChild({package: {name: pkgName}})
- if (tree.isTop) {
- if (saveToDependencies) {
- pkgToRemove.save = getSaveType(tree, pkg)
- delete tree.package[pkgToRemove.save][pkgName]
- if (pkgToRemove.save === 'optionalDependencies') {
- delete tree.package.dependencies[pkgName]
- }
- replaceModuleByPath(tree, 'removed', pkgToRemove)
+ var saveType = getSaveType(tree, pkg) || 'dependencies'
+ if (tree.isTop && saveToDependencies) {
+ pkgToRemove.save = saveType
+ }
+ if (tree.package[saveType][pkgName]) {
+ delete tree.package[saveType][pkgName]
+ if (saveType === 'optionalDependencies' && tree.package.dependencies[pkgName]) {
+ delete tree.package.dependencies[pkgName]
}
- pkgToRemove.requiredBy = pkgToRemove.requiredBy.filter((parent) => parent !== tree)
}
- if (pkgToRemove.requiredBy.length === 0) removeObsoleteDep(pkgToRemove)
- })
- log.finish()
+ replaceModuleByPath(tree, 'removedChildren', pkgToRemove)
+ for (let parent of pkgToRemove.requiredBy) {
+ parent.requires = parent.requires.filter((child) => child !== pkgToRemove)
+ }
+ pkgToRemove.requiredBy = pkgToRemove.requiredBy.filter((parent) => parent !== tree)
+ }
+ next()
+}
+exports.removeExtraneous = function (args, tree, next) {
+ for (let pkg of args) {
+ var pkgName = moduleName(pkg)
+ var toRemove = tree.children.filter(moduleNameMatches(pkgName))
+ if (toRemove.length) {
+ removeObsoleteDep(toRemove[0])
+ }
+ }
next()
}
@@ -639,6 +671,13 @@ var findRequirement = exports.findRequirement = function (tree, name, requested,
return findRequirement(tree.parent, name, requested, requestor)
}
+function preserveSymlinks () {
+ if (!('NODE_PRESERVE_SYMLINKS' in process.env)) return false
+ const value = process.env.NODE_PRESERVE_SYMLINKS
+ if (value == null || value === '' || value === 'false' || value === 'no' || value === '0') return false
+ return true
+}
+
// Find the highest level in the tree that we can install this module in.
// If the module isn't installed above us yet, that'd be the very top.
// If it is, then it's the level below where its installed.
@@ -670,7 +709,7 @@ var earliestInstallable = exports.earliestInstallable = function (requiredBy, tr
var devDeps = tree.package.devDependencies || {}
if (tree.isTop && devDeps[pkg.name]) {
- var requested = npa.resolve(pkg.name, devDeps[pkg.name], tree.path)
+ var requested = childDependencySpecifier(tree, pkg.name, devDeps[pkg.name])
if (!doesChildVersionMatch({package: pkg}, requested, tree)) {
return null
}
@@ -684,7 +723,7 @@ var earliestInstallable = exports.earliestInstallable = function (requiredBy, tr
if (npm.config.get('global-style') && tree.parent.isTop) return tree
if (npm.config.get('legacy-bundling')) return tree
- if (!process.env.NODE_PRESERVE_SYMLINKS && /^[.][.][\\/]/.test(path.relative(tree.parent.realpath, tree.realpath))) return tree
+ if (!preserveSymlinks() && /^[.][.][\\/]/.test(path.relative(tree.parent.realpath, tree.realpath))) return tree
return (earliestInstallable(requiredBy, tree.parent, pkg) || tree)
}
diff --git a/deps/npm/lib/install/inflate-shrinkwrap.js b/deps/npm/lib/install/inflate-shrinkwrap.js
index 9878b0f19a..8cb75626bb 100644
--- a/deps/npm/lib/install/inflate-shrinkwrap.js
+++ b/deps/npm/lib/install/inflate-shrinkwrap.js
@@ -2,10 +2,10 @@
const BB = require('bluebird')
-const addBundled = BB.promisify(require('../fetch-package-metadata.js').addBundled)
+let addBundled
const childPath = require('../utils/child-path.js')
const createChild = require('./node.js').create
-const fetchPackageMetadata = BB.promisify(require('../fetch-package-metadata.js'))
+let fetchPackageMetadata
const inflateBundled = require('./inflate-bundled.js')
const moduleName = require('../utils/module-name.js')
const normalizePackageData = require('normalize-package-data')
@@ -14,17 +14,28 @@ const realizeShrinkwrapSpecifier = require('./realize-shrinkwrap-specifier.js')
const validate = require('aproba')
const path = require('path')
-module.exports = function (tree, swdeps, finishInflating) {
- if (!npm.config.get('shrinkwrap')) return finishInflating()
+module.exports = function (tree, swdeps, opts, finishInflating) {
+ if (!fetchPackageMetadata) {
+ fetchPackageMetadata = BB.promisify(require('../fetch-package-metadata.js'))
+ addBundled = BB.promisify(fetchPackageMetadata.addBundled)
+ }
+ if (!npm.config.get('shrinkwrap') || !npm.config.get('package-lock')) {
+ return finishInflating()
+ }
+ if (arguments.length === 3) {
+ finishInflating = opts
+ opts = {}
+ }
tree.loaded = true
- return inflateShrinkwrap(tree.path, tree, swdeps).then(
+ return inflateShrinkwrap(tree.path, tree, swdeps, opts).then(
() => finishInflating(),
finishInflating
)
}
-function inflateShrinkwrap (topPath, tree, swdeps) {
- validate('SOO', arguments)
+function inflateShrinkwrap (topPath, tree, swdeps, opts) {
+ validate('SOO|SOOO', arguments)
+ if (!opts) opts = {}
const onDisk = {}
tree.children.forEach((child) => {
onDisk[moduleName(child)] = child
@@ -43,7 +54,7 @@ function inflateShrinkwrap (topPath, tree, swdeps) {
const dependencies = sw.dependencies || {}
const requested = realizeShrinkwrapSpecifier(name, sw, topPath)
return inflatableChild(
- onDisk[name], name, topPath, tree, sw, requested
+ onDisk[name], name, topPath, tree, sw, requested, opts
).then((child) => {
return inflateShrinkwrap(topPath, child, dependencies)
})
@@ -58,8 +69,8 @@ function normalizePackageDataNoErrors (pkg) {
}
}
-function inflatableChild (onDiskChild, name, topPath, tree, sw, requested) {
- validate('OSSOOO|ZSSOOO', arguments)
+function inflatableChild (onDiskChild, name, topPath, tree, sw, requested, opts) {
+ validate('OSSOOOO|ZSSOOOO', arguments)
if (onDiskChild && childIsEquivalent(sw, requested, onDiskChild)) {
// The version on disk matches the shrinkwrap entry.
if (!onDiskChild.fromShrinkwrap) onDiskChild.fromShrinkwrap = true
@@ -77,7 +88,7 @@ function inflatableChild (onDiskChild, name, topPath, tree, sw, requested) {
normalizePackageDataNoErrors(onDiskChild.package)
tree.children.push(onDiskChild)
return BB.resolve(onDiskChild)
- } else if (sw.version && sw.integrity) {
+ } else if (opts.fakeChildren !== false && sw.version && sw.integrity) {
// The shrinkwrap entry has an integrity field. We can fake a pkg to get
// the installer to do a content-address fetch from the cache, if possible.
return BB.resolve(makeFakeChild(name, topPath, tree, sw, requested))
@@ -101,8 +112,7 @@ function makeFakeChild (name, topPath, tree, sw, requested) {
_from: from,
_spec: requested.rawSpec,
_where: topPath,
- _args: [[requested.toString(), topPath]],
- _injectedFromShrinkwrap: sw
+ _args: [[requested.toString(), topPath]]
}
let bundleAdded = BB.resolve()
if (Object.keys(sw.dependencies || {}).some((d) => {
@@ -118,6 +128,7 @@ function makeFakeChild (name, topPath, tree, sw, requested) {
parent: tree,
children: pkg._bundled || [],
fromShrinkwrap: true,
+ fakeChild: sw,
fromBundle: sw.bundled ? tree.fromBundle || tree : null,
path: childPath(tree.path, pkg),
realpath: childPath(tree.realpath, pkg),
diff --git a/deps/npm/lib/install/is-extraneous.js b/deps/npm/lib/install/is-extraneous.js
index f0d599965f..a6477c2374 100644
--- a/deps/npm/lib/install/is-extraneous.js
+++ b/deps/npm/lib/install/is-extraneous.js
@@ -6,14 +6,6 @@ function isExtraneous (tree) {
return result
}
-function isNotRequired (tree) {
- return tree.requiredBy && tree.requiredBy.length === 0
-}
-
-function parentHasNoPjson (tree) {
- return tree.parent && tree.parent.isTop && tree.parent.error
-}
-
function topHasNoPjson (tree) {
var top = tree
while (!top.isTop) top = top.parent
@@ -24,8 +16,6 @@ function isNotExtraneous (tree, isCycle) {
if (!isCycle) isCycle = {}
if (tree.isTop || tree.userRequired) {
return true
- } else if (isNotRequired(tree) && parentHasNoPjson(tree)) {
- return true
} else if (isCycle[tree.path]) {
return topHasNoPjson(tree)
} else {
diff --git a/deps/npm/lib/install/mutate-into-logical-tree.js b/deps/npm/lib/install/mutate-into-logical-tree.js
index 491f20913c..018745cc5f 100644
--- a/deps/npm/lib/install/mutate-into-logical-tree.js
+++ b/deps/npm/lib/install/mutate-into-logical-tree.js
@@ -7,6 +7,7 @@ var isExtraneous = require('./is-extraneous.js')
var validateAllPeerDeps = require('./deps.js').validateAllPeerDeps
var packageId = require('../utils/package-id.js')
var moduleName = require('../utils/module-name.js')
+var npm = require('../npm.js')
// Return true if tree is a part of a cycle that:
// A) Never connects to the top of the tree
@@ -128,7 +129,7 @@ function translateTree_ (tree, seen) {
pkg.path = tree.path
pkg.error = tree.error
- pkg.extraneous = isExtraneous(tree)
+ pkg.extraneous = !tree.isTop && (!tree.parent.isTop || !tree.parent.error) && !npm.config.get('global') && isExtraneous(tree)
if (tree.target && tree.parent && !tree.parent.target) pkg.link = tree.realpath
return pkg
}
diff --git a/deps/npm/lib/install/read-shrinkwrap.js b/deps/npm/lib/install/read-shrinkwrap.js
index 913c303482..de398fb40b 100644
--- a/deps/npm/lib/install/read-shrinkwrap.js
+++ b/deps/npm/lib/install/read-shrinkwrap.js
@@ -9,7 +9,6 @@ const log = require('npmlog')
const parseJSON = require('../utils/parse-json.js')
const path = require('path')
const PKGLOCK_VERSION = require('../npm.js').lockfileVersion
-const pkgSri = require('../utils/package-integrity.js')
const readFileAsync = BB.promisify(fs.readFile)
@@ -34,14 +33,6 @@ function readShrinkwrap (child, next) {
throw ex
}
}
- if (
- pkgJson &&
- parsed &&
- parsed.packageIntegrity &&
- !pkgSri.check(JSON.parse(pkgJson), parsed.packageIntegrity)
- ) {
- log.info('read-shrinkwrap', `${name} will be updated because package.json does not match what it was generated against.`)
- }
if (parsed && parsed.lockfileVersion !== PKGLOCK_VERSION) {
log.warn('read-shrinkwrap', `This version of npm is compatible with lockfileVersion@${PKGLOCK_VERSION}, but ${name} was generated for lockfileVersion@${parsed.lockfileVersion || 0}. I'll try to do my best with it!`)
}
@@ -56,10 +47,14 @@ function maybeReadFile (name, child) {
).catch({code: 'ENOENT'}, () => null)
}
-module.exports.andInflate = function (child, next) {
+module.exports.andInflate = function (child, opts, next) {
+ if (arguments.length === 2) {
+ next = opts
+ opts = {}
+ }
readShrinkwrap(child, iferr(next, function () {
if (child.package._shrinkwrap) {
- return inflateShrinkwrap(child, child.package._shrinkwrap.dependencies || {}, next)
+ return inflateShrinkwrap(child, child.package._shrinkwrap.dependencies || {}, opts, next)
} else {
return next()
}
diff --git a/deps/npm/lib/install/save.js b/deps/npm/lib/install/save.js
index 5d5f4e7f7a..56a4a892ad 100644
--- a/deps/npm/lib/install/save.js
+++ b/deps/npm/lib/install/save.js
@@ -19,9 +19,9 @@ const writeFileAtomic = require('write-file-atomic')
// if the -S|--save option is specified, then write installed packages
// as dependencies to a package.json file.
-exports.saveRequested = function (args, tree, andReturn) {
- validate('AOF', arguments)
- savePackageJson(args, tree, andWarnErrors(andSaveShrinkwrap(tree, andReturn)))
+exports.saveRequested = function (tree, andReturn) {
+ validate('OF', arguments)
+ savePackageJson(tree, andWarnErrors(andSaveShrinkwrap(tree, andReturn)))
}
function andSaveShrinkwrap (tree, andReturn) {
@@ -43,13 +43,14 @@ function andWarnErrors (cb) {
function saveShrinkwrap (tree, next) {
validate('OF', arguments)
+ if (!npm.config.get('shrinkwrap') || !npm.config.get('package-lock')) {
+ next()
+ }
createShrinkwrap(tree, {silent: false}, next)
}
-function savePackageJson (args, tree, next) {
- validate('AOF', arguments)
- if (!args || !args.length) { return next() }
-
+function savePackageJson (tree, next) {
+ validate('OF', arguments)
var saveBundle = npm.config.get('save-bundle')
// each item in the tree is a top-level thing that should be saved
@@ -84,8 +85,23 @@ function savePackageJson (args, tree, next) {
})
log.verbose('saving', toSave)
+ const types = ['dependencies', 'devDependencies', 'optionalDependencies']
toSave.forEach(function (pkg) {
tree.package[pkg.save][pkg.name] = pkg.spec
+ const movedFrom = []
+ for (let saveType of types) {
+ if (
+ pkg.save !== saveType &&
+ tree.package[saveType] &&
+ tree.package[saveType][pkg.name]
+ ) {
+ movedFrom.push(saveType)
+ delete tree.package[saveType][pkg.name]
+ }
+ }
+ if (movedFrom.length) {
+ log.notice('save', `${pkg.name} is being moved from ${movedFrom.join(' and ')} to ${pkg.save}`)
+ }
if (saveBundle) {
var ii = bundle.indexOf(pkg.name)
if (ii === -1) bundle.push(pkg.name)
@@ -116,6 +132,7 @@ exports.getSaveType = function (tree, arg) {
var globalInstall = npm.config.get('global')
var noSaveFlags = !npm.config.get('save') &&
!npm.config.get('save-dev') &&
+ !npm.config.get('save-prod') &&
!npm.config.get('save-optional')
if (globalInstall || noSaveFlags) return null
@@ -123,6 +140,8 @@ exports.getSaveType = function (tree, arg) {
return 'optionalDependencies'
} else if (npm.config.get('save-dev')) {
return 'devDependencies'
+ } else if (npm.config.get('save-prod')) {
+ return 'dependencies'
} else {
if (arg) {
var name = moduleName(arg)
@@ -152,8 +171,8 @@ function getThingsToSave (tree) {
function getThingsToRemove (tree) {
validate('O', arguments)
- if (!tree.removed) return []
- var toRemove = tree.removed.map(function (child) {
+ if (!tree.removedChildren) return []
+ var toRemove = tree.removedChildren.map(function (child) {
return {
name: moduleName(child),
save: child.save
diff --git a/deps/npm/lib/pack.js b/deps/npm/lib/pack.js
index 68c6030ee8..075a672d66 100644
--- a/deps/npm/lib/pack.js
+++ b/deps/npm/lib/pack.js
@@ -8,16 +8,19 @@ const BB = require('bluebird')
const cache = require('./cache')
const cacache = require('cacache')
+const cp = require('child_process')
const deprCheck = require('./utils/depr-check')
-const fpm = BB.promisify(require('./fetch-package-metadata'))
+const fpm = require('./fetch-package-metadata')
const fs = require('graceful-fs')
const install = require('./install')
const lifecycle = BB.promisify(require('./utils/lifecycle'))
+const log = require('npmlog')
const move = require('move-concurrently')
const npm = require('./npm')
const output = require('./utils/output')
const pacoteOpts = require('./config/pacote')
const path = require('path')
+const PassThrough = require('stream').PassThrough
const pathIsInside = require('path-is-inside')
const pipe = BB.promisify(require('mississippi').pipe)
const prepublishWarning = require('./utils/warn-deprecated')('prepublish-on-install')
@@ -53,7 +56,7 @@ function pack (args, silent, cb) {
// add to cache, then cp to the cwd
function pack_ (pkg, dir) {
- return fpm(pkg, dir).then((mani) => {
+ return BB.fromNode((cb) => fpm(pkg, dir, cb)).then((mani) => {
let name = mani.name[0] === '@'
// scoped packages get special treatment
? mani.name.substr(1).replace(/\//g, '-')
@@ -108,10 +111,111 @@ function prepareDirectory (dir) {
module.exports.packDirectory = packDirectory
function packDirectory (mani, dir, target) {
deprCheck(mani)
- return cacache.tmp.withTmp(npm.tmp, {tmpPrefix: 'packing'}, (tmp) => {
- const tmpTarget = path.join(tmp, path.basename(target))
- return tarPack(tmpTarget, dir, mani).then(() => {
- return move(tmpTarget, target, {Promise: BB, fs})
- }).then(() => target)
+ return readJson(path.join(dir, 'package.json')).then((pkg) => {
+ return lifecycle(pkg, 'prepack', dir)
+ }).then(() => {
+ return readJson(path.join(dir, 'package.json'))
+ }).then((pkg) => {
+ return cacache.tmp.withTmp(npm.tmp, {tmpPrefix: 'packing'}, (tmp) => {
+ const tmpTarget = path.join(tmp, path.basename(target))
+ return tarPack(tmpTarget, dir, pkg).then(() => {
+ return move(tmpTarget, target, {Promise: BB, fs})
+ }).then(() => {
+ return lifecycle(pkg, 'postpack', dir)
+ }).then(() => target)
+ })
})
}
+
+const PASSTHROUGH_OPTS = [
+ 'always-auth',
+ 'auth-type',
+ 'ca',
+ 'cafile',
+ 'cert',
+ 'git',
+ 'local-address',
+ 'maxsockets',
+ 'offline',
+ 'prefer-offline',
+ 'prefer-online',
+ 'proxy',
+ 'https-proxy',
+ 'registry',
+ 'send-metrics',
+ 'sso-poll-frequency',
+ 'sso-type',
+ 'strict-ssl'
+]
+
+module.exports.packGitDep = packGitDep
+function packGitDep (manifest, dir) {
+ const stream = new PassThrough()
+ readJson(path.join(dir, 'package.json')).then((pkg) => {
+ if (pkg.scripts && pkg.scripts.prepare) {
+ log.verbose('prepareGitDep', `${manifest._spec}: installing devDeps and running prepare script.`)
+ const cliArgs = PASSTHROUGH_OPTS.reduce((acc, opt) => {
+ if (npm.config.get(opt, 'cli') != null) {
+ acc.push(`--${opt}=${npm.config.get(opt)}`)
+ }
+ return acc
+ }, [])
+ const child = cp.spawn(process.env.NODE || process.execPath, [
+ require.main.filename,
+ 'install',
+ '--ignore-prepublish',
+ '--no-progress',
+ '--no-save'
+ ].concat(cliArgs), {
+ cwd: dir,
+ env: process.env
+ })
+ let errData = []
+ let errDataLen = 0
+ let outData = []
+ let outDataLen = 0
+ child.stdout.on('data', (data) => {
+ outData.push(data)
+ outDataLen += data.length
+ log.gauge.pulse('preparing git package')
+ })
+ child.stderr.on('data', (data) => {
+ errData.push(data)
+ errDataLen += data.length
+ log.gauge.pulse('preparing git package')
+ })
+ return BB.fromNode((cb) => {
+ child.on('error', cb)
+ child.on('exit', (code, signal) => {
+ if (code > 0) {
+ const err = new Error(`${signal}: npm exited with code ${code} while attempting to build ${manifest._requested}. Clone the repository manually and run 'npm install' in it for more information.`)
+ err.code = code
+ err.signal = signal
+ cb(err)
+ } else {
+ cb()
+ }
+ })
+ }).then(() => {
+ if (outDataLen > 0) log.silly('prepareGitDep', '1>', Buffer.concat(outData, outDataLen).toString())
+ if (errDataLen > 0) log.silly('prepareGitDep', '2>', Buffer.concat(errData, errDataLen).toString())
+ }, (err) => {
+ if (outDataLen > 0) log.error('prepareGitDep', '1>', Buffer.concat(outData, outDataLen).toString())
+ if (errDataLen > 0) log.error('prepareGitDep', '2>', Buffer.concat(errData, errDataLen).toString())
+ throw err
+ })
+ }
+ }).then(() => {
+ return readJson(path.join(dir, 'package.json'))
+ }).then((pkg) => {
+ return cacache.tmp.withTmp(npm.tmp, {
+ tmpPrefix: 'pacote-packing'
+ }, (tmp) => {
+ const tmpTar = path.join(tmp, 'package.tgz')
+ return packDirectory(manifest, dir, tmpTar).then(() => {
+ return pipe(fs.createReadStream(tmpTar), stream)
+ })
+ })
+ }).catch((err) => stream.emit('error', err))
+ return stream
+}
diff --git a/deps/npm/lib/prune.js b/deps/npm/lib/prune.js
index 39d1c8ffb7..6027745383 100644
--- a/deps/npm/lib/prune.js
+++ b/deps/npm/lib/prune.js
@@ -26,6 +26,7 @@ function prune (args, cb) {
function Pruner (where, dryrun, args) {
Installer.call(this, where, dryrun, args)
+ this.fakeChildren = false
}
util.inherits(Pruner, Installer)
@@ -59,7 +60,7 @@ Pruner.prototype.loadAllDepsIntoIdealTree = function (cb) {
var toPrune = this.idealTree.children.filter(shouldPrune).map(getModuleName).filter(matchesArg).map(nameObj)
steps.push(
- [removeDeps, toPrune, this.idealTree, null, cg.newGroup('removeDeps')],
+ [removeDeps, toPrune, this.idealTree, null],
[loadExtraneous, this.idealTree, cg.newGroup('loadExtraneous')])
chain(steps, cb)
}
diff --git a/deps/npm/lib/publish.js b/deps/npm/lib/publish.js
index 49c98fb8e6..5d99bfd089 100644
--- a/deps/npm/lib/publish.js
+++ b/deps/npm/lib/publish.js
@@ -76,15 +76,23 @@ function publish_ (arg) {
}
function publishFromDirectory (arg) {
- return pack.prepareDirectory(arg).tap((pkg) => {
+ // All this readJson is because any of the given scripts might modify the
+ // package.json in question, so we need to refresh after every step.
+ return pack.prepareDirectory(arg).then(() => {
+ return readJson(path.join(arg, 'package.json'))
+ }).then((pkg) => {
return lifecycle(pkg, 'prepublishOnly', arg)
- }).tap((pkg) => {
+ }).then(() => {
+ return readJson(path.join(arg, 'package.json'))
+ }).then((pkg) => {
return cacache.tmp.withTmp(npm.tmp, {tmpPrefix: 'fromDir'}, (tmpDir) => {
const target = path.join(tmpDir, 'package.tgz')
return pack.packDirectory(pkg, arg, target).then(() => {
return upload(arg, pkg, false, target)
})
})
+ }).then(() => {
+ return readJson(path.join(arg, 'package.json'))
}).tap((pkg) => {
return lifecycle(pkg, 'publish', arg)
}).tap((pkg) => {
diff --git a/deps/npm/lib/shrinkwrap.js b/deps/npm/lib/shrinkwrap.js
index 75fe0dd95d..428c12bba7 100644
--- a/deps/npm/lib/shrinkwrap.js
+++ b/deps/npm/lib/shrinkwrap.js
@@ -9,7 +9,6 @@ const getRequested = require('./install/get-requested.js')
const id = require('./install/deps.js')
const iferr = require('iferr')
const isDevDep = require('./install/is-dev-dep.js')
-const isExtraneous = require('./install/is-extraneous.js')
const isOptDep = require('./install/is-opt-dep.js')
const isProdDep = require('./install/is-prod-dep.js')
const lifecycle = require('./utils/lifecycle.js')
@@ -17,9 +16,7 @@ const log = require('npmlog')
const moduleName = require('./utils/module-name.js')
const move = require('move-concurrently')
const npm = require('./npm.js')
-const packageId = require('./utils/package-id.js')
const path = require('path')
-const pkgSri = require('./utils/package-integrity.js')
const readPackageTree = BB.promisify(require('read-package-tree'))
const ssri = require('ssri')
const validate = require('aproba')
@@ -92,33 +89,21 @@ function treeToShrinkwrap (tree) {
var pkginfo = {}
if (tree.package.name) pkginfo.name = tree.package.name
if (tree.package.version) pkginfo.version = tree.package.version
- var problems = []
if (tree.children.length) {
- shrinkwrapDeps(problems, pkginfo.dependencies = {}, tree, tree)
+ shrinkwrapDeps(pkginfo.dependencies = {}, tree, tree)
}
- if (problems.length) pkginfo.problems = problems
return pkginfo
}
-function shrinkwrapDeps (problems, deps, top, tree, seen) {
- validate('AOOO', [problems, deps, top, tree])
+function shrinkwrapDeps (deps, top, tree, seen) {
+ validate('OOO', [deps, top, tree])
if (!seen) seen = {}
if (seen[tree.path]) return
seen[tree.path] = true
- Object.keys(tree.missingDeps).forEach(function (name) {
- var invalid = tree.children.filter(function (dep) { return moduleName(dep) === name })[0]
- if (invalid) {
- problems.push('invalid: have ' + invalid.package._id + ' (expected: ' + tree.missingDeps[name] + ') ' + invalid.path)
- } else if (!tree.package.optionalDependencies || !tree.package.optionalDependencies[name]) {
- var topname = packageId(tree)
- problems.push('missing: ' + name + '@' + tree.package.dependencies[name] +
- (topname ? ', required by ' + topname : ''))
- }
- })
tree.children.sort(function (aa, bb) { return moduleName(aa).localeCompare(moduleName(bb)) }).forEach(function (child) {
var childIsOnlyDev = isOnlyDev(child)
- if (child.package._injectedFromShrinkwrap) {
- deps[moduleName(child)] = child.package._injectedFromShrinkwrap
+ if (child.fakeChild) {
+ deps[moduleName(child)] = child.fakeChild
return
}
var pkginfo = deps[moduleName(child)] = {}
@@ -148,16 +133,9 @@ function shrinkwrapDeps (problems, deps, top, tree, seen) {
}
if (childIsOnlyDev) pkginfo.dev = true
if (isOptional(child)) pkginfo.optional = true
- if (isExtraneous(child)) {
- problems.push('extraneous: ' + child.package._id + ' ' + child.path)
- }
- id.validatePeerDeps(child, function (tree, pkgname, version) {
- problems.push('peer invalid: ' + pkgname + '@' + version +
- ', required by ' + child.package._id)
- })
if (child.children.length) {
pkginfo.dependencies = {}
- shrinkwrapDeps(problems, pkginfo.dependencies, top, child, seen)
+ shrinkwrapDeps(pkginfo.dependencies, top, child, seen)
}
})
}
@@ -205,7 +183,6 @@ function updateLockfileMetadata (pkginfo, pkgJson) {
let metainfoWritten = false
const metainfo = new Set([
'lockfileVersion',
- 'packageIntegrity',
'preserveSymlinks'
])
Object.keys(pkginfo).forEach((k) => {
@@ -224,7 +201,6 @@ function updateLockfileMetadata (pkginfo, pkgJson) {
}
function writeMetainfo (pkginfo) {
pkginfo.lockfileVersion = PKGLOCK_VERSION
- pkginfo.packageIntegrity = pkgJson && pkgSri.hash(pkgJson)
if (process.env.NODE_PRESERVE_SYMLINKS) {
pkginfo.preserveSymlinks = process.env.NODE_PRESERVE_SYMLINKS
}
diff --git a/deps/npm/lib/uninstall.js b/deps/npm/lib/uninstall.js
index 9e3d91ac40..c181fdc4e8 100644
--- a/deps/npm/lib/uninstall.js
+++ b/deps/npm/lib/uninstall.js
@@ -2,24 +2,21 @@
// remove a package.
module.exports = uninstall
-module.exports.Uninstaller = Uninstaller
-var util = require('util')
-var path = require('path')
-var validate = require('aproba')
-var chain = require('slide').chain
-var readJson = require('read-package-json')
-var npm = require('./npm.js')
-var Installer = require('./install.js').Installer
-var getSaveType = require('./install/save.js').getSaveType
-var removeDeps = require('./install/deps.js').removeDeps
-var loadExtraneous = require('./install/deps.js').loadExtraneous
-var log = require('npmlog')
-var usage = require('./utils/usage')
+const path = require('path')
+const validate = require('aproba')
+const readJson = require('read-package-json')
+const iferr = require('iferr')
+const npm = require('./npm.js')
+const Installer = require('./install.js').Installer
+const getSaveType = require('./install/save.js').getSaveType
+const removeDeps = require('./install/deps.js').removeDeps
+const log = require('npmlog')
+const usage = require('./utils/usage')
uninstall.usage = usage(
'uninstall',
- 'npm uninstall [<@scope>/]<pkg>[@<version>]... [--save|--save-dev|--save-optional]'
+ 'npm uninstall [<@scope>/]<pkg>[@<version>]... [--save-prod|--save-dev|--save-optional] [--no-save]'
)
uninstall.completion = require('./utils/completion/installed-shallow.js')
@@ -27,17 +24,18 @@ uninstall.completion = require('./utils/completion/installed-shallow.js')
function uninstall (args, cb) {
validate('AF', arguments)
// the /path/to/node_modules/..
- var dryrun = !!npm.config.get('dry-run')
+ const dryrun = !!npm.config.get('dry-run')
if (args.length === 1 && args[0] === '.') args = []
- args = args.filter(function (a) {
- return path.resolve(a) !== where
- })
- var where = npm.config.get('global') || !args.length
+ const where = npm.config.get('global') || !args.length
? path.resolve(npm.globalDir, '..')
: npm.prefix
+ args = args.filter(function (a) {
+ return path.resolve(a) !== where
+ })
+
if (args.length) {
new Uninstaller(where, dryrun, args).run(cb)
} else {
@@ -50,29 +48,33 @@ function uninstall (args, cb) {
}
}
-function Uninstaller (where, dryrun, args) {
- validate('SBA', arguments)
- Installer.call(this, where, dryrun, args)
-}
-util.inherits(Uninstaller, Installer)
+class Uninstaller extends Installer {
+ constructor (where, dryrun, args) {
+ super(where, dryrun, args)
+ this.remove = []
+ this.fakeChildren = false
+ }
-Uninstaller.prototype.loadArgMetadata = function (next) {
- this.args = this.args.map(function (arg) { return {name: arg} })
- next()
-}
+ loadArgMetadata (next) {
+ this.args = this.args.map(function (arg) { return {name: arg} })
+ next()
+ }
-Uninstaller.prototype.loadAllDepsIntoIdealTree = function (cb) {
- validate('F', arguments)
- log.silly('uninstall', 'loadAllDepsIntoIdealTree')
- var saveDeps = getSaveType()
+ loadAllDepsIntoIdealTree (cb) {
+ validate('F', arguments)
+ this.remove = this.args
+ this.args = []
+ log.silly('uninstall', 'loadAllDepsIntoIdealTree')
+ const saveDeps = getSaveType()
- var cg = this.progress['loadIdealTree:loadAllDepsIntoIdealTree']
- var steps = []
- steps.push(
- [removeDeps, this.args, this.idealTree, saveDeps, cg.newGroup('removeDeps')],
- [loadExtraneous, this.idealTree, cg.newGroup('loadExtraneous')])
- chain(steps, cb)
+ super.loadAllDepsIntoIdealTree(iferr(cb, () => {
+ removeDeps(this.remove, this.idealTree, saveDeps, cb)
+ }))
+ }
+
+ // no top level lifecycles on rm
+ runPreinstallTopLevelLifecycles (cb) { cb() }
+ runPostinstallTopLevelLifecycles (cb) { cb() }
}
-Uninstaller.prototype.runPreinstallTopLevelLifecycles = function (cb) { cb() }
-Uninstaller.prototype.runPostinstallTopLevelLifecycles = function (cb) { cb() }
+module.exports.Uninstaller = Uninstaller
diff --git a/deps/npm/lib/utils/error-handler.js b/deps/npm/lib/utils/error-handler.js
index 8365f39d9d..5374d1feec 100644
--- a/deps/npm/lib/utils/error-handler.js
+++ b/deps/npm/lib/utils/error-handler.js
@@ -130,10 +130,12 @@ function exit (code, noLog) {
itWorked = !code
- // just emit a fake exit event.
- // if we're really exiting, then let it exit on its own, so that
- // in-process stuff can finish or clean up first.
- if (!doExit) process.emit('exit', code)
+ // Exit directly -- nothing in the CLI should still be running in the
+ // background at this point, and this makes sure anything left dangling
+ // for whatever reason gets thrown away, instead of leaving the CLI open
+ //
+ // Commands that expect long-running actions should just delay `cb()`
+ process.exit(code)
}
}
diff --git a/deps/npm/lib/utils/link.js b/deps/npm/lib/utils/link.js
index 605b77402c..15331740a4 100644
--- a/deps/npm/lib/utils/link.js
+++ b/deps/npm/lib/utils/link.js
@@ -64,7 +64,7 @@ function link (from, to, gently, abs, cb) {
[
[ensureFromIsNotSource, absTarget, to],
[fs, 'stat', absTarget],
- [rm, to, gently],
+ [rm, to, gently, path.dirname(to)],
[mkdir, path.dirname(to)],
[fs, 'symlink', target, to, 'junction']
],
diff --git a/deps/npm/lib/utils/package-integrity.js b/deps/npm/lib/utils/package-integrity.js
deleted file mode 100644
index f9560d660e..0000000000
--- a/deps/npm/lib/utils/package-integrity.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-// Utilities for generating and verifying the packageIntegrity field for
-// package-lock
-//
-// Spec: https://github.com/npm/npm/pull/16441
-
-const ssri = require('ssri')
-const SSRI_OPTS = {
- algorithms: ['sha512']
-}
-
-module.exports.check = check
-function check (pkg, integrity) {
- return ssri.checkData(JSON.stringify(pkg), integrity, SSRI_OPTS)
-}
-
-module.exports.hash = hash
-function hash (pkg) {
- return ssri.fromData(JSON.stringify(pkg), SSRI_OPTS).toString()
-}
diff --git a/deps/npm/lib/utils/tar.js b/deps/npm/lib/utils/tar.js
index 7ebc9d6875..ebbee025a2 100644
--- a/deps/npm/lib/utils/tar.js
+++ b/deps/npm/lib/utils/tar.js
@@ -3,8 +3,6 @@
// commands for packing and unpacking tarballs
// this file is used by lib/cache.js
-const BB = require('bluebird')
-
var fs = require('graceful-fs')
var path = require('path')
var writeFileAtomic = require('write-file-atomic')
@@ -28,11 +26,6 @@ var moduleName = require('./module-name.js')
var packageId = require('./package-id.js')
var pulseTillDone = require('../utils/pulse-till-done.js')
-const cacache = require('cacache')
-const packAsync = BB.promisify(pack)
-const PassThrough = require('stream').PassThrough
-const pipe = BB.promisify(require('mississippi').pipe)
-
if (process.env.SUDO_UID && myUid === 0) {
if (!isNaN(process.env.SUDO_UID)) myUid = +process.env.SUDO_UID
if (!isNaN(process.env.SUDO_GID)) myGid = +process.env.SUDO_GID
@@ -41,18 +34,6 @@ if (process.env.SUDO_UID && myUid === 0) {
exports.pack = pack
exports.unpack = unpack
-module.exports.packToStream = packToStream
-function packToStream (mani, dir) {
- const stream = new PassThrough()
- cacache.tmp.withTmp(npm.tmp, (tmp) => {
- const tmpTarget = path.join(tmp, 'package.tgz')
- return packAsync(tmpTarget, dir, mani).then(() => {
- return pipe(fs.createReadStream(tmpTarget), stream)
- })
- }).catch((err) => stream.emit('error', err))
- return stream
-}
-
function pack (tarball, folder, pkg, cb) {
log.verbose('tar pack', [tarball, folder])