aboutsummaryrefslogtreecommitdiff
path: root/deps/npm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/lib')
-rw-r--r--deps/npm/lib/config/defaults.js4
-rw-r--r--deps/npm/lib/doctor.js2
-rw-r--r--deps/npm/lib/fetch-package-metadata.md4
-rw-r--r--deps/npm/lib/npm.js15
-rw-r--r--deps/npm/lib/search.js65
-rw-r--r--deps/npm/lib/search/all-package-metadata.js2
-rw-r--r--deps/npm/lib/search/all-package-search.js50
-rw-r--r--deps/npm/lib/search/esearch.js64
-rw-r--r--deps/npm/lib/search/format-package-stream.js59
-rw-r--r--deps/npm/lib/utils/error-handler.js45
-rw-r--r--deps/npm/lib/utils/gunzip-maybe.js22
-rw-r--r--deps/npm/lib/utils/lifecycle.js1
12 files changed, 252 insertions, 81 deletions
diff --git a/deps/npm/lib/config/defaults.js b/deps/npm/lib/config/defaults.js
index 81ead08b6f..a79c8a0fa0 100644
--- a/deps/npm/lib/config/defaults.js
+++ b/deps/npm/lib/config/defaults.js
@@ -164,6 +164,7 @@ Object.defineProperty(exports, 'defaults', {get: function () {
'local-address': undefined,
loglevel: 'warn',
logstream: process.stderr,
+ 'logs-max': 10,
long: false,
maxsockets: 50,
message: '%s',
@@ -196,6 +197,7 @@ Object.defineProperty(exports, 'defaults', {get: function () {
'scripts-prepend-node-path': 'warn-only',
searchopts: '',
searchexclude: null,
+ searchlimit: 20,
searchstaleness: 15 * 60,
'send-metrics': false,
shell: osenv.shell(),
@@ -278,6 +280,7 @@ exports.types = {
'local-address': getLocalAddresses(),
loglevel: ['silent', 'error', 'warn', 'http', 'info', 'verbose', 'silly'],
logstream: Stream,
+ 'logs-max': Number,
long: Boolean,
maxsockets: Number,
message: String,
@@ -305,6 +308,7 @@ exports.types = {
'scripts-prepend-node-path': [false, true, 'auto', 'warn-only'],
searchopts: String,
searchexclude: [null, String],
+ searchlimit: Number,
searchstaleness: Number,
'send-metrics': Boolean,
shell: String,
diff --git a/deps/npm/lib/doctor.js b/deps/npm/lib/doctor.js
index f2037ab86c..18453491e4 100644
--- a/deps/npm/lib/doctor.js
+++ b/deps/npm/lib/doctor.js
@@ -98,7 +98,7 @@ function makePretty (p) {
if (ping !== 'ok') list[0][2] = 'Check your internet connection'
if (!semver.satisfies(npmV, '>=' + npmLTS)) list[1][2] = 'Use npm v' + npmLTS
if (!semver.satisfies(nodeV, '>=' + nodeLTS)) list[2][2] = 'Use node v' + nodeLTS
- if (registry !== defaultRegistry) list[3][2] = 'Try `npm config set registry ' + defaultRegistry
+ if (registry !== defaultRegistry) list[3][2] = 'Try `npm config set registry ' + defaultRegistry + '`'
if (whichGit === 'not installed') list[4][2] = 'Install git and ensure it\'s in your PATH.'
if (readbleCaches !== 'ok') list[5][2] = 'Check the permissions of your files in ' + npm.config.get('cache')
if (executableGlobalModules !== 'ok') list[6][2] = globalNodeModules + ' must be readable and writable by the current user.'
diff --git a/deps/npm/lib/fetch-package-metadata.md b/deps/npm/lib/fetch-package-metadata.md
index 6a7d4fc595..6fe4beac6e 100644
--- a/deps/npm/lib/fetch-package-metadata.md
+++ b/deps/npm/lib/fetch-package-metadata.md
@@ -5,7 +5,7 @@ fetch-package-metadata
fetchPackageMetadata(spec, contextdir, callback)
This will get package metadata (and if possible, ONLY package metadata) for
-a specifer as passed to `npm install` et al, eg `npm@next` or `npm@^2.0.3`
+a specifier as passed to `npm install` et al, eg `npm@next` or `npm@^2.0.3`
## fetchPackageMetadata(*spec*, *contextdir*, *tracker*, *callback*)
@@ -29,7 +29,7 @@ a specifer as passed to `npm install` et al, eg `npm@next` or `npm@^2.0.3`
In the case of tarballs and git repos, it will use the cache to download
them in order to get the package metadata. For named packages, only the
-metadata is downloaded (eg http://registry.npmjs.org/package). For local
+metadata is downloaded (eg https://registry.npmjs.org/package). For local
directories, the package.json is read directly. For local tarballs, the
tarball is streamed in memory and just the package.json is extracted from
it. (Due to the nature of tars, having the package.json early in the file
diff --git a/deps/npm/lib/npm.js b/deps/npm/lib/npm.js
index d0af64b195..890c369cc6 100644
--- a/deps/npm/lib/npm.js
+++ b/deps/npm/lib/npm.js
@@ -29,6 +29,8 @@
var path = require('path')
var abbrev = require('abbrev')
var which = require('which')
+ var glob = require('glob')
+ var rimraf = require('rimraf')
var CachingRegClient = require('./cache/caching-client.js')
var parseJSON = require('./utils/parse-json.js')
var aliases = require('./config/cmd-list').aliases
@@ -286,8 +288,21 @@
log.disableProgress()
}
+ glob(path.resolve(npm.cache, '_logs', '*-debug.log'), function (er, files) {
+ if (er) return cb(er)
+
+ while (files.length >= npm.config.get('logs-max')) {
+ rimraf.sync(files[0])
+ files.splice(0, 1)
+ }
+ })
+
log.resume()
+ // at this point the configs are all set.
+ // go ahead and spin up the registry client.
+ npm.registry = new CachingRegClient(npm.config)
+
var umask = npm.config.get('umask')
npm.modes = {
exec: parseInt('0777', 8) & (~umask),
diff --git a/deps/npm/lib/search.js b/deps/npm/lib/search.js
index c9f3628717..3987be135c 100644
--- a/deps/npm/lib/search.js
+++ b/deps/npm/lib/search.js
@@ -3,8 +3,8 @@
module.exports = exports = search
var npm = require('./npm.js')
-var allPackageMetadata = require('./search/all-package-metadata.js')
-var packageFilter = require('./search/package-filter.js')
+var allPackageSearch = require('./search/all-package-search')
+var esearch = require('./search/esearch.js')
var formatPackageStream = require('./search/format-package-stream.js')
var usage = require('./utils/usage')
var output = require('./utils/output.js')
@@ -21,33 +21,44 @@ search.completion = function (opts, cb) {
}
function search (args, cb) {
- var staleness = npm.config.get('searchstaleness')
+ var searchOpts = {
+ description: npm.config.get('description'),
+ exclude: prepareExcludes(npm.config.get('searchexclude')),
+ include: prepareIncludes(args, npm.config.get('searchopts')),
+ limit: npm.config.get('searchlimit'),
+ log: log,
+ staleness: npm.config.get('searchstaleness'),
+ unicode: npm.config.get('unicode')
+ }
- var include = prepareIncludes(args, npm.config.get('searchopts'))
- if (include.length === 0) {
+ if (searchOpts.include.length === 0) {
return cb(new Error('search must be called with arguments'))
}
- var exclude = prepareExcludes(npm.config.get('searchexclude'))
-
// Used later to figure out whether we had any packages go out
var anyOutput = false
- // Get a stream with *all* the packages. This takes care of dealing
- // with the local cache as well, but that's an internal detail.
- var allEntriesStream = allPackageMetadata(staleness)
+ var entriesStream = ms.through.obj()
- // Grab a stream that filters those packages according to given params.
- var searchSection = (npm.config.get('unicode') ? '🤔 ' : '') + 'search'
- var filterStream = streamFilter(function (pkg) {
- log.gauge.pulse('search')
- log.gauge.show({section: searchSection, logline: 'scanning ' + pkg.name})
- // Simply 'true' if the package matches search parameters.
- var match = packageFilter(pkg, include, exclude, {
- description: npm.config.get('description')
+ var esearchWritten = false
+ esearch(searchOpts).on('data', function (pkg) {
+ entriesStream.write(pkg)
+ !esearchWritten && (esearchWritten = true)
+ }).on('error', function (e) {
+ if (esearchWritten) {
+ // If esearch errored after already starting output, we can't fall back.
+ return entriesStream.emit('error', e)
+ }
+ log.warn('search', 'fast search endpoint errored. Using old search.')
+ allPackageSearch(searchOpts).on('data', function (pkg) {
+ entriesStream.write(pkg)
+ }).on('error', function (e) {
+ entriesStream.emit('error', e)
+ }).on('end', function () {
+ entriesStream.end()
})
- if (match) { anyOutput = true }
- return match
+ }).on('end', function () {
+ entriesStream.end()
})
// Grab a configured output stream that will spit out packages in the
@@ -61,16 +72,17 @@ function search (args, cb) {
color: npm.color
})
outputStream.on('data', function (chunk) {
+ if (!anyOutput) { anyOutput = true }
output(chunk.toString('utf8'))
})
log.silly('search', 'searching packages')
- ms.pipe(allEntriesStream, filterStream, outputStream, function (er) {
+ ms.pipe(entriesStream, outputStream, function (er) {
if (er) return cb(er)
if (!anyOutput && !npm.config.get('json') && !npm.config.get('parseable')) {
output('No matches found for ' + (args.map(JSON.stringify).join(' ')))
}
- log.silly('search', 'index search completed')
+ log.silly('search', 'search completed')
log.clearProgress()
cb(null, {})
})
@@ -94,12 +106,3 @@ function prepareExcludes (searchexclude) {
return s.toLowerCase()
})
}
-
-function streamFilter (filter) {
- return ms.through.obj(function (chunk, enc, cb) {
- if (filter(chunk)) {
- this.push(chunk)
- }
- cb()
- })
-}
diff --git a/deps/npm/lib/search/all-package-metadata.js b/deps/npm/lib/search/all-package-metadata.js
index ce917f5ef0..fda5b6d306 100644
--- a/deps/npm/lib/search/all-package-metadata.js
+++ b/deps/npm/lib/search/all-package-metadata.js
@@ -14,6 +14,7 @@ var writeStreamAtomic = require('fs-write-stream-atomic')
var ms = require('mississippi')
var sortedUnionStream = require('sorted-union-stream')
var once = require('once')
+var gunzip = require('../utils/gunzip-maybe')
// Returns a sorted stream of all package metadata. Internally, takes care of
// maintaining its metadata cache and making partial or full remote requests,
@@ -153,6 +154,7 @@ function createEntryUpdateStream (all, auth, staleness, latest, cb) {
ms.through(function (chunk, enc, cb) {
cb(null, chunk)
}),
+ gunzip(),
jsonstream.parse('*', function (pkg, key) {
if (key[0] === '_updated' || key[0][0] !== '_') {
return pkg
diff --git a/deps/npm/lib/search/all-package-search.js b/deps/npm/lib/search/all-package-search.js
new file mode 100644
index 0000000000..7a893d517b
--- /dev/null
+++ b/deps/npm/lib/search/all-package-search.js
@@ -0,0 +1,50 @@
+var ms = require('mississippi')
+var allPackageMetadata = require('./all-package-metadata')
+var packageFilter = require('./package-filter.js')
+
+module.exports = allPackageSearch
+function allPackageSearch (opts) {
+ var searchSection = (opts.unicode ? '🤔 ' : '') + 'search'
+
+ // Get a stream with *all* the packages. This takes care of dealing
+ // with the local cache as well, but that's an internal detail.
+ var allEntriesStream = allPackageMetadata(opts.staleness)
+
+ // Grab a stream that filters those packages according to given params.
+ var filterStream = streamFilter(function (pkg) {
+ opts.log.gauge.pulse('search')
+ opts.log.gauge.show({section: searchSection, logline: 'scanning ' + pkg.name})
+ // Simply 'true' if the package matches search parameters.
+ var match = packageFilter(pkg, opts.include, opts.exclude, {
+ description: opts.description
+ })
+ return match
+ })
+ return ms.pipeline.obj(allEntriesStream, filterStream)
+}
+
+function streamFilter (filter) {
+ return ms.through.obj(function (data, enc, cb) {
+ if (filter(data)) {
+ this.push(standardizePkg(data))
+ }
+ cb()
+ })
+}
+
+function standardizePkg (data) {
+ return {
+ name: data.name,
+ description: data.description,
+ maintainers: (data.maintainers || []).map(function (m) {
+ return { username: m.name, email: m.email }
+ }),
+ keywords: data.keywords || [],
+ version: Object.keys(data.versions || {})[0] || [],
+ date: (
+ data.time &&
+ data.time.modified &&
+ new Date(data.time.modified)
+ ) || null
+ }
+}
diff --git a/deps/npm/lib/search/esearch.js b/deps/npm/lib/search/esearch.js
new file mode 100644
index 0000000000..f4beb7ade6
--- /dev/null
+++ b/deps/npm/lib/search/esearch.js
@@ -0,0 +1,64 @@
+'use strict'
+
+var npm = require('../npm.js')
+var log = require('npmlog')
+var mapToRegistry = require('../utils/map-to-registry.js')
+var jsonstream = require('JSONStream')
+var ms = require('mississippi')
+var gunzip = require('../utils/gunzip-maybe')
+
+module.exports = esearch
+
+function esearch (opts) {
+ var stream = ms.through.obj()
+
+ mapToRegistry('-/v1/search', npm.config, function (er, uri, auth) {
+ if (er) return stream.emit('error', er)
+ createResultStream(uri, auth, opts, function (err, resultStream) {
+ if (err) return stream.emit('error', err)
+ ms.pipeline.obj(resultStream, stream)
+ })
+ })
+ return stream
+}
+
+function createResultStream (uri, auth, opts, cb) {
+ log.verbose('esearch', 'creating remote entry stream')
+ var params = {
+ timeout: 600,
+ follow: true,
+ staleOk: true,
+ auth: auth,
+ streaming: true
+ }
+ var q = buildQuery(opts)
+ npm.registry.request(uri + '?text=' + encodeURIComponent(q) + '&size=' + opts.limit, params, function (err, res) {
+ if (err) return cb(err)
+ log.silly('esearch', 'request stream opened, code:', res.statusCode)
+ // NOTE - The stream returned by `request` seems to be very persnickety
+ // and this is almost a magic incantation to get it to work.
+ // Modify how `res` is used here at your own risk.
+ var entryStream = ms.pipeline.obj(
+ res,
+ ms.through(function (chunk, enc, cb) {
+ cb(null, chunk)
+ }),
+ gunzip(),
+ jsonstream.parse('objects.*.package', function (data) {
+ return {
+ name: data.name,
+ description: data.description,
+ maintainers: data.maintainers,
+ keywords: data.keywords,
+ version: data.version,
+ date: data.date ? new Date(data.date) : null
+ }
+ })
+ )
+ return cb(null, entryStream)
+ })
+}
+
+function buildQuery (opts) {
+ return opts.include.join(' ')
+}
diff --git a/deps/npm/lib/search/format-package-stream.js b/deps/npm/lib/search/format-package-stream.js
index d4333dc1a6..caa46cb898 100644
--- a/deps/npm/lib/search/format-package-stream.js
+++ b/deps/npm/lib/search/format-package-stream.js
@@ -4,6 +4,20 @@ var ms = require('mississippi')
var jsonstream = require('JSONStream')
var columnify = require('columnify')
+// This module consumes package data in the following format:
+//
+// {
+// name: String,
+// description: String,
+// maintainers: [{ username: String, email: String }],
+// keywords: String | [String],
+// version: String,
+// date: Date // can be null,
+// }
+//
+// The returned stream will format this package data
+// into a byte stream of formatted, displayable output.
+
module.exports = formatPackageStream
function formatPackageStream (opts) {
opts = opts || {}
@@ -33,26 +47,7 @@ function prettify (data, num, opts) {
opts = opts || {}
var truncate = !opts.long
- var dat = stripData(data, opts)
- dat.author = dat.maintainers
- delete dat.maintainers
- dat.date = dat.time
- delete dat.time
- // split keywords on whitespace or ,
- if (typeof dat.keywords === 'string') {
- dat.keywords = dat.keywords.split(/[,\s]+/)
- }
- if (Array.isArray(dat.keywords)) {
- dat.keywords = dat.keywords.join(' ')
- }
-
- // split author on whitespace or ,
- if (typeof dat.author === 'string') {
- dat.author = dat.author.split(/[,\s]+/)
- }
- if (Array.isArray(dat.author)) {
- dat.author = dat.author.join(' ')
- }
+ var pkg = normalizePackage(data, opts)
var columns = opts.description
? ['name', 'description', 'author', 'date', 'version', 'keywords']
@@ -60,12 +55,12 @@ function prettify (data, num, opts) {
if (opts.parseable) {
return columns.map(function (col) {
- return dat[col] && ('' + dat[col]).replace(/\t/g, ' ')
+ return pkg[col] && ('' + pkg[col]).replace(/\t/g, ' ')
}).join('\t')
}
var output = columnify(
- [dat],
+ [pkg],
{
include: columns,
showHeaders: num <= 1,
@@ -153,20 +148,22 @@ function highlightSearchTerms (str, terms) {
return colorize(str).trim()
}
-function stripData (data, opts) {
+function normalizePackage (data, opts) {
opts = opts || {}
return {
name: data.name,
description: opts.description ? data.description : '',
- maintainers: (data.maintainers || []).map(function (m) {
- return '=' + m.name
- }),
- url: !Object.keys(data.versions || {}).length ? data.url : null,
- keywords: data.keywords || [],
+ author: (data.maintainers || []).map(function (m) {
+ return '=' + m.username
+ }).join(' '),
+ keywords: Array.isArray(data.keywords)
+ ? data.keywords.join(' ')
+ : typeof data.keywords === 'string'
+ ? data.keywords.replace(/[,\s]+/, ' ')
+ : '',
version: Object.keys(data.versions || {})[0] || [],
- time: data.time &&
- data.time.modified &&
- (new Date(data.time.modified).toISOString() // remove time
+ date: data.date &&
+ (data.date.toISOString() // remove time
.split('T').join(' ')
.replace(/:[0-9]{2}\.[0-9]{3}Z$/, ''))
.slice(0, -5) ||
diff --git a/deps/npm/lib/utils/error-handler.js b/deps/npm/lib/utils/error-handler.js
index f3cfc3c5ea..a2911a101a 100644
--- a/deps/npm/lib/utils/error-handler.js
+++ b/deps/npm/lib/utils/error-handler.js
@@ -14,6 +14,15 @@ var chain = require('slide').chain
var writeStreamAtomic = require('fs-write-stream-atomic')
var errorMessage = require('./error-message.js')
var stopMetrics = require('./metrics.js').stop
+var mkdir = require('mkdirp')
+
+var logFileName
+function getLogFile () {
+ if (!logFileName) {
+ logFileName = path.resolve(npm.config.get('cache'), '_logs', (new Date()).toISOString().replace(/[.:]/g, '_') + '-debug.log')
+ }
+ return logFileName
+}
process.on('exit', function (code) {
log.disableProgress()
@@ -37,7 +46,7 @@ process.on('exit', function (code) {
'',
[
'Please include the following file with any support request:',
- ' ' + path.resolve('npm-debug.log')
+ ' ' + getLogFile()
].join('\n')
)
wroteLogFile = false
@@ -79,7 +88,7 @@ function exit (code, noLog) {
else writeLogFile(reallyExit.bind(this, er))
} else {
if (!noLog && code) writeLogFile(reallyExit)
- else rm('npm-debug.log', reallyExit)
+ else rm(getLogFile(), reallyExit)
}
})
rollbacks.length = 0
@@ -191,22 +200,26 @@ function writeLogFile (cb) {
writingLogFile = true
wroteLogFile = true
- var fstr = writeStreamAtomic('npm-debug.log')
var os = require('os')
- var out = ''
- log.record.forEach(function (m) {
- var pref = [m.id, m.level]
- if (m.prefix) pref.push(m.prefix)
- pref = pref.join(' ')
-
- m.message.trim().split(/\r?\n/).map(function (line) {
- return (pref + ' ' + line).trim()
- }).forEach(function (line) {
- out += line + os.EOL
+ mkdir(path.resolve(npm.config.get('cache'), '_logs'), function (er) {
+ if (er) {
+ cb(er)
+ return
+ }
+ var fstr = writeStreamAtomic(getLogFile())
+ log.record.forEach(function (m) {
+ var pref = [m.id, m.level]
+ if (m.prefix) pref.push(m.prefix)
+ pref = pref.join(' ')
+
+ m.message.trim().split(/\r?\n/).map(function (line) {
+ return (pref + ' ' + line).trim()
+ }).forEach(function (line) {
+ fstr.write(line + os.EOL)
+ })
})
+ fstr.end()
+ fstr.on('close', cb)
})
-
- fstr.end(out)
- fstr.on('close', cb)
}
diff --git a/deps/npm/lib/utils/gunzip-maybe.js b/deps/npm/lib/utils/gunzip-maybe.js
new file mode 100644
index 0000000000..db75f06017
--- /dev/null
+++ b/deps/npm/lib/utils/gunzip-maybe.js
@@ -0,0 +1,22 @@
+var duplex = require('mississippi').duplex
+var through = require('mississippi').through
+var zlib = require('zlib')
+
+function hasGzipHeader (c) {
+ return c[0] === 0x1F && c[1] === 0x8B && c[2] === 0x08
+}
+
+module.exports = gunzip
+function gunzip () {
+ var stream = duplex()
+ var peeker = through(function (chunk, enc, cb) {
+ var newStream = hasGzipHeader(chunk)
+ ? zlib.createGunzip()
+ : through()
+ stream.setReadable(newStream)
+ stream.setWritable(newStream)
+ stream.write(chunk)
+ })
+ stream.setWritable(peeker)
+ return stream
+}
diff --git a/deps/npm/lib/utils/lifecycle.js b/deps/npm/lib/utils/lifecycle.js
index a1d1625153..f48d5e2a3b 100644
--- a/deps/npm/lib/utils/lifecycle.js
+++ b/deps/npm/lib/utils/lifecycle.js
@@ -277,6 +277,7 @@ function runCmd_ (cmd, pkg, env, wd, stage, unsafe, uid, gid, cb_) {
process.kill(process.pid, signal)
} else if (code) {
var er = new Error('Exit status ' + code)
+ er.errno = code
}
procError(er)
})