diff options
author | isaacs <i@izs.me> | 2020-11-06 23:04:03 +0300 |
---|---|---|
committer | isaacs <i@izs.me> | 2020-11-06 23:04:03 +0300 |
commit | 6141de7b9e866979bf51706fd1be10c54235cf08 (patch) | |
tree | 662b1b1def50f48da6b11f82831f47d9581a278d | |
parent | 1d90b2747ac3c7d4f6fa1df2c23aec33c4e0d8a0 (diff) | |
parent | 3ef108a4d56cf3900ef9ff7111ee7746a6170e2e (diff) |
Merge branch 'release/v7.0.9' into latest
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | CHANGELOG.md | 43 | ||||
-rw-r--r-- | lib/adduser.js | 3 | ||||
-rw-r--r-- | lib/cache.js | 20 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js | 16 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/lib/arborist/load-virtual.js | 23 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/lib/arborist/reify.js | 8 | ||||
-rw-r--r-- | node_modules/@npmcli/arborist/package.json | 3 | ||||
-rw-r--r-- | node_modules/libnpmversion/lib/version.js | 2 | ||||
-rw-r--r-- | node_modules/libnpmversion/package.json | 2 | ||||
-rw-r--r-- | node_modules/pacote/lib/fetcher.js | 16 | ||||
-rw-r--r-- | node_modules/pacote/package.json | 4 | ||||
-rw-r--r-- | package-lock.json | 160 | ||||
-rw-r--r-- | package.json | 10 | ||||
-rwxr-xr-x | scripts/install.sh | 170 | ||||
-rw-r--r-- | test/lib/adduser.js | 13 | ||||
-rw-r--r-- | test/lib/cache.js | 232 |
17 files changed, 488 insertions, 238 deletions
@@ -730,3 +730,4 @@ Michele Azzolari <michele@azzolari.it> foxxyz <foxxyz@gmail.com> Dr <dr@dr.run> Jan Tojnar <jtojnar@gmail.com> +Jason Attwood <jason_attwood@hotmail.co.uk> diff --git a/CHANGELOG.md b/CHANGELOG.md index 49d44ab10..1e300dcff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,46 @@ +## 7.0.9 (2020-11-06) + +### BUG FIXES + +* [`96a0d2802`](https://github.com/npm/cli/commit/96a0d2802d3e619c6ea47290f5c460edfe94070a) + default the 'start' script when server.js present + ([@isaacs](https://github.com/isaacs)) +* [`7716e423e`](https://github.com/npm/cli/commit/7716e423ee92a81730c0dfe5b9ecb4bb41a3f947) + [#2075](https://github.com/npm/cli/issues/2075) + [#2071](https://github.com/npm/cli/issues/2071) print the registry when + using 'npm login' ([@Wicked7000](https://github.com/Wicked7000)) +* [`7046fe10c`](https://github.com/npm/cli/commit/7046fe10c5035ac57246a31ca8a6b09e3f5562bf) + [#2122](https://github.com/npm/cli/issues/2122) tests for `npm cache` + command ([@nlf](https://github.com/nlf)) + +### DEPENDENCIES + +* [`74325f53b`](https://github.com/npm/cli/commit/74325f53b9d813b0e42203c037189418fad2f64a) + [#2124](https://github.com/npm/cli/issues/2124) + `@npmcli/run-script@1.7.5`: + * Export the `isServerPackage` method + * Proxy signals to and from foreground child processes +* [`0e58e6f6b`](https://github.com/npm/cli/commit/0e58e6f6b8f0cd62294642a502c17561aaf46553) + [#1984](https://github.com/npm/cli/issues/1984) + [#2079](https://github.com/npm/cli/issues/2079) + [#1923](https://github.com/npm/cli/issues/1923) + [#606](https://github.com/npm/cli/issues/606) + [#2031](https://github.com/npm/cli/issues/2031) `@npmcli/arborist@1.0.9`: + * Process deps for all link nodes + * Use junctions instead of symlinks + * Use @npmcli/move-file instead of fs.rename +* [`1dad328a1`](https://github.com/npm/cli/commit/1dad328a17d93def7799545596b4eba9833b35aa) + [#1865](https://github.com/npm/cli/issues/1865) + [#2106](https://github.com/npm/cli/issues/2106) + [#2084](https://github.com/npm/cli/issues/2084) `pacote@11.1.13`: + * Properly set the installation command for `prepare` scripts when + installing git/dir deps +* [`e090d706c`](https://github.com/npm/cli/commit/e090d706ca637d4df96d28bff1660590aa3f3b62) + [#2097](https://github.com/npm/cli/issues/2097) `libnpmversion@1.0.7`: + * Do not crash when the package.json file lacks a 'version' field +* [`8fa541a10`](https://github.com/npm/cli/commit/8fa541a10dbdc09376175db7a378cc9b33e8b17b) + `cmark-gfm@0.8.4` + ## 7.0.8 (2020-11-03) ### DOCUMENTATION diff --git a/lib/adduser.js b/lib/adduser.js index 895a677c0..5017f57a8 100644 --- a/lib/adduser.js +++ b/lib/adduser.js @@ -4,6 +4,7 @@ const log = require('npmlog') const npm = require('./npm.js') const output = require('./utils/output.js') const usageUtil = require('./utils/usage.js') +const replaceInfo = require('./utils/replace-info.js') const authTypes = { legacy: require('./auth/legacy.js'), oauth: require('./auth/oauth.js'), @@ -57,6 +58,8 @@ const adduser = async (args) => { log.disableProgress() + log.notice('', `Log in on ${replaceInfo(registry)}`) + const { message, newCreds } = await auth({ creds, registry, diff --git a/lib/cache.js b/lib/cache.js index bf788043a..30d6aef86 100644 --- a/lib/cache.js +++ b/lib/cache.js @@ -22,10 +22,11 @@ const usage = usageUtil('cache', const completion = (opts, cb) => { const argv = opts.conf.argv.remain if (argv.length === 2) - return cb(null, ['add', 'clean']) + return cb(null, ['add', 'clean', 'verify']) // TODO - eventually... switch (argv[2]) { + case 'verify': case 'clean': case 'add': return cb(null, []) @@ -40,11 +41,11 @@ const cache = async (args) => { case 'rm': case 'clear': case 'clean': return await clean(args) case 'add': - return await add(args, npm.prefix) + return await add(args) case 'verify': case 'check': return await verify() default: - throw usage + throw Object.assign(new Error(usage), { code: 'EUSAGE' }) } } @@ -77,22 +78,21 @@ with --force.`) // npm cache add <pkg> <ver> // npm cache add <tarball> // npm cache add <folder> -const add = async (args, where) => { +const add = async (args) => { const usage = 'Usage:\n' + ' npm cache add <tarball-url>\n' + ' npm cache add <pkg>@<ver>\n' + ' npm cache add <tarball>\n' + ' npm cache add <folder>\n' log.silly('cache add', 'args', args) - const spec = args[0] + + const spec = args[0] && args[0] + (args[1] === undefined || args[1] === null ? '' : `@${args[1]}`) - log.verbose('cache add', 'spec', spec) if (!spec) - throw new Error(usage) + throw Object.assign(new Error(usage), { code: 'EUSAGE' }) - log.silly('cache add', 'parsed spec', spec) - const opts = { ...npm.flatOptions, where } + log.silly('cache add', 'spec', spec) + const opts = { ...npm.flatOptions } // we ask pacote for the thing, and then just throw the data // away so that it tee-pipes it into the cache like it does @@ -109,7 +109,7 @@ const verify = async () => { ? `~${cache.substr(process.env.HOME.length)}` : cache const stats = await cacache.verify(cache) - output(`Cache verified and compressed (${prefix}):`) + output(`Cache verified and compressed (${prefix})`) output(`Content verified: ${stats.verifiedContent} (${stats.keptSize} bytes)`) stats.badContentCount && output(`Corrupted content removed: ${stats.badContentCount}`) stats.reclaimedCount && output(`Content garbage-collected: ${stats.reclaimedCount} (${stats.reclaimedSize} bytes)`) diff --git a/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js b/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js index 54a6ff337..582575ebf 100644 --- a/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js +++ b/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js @@ -790,6 +790,11 @@ This is a one-time fix-up, please be patient... } await Promise.all(promises) + for (const { to } of node.edgesOut.values()) { + if (to && to.isLink) + this[_linkNodes].add(to) + } + return this[_buildDepStep]() } @@ -1539,9 +1544,14 @@ This is a one-time fix-up, please be patient... } } - // didn't find a parent for it, but we're filling in external - // link targets, so go ahead and process it. - if (this[_follow] && !link.target.parent && !link.target.fsParent) { + // didn't find a parent for it or it has not been seen yet + // so go ahead and process it. + const unseenLink = (link.target.parent || link.target.fsParent) + && !this[_depsSeen].has(link.target) + if (this[_follow] + && !link.target.parent + && !link.target.fsParent + || unseenLink) { this.addTracker('idealTree', link.target.name, link.target.location) this[_depsQueue].push(link.target) } diff --git a/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js b/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js index 14c960927..924d720de 100644 --- a/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js +++ b/node_modules/@npmcli/arborist/lib/arborist/load-virtual.js @@ -185,12 +185,6 @@ module.exports = cls => class VirtualLoader extends cls { // links is the set of metadata, and nodes is the map of non-Link nodes // Set the targets to nodes in the set, if we have them (we might not) async [resolveLinks] (links, nodes) { - // now we've loaded the root, and all real nodes - // link up the links - const {meta} = this.virtualTree - const {loadedFromDisk, originalLockfileVersion} = meta - const oldLockfile = loadedFromDisk && !(originalLockfileVersion >= 2) - for (const [location, meta] of links.entries()) { const targetPath = resolve(this.path, meta.resolved) const targetLoc = relpath(this.path, targetPath) @@ -198,16 +192,13 @@ module.exports = cls => class VirtualLoader extends cls { const link = this[loadLink](location, targetLoc, target, meta) nodes.set(location, link) nodes.set(targetLoc, link.target) - // legacy shrinkwraps do not store all the info we need for the target. - // if we're loading from disk, and have a link in place, we need to - // look in that actual folder (or at least try to) in order to get - // the dependencies of the link target and load it properly. - if (oldLockfile) { - const pj = link.realpath + '/package.json' - const pkg = await rpj(pj).catch(() => null) - if (pkg) - link.target.package = pkg - } + + // we always need to read the package.json for link targets + // because they can be changed by the local user + const pj = link.realpath + '/package.json' + const pkg = await rpj(pj).catch(() => null) + if (pkg) + link.target.package = pkg } } diff --git a/node_modules/@npmcli/arborist/lib/arborist/reify.js b/node_modules/@npmcli/arborist/lib/arborist/reify.js index 57ecf071f..8711f8d29 100644 --- a/node_modules/@npmcli/arborist/lib/arborist/reify.js +++ b/node_modules/@npmcli/arborist/lib/arborist/reify.js @@ -10,10 +10,10 @@ const {dirname, resolve, relative} = require('path') const {depth: dfwalk} = require('treeverse') const fs = require('fs') const {promisify} = require('util') -const rename = promisify(fs.rename) const symlink = promisify(fs.symlink) const writeFile = promisify(fs.writeFile) const mkdirp = require('mkdirp-infer-owner') +const moveFile = require('@npmcli/move-file') const rimraf = promisify(require('rimraf')) const packageContents = require('@npmcli/installed-package-contents') @@ -251,7 +251,7 @@ module.exports = cls => class Reifier extends cls { } [_renamePath] (from, to, didMkdirp = false) { - return rename(from, to) + return moveFile(from, to) .catch(er => { // Occasionally an expected bin file might not exist in the package, // or a shim/symlink might have been moved aside. If we've already @@ -261,7 +261,7 @@ module.exports = cls => class Reifier extends cls { return didMkdirp ? null : mkdirp(dirname(to)).then(() => this[_renamePath](from, to, true)) } else if (er.code === 'EEXIST') - return rimraf(to).then(() => rename(from, to)) + return rimraf(to).then(() => moveFile(from, to)) else throw er }) @@ -427,7 +427,7 @@ module.exports = cls => class Reifier extends cls { const dir = dirname(node.path) const target = node.realpath const rel = relative(dir, target) - return symlink(rel, node.path, 'dir') + return symlink(rel, node.path, 'junction') } [_warnDeprecated] (node) { diff --git a/node_modules/@npmcli/arborist/package.json b/node_modules/@npmcli/arborist/package.json index fe72f409c..99522745c 100644 --- a/node_modules/@npmcli/arborist/package.json +++ b/node_modules/@npmcli/arborist/package.json @@ -1,11 +1,12 @@ { "name": "@npmcli/arborist", - "version": "1.0.8", + "version": "1.0.9", "description": "Manage node_modules trees", "dependencies": { "@npmcli/installed-package-contents": "^1.0.5", "@npmcli/map-workspaces": "^1.0.1", "@npmcli/metavuln-calculator": "^1.0.0", + "@npmcli/move-file": "^1.0.1", "@npmcli/name-from-folder": "^1.0.1", "@npmcli/node-gyp": "^1.0.0", "@npmcli/run-script": "^1.7.2", diff --git a/node_modules/libnpmversion/lib/version.js b/node_modules/libnpmversion/lib/version.js index ee02fb7ff..309b9c2b9 100644 --- a/node_modules/libnpmversion/lib/version.js +++ b/node_modules/libnpmversion/lib/version.js @@ -34,7 +34,7 @@ module.exports = async (newversion, opts) => { } = opts const { valid, clean, inc } = semver - const current = pkg.version + const current = pkg.version || '0.0.0' const currentClean = clean(current) const newV = valid(newversion, { loose: true }) ? clean(newversion, { loose: true }) diff --git a/node_modules/libnpmversion/package.json b/node_modules/libnpmversion/package.json index 856e36da6..d7e8d5fa5 100644 --- a/node_modules/libnpmversion/package.json +++ b/node_modules/libnpmversion/package.json @@ -1,6 +1,6 @@ { "name": "libnpmversion", - "version": "1.0.6", + "version": "1.0.7", "main": "lib/index.js", "files": [ "lib/*.js" diff --git a/node_modules/pacote/lib/fetcher.js b/node_modules/pacote/lib/fetcher.js index 01058acb2..5142bb280 100644 --- a/node_modules/pacote/lib/fetcher.js +++ b/node_modules/pacote/lib/fetcher.js @@ -91,18 +91,11 @@ class FetcherBase { // command to run 'prepare' scripts on directories and git dirs // To use pacote with yarn, for example, set npmBin to 'yarn' - // and npmInstallCmd to ['add'], and npmCliConfig with yarn's equivalents. + // and npmCliConfig with yarn's equivalents. this.npmBin = opts.npmBin || 'npm' // command to install deps for preparing - this.npmInstallCmd = opts.npmInstallCmd || [ - 'install', - '--only=dev', - '--prod', - '--ignore-prepublish', - '--no-progress', - '--no-save', - ] + this.npmInstallCmd = opts.npmInstallCmd || [ 'install' ] // XXX fill more of this in based on what we know from this.opts // we explicitly DO NOT fill in --tag, though, since we are often @@ -113,7 +106,10 @@ class FetcherBase { `--prefer-offline=${!!this.preferOffline}`, `--prefer-online=${!!this.preferOnline}`, `--offline=${!!this.offline}`, - `--before=${this.before ? this.before.toISOString() : ''}`, + ...(this.before ? [`--before=${this.before.toISOString()}`] : []), + '--no-progress', + '--no-save', + '--no-audit', ] } diff --git a/node_modules/pacote/package.json b/node_modules/pacote/package.json index 7f38a193f..bef19b662 100644 --- a/node_modules/pacote/package.json +++ b/node_modules/pacote/package.json @@ -1,6 +1,6 @@ { "name": "pacote", - "version": "11.1.12", + "version": "11.1.13", "description": "JavaScript package downloader", "author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)", "bin": { @@ -47,7 +47,7 @@ "minipass": "^3.1.3", "mkdirp": "^1.0.3", "npm-package-arg": "^8.0.1", - "npm-packlist": "^2.1.0", + "npm-packlist": "^2.1.4", "npm-pick-manifest": "^6.0.0", "npm-registry-fetch": "^9.0.0", "promise-retry": "^1.1.1", diff --git a/package-lock.json b/package-lock.json index f0617ffe2..5c5b78a55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "npm", - "version": "7.0.8", + "version": "7.0.9", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "npm", - "version": "7.0.8", + "version": "7.0.9", "bundleDependencies": [ "@npmcli/arborist", "@npmcli/ci-detect", @@ -78,7 +78,7 @@ ], "license": "Artistic-2.0", "dependencies": { - "@npmcli/arborist": "^1.0.8", + "@npmcli/arborist": "^1.0.9", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^1.2.1", "@npmcli/run-script": "^1.7.5", @@ -112,7 +112,7 @@ "libnpmpublish": "^4.0.0", "libnpmsearch": "^3.0.1", "libnpmteam": "^2.0.2", - "libnpmversion": "^1.0.6", + "libnpmversion": "^1.0.7", "make-fetch-happen": "^8.0.9", "mkdirp": "^1.0.4", "mkdirp-infer-owner": "^2.0.0", @@ -128,7 +128,7 @@ "npm-user-validate": "^1.0.1", "npmlog": "~4.1.2", "opener": "^1.5.2", - "pacote": "^11.1.12", + "pacote": "^11.1.13", "parse-conflict-json": "^1.1.1", "qrcode-terminal": "^0.12.0", "read": "~1.0.7", @@ -151,7 +151,7 @@ "npx": "bin/npx-cli.js" }, "devDependencies": { - "cmark-gfm": "^0.8.3", + "cmark-gfm": "^0.8.4", "eslint": "^7.12.1", "eslint-plugin-import": "^2.22.1", "eslint-plugin-node": "^11.1.0", @@ -386,14 +386,15 @@ } }, "node_modules/@npmcli/arborist": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-1.0.8.tgz", - "integrity": "sha512-LAopKkhAnBr6/cbIpH9VeNS4yLWMFf6AFKC7x3XHvNFDMy8cmvEjWtjcpV8ACjPPm4UbjIzQ/n4qrxaA0ZyBDA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-1.0.9.tgz", + "integrity": "sha512-bvaPKdlT4F0U2JT0eV1fprv9dWdjFxY+O7WbXMvABvyO81kUPTJTBe1HhsGTIqXTrt2cOqXtLJI31Xs7iugptg==", "inBundle": true, "dependencies": { "@npmcli/installed-package-contents": "^1.0.5", "@npmcli/map-workspaces": "^1.0.1", "@npmcli/metavuln-calculator": "^1.0.0", + "@npmcli/move-file": "^1.0.1", "@npmcli/name-from-folder": "^1.0.1", "@npmcli/node-gyp": "^1.0.0", "@npmcli/run-script": "^1.7.2", @@ -955,13 +956,27 @@ "dev": true }, "node_modules/buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "node_modules/buffer-from": { @@ -1238,15 +1253,15 @@ } }, "node_modules/cmark-gfm": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/cmark-gfm/-/cmark-gfm-0.8.3.tgz", - "integrity": "sha512-DgFD2xlYgO46BQULAFTKvHja2TtnuxJQw3+4msxgRngohIzZR9hrkhqIIWwn/Kad2r/X8C1OQG8PMZwVAsI1vw==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/cmark-gfm/-/cmark-gfm-0.8.4.tgz", + "integrity": "sha512-SzcGygfWYk35SAJ6nO/w8Yng0mMOY4225iwL+joR+WAf/GS5b+bzZdpPeSE66Hrx+QW7NaoZbwjfDPSbqAoF2A==", "dev": true, "hasInstallScript": true, "dependencies": { "bindings": "^1.5.0", "node-addon-api": "^3.0.0", - "prebuild-install": "^5.3.5" + "prebuild-install": "^6.0.0" }, "engines": { "node": ">=10" @@ -2951,10 +2966,24 @@ } }, "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/ignore": { "version": "4.0.6", @@ -3794,9 +3823,9 @@ } }, "node_modules/libnpmversion": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/libnpmversion/-/libnpmversion-1.0.6.tgz", - "integrity": "sha512-kdE2ilP0swnRZFyuBUGUFDb4NV0mi1rxbdQfFb5rfgT9o5YpifwMH/7LdRnXoAofuIFGy+4BfI2eletqwsNUpg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/libnpmversion/-/libnpmversion-1.0.7.tgz", + "integrity": "sha512-WNJOnu7pqXv66Szz8pBBf7xFdPobd6fRjf1n2wBjmhy1bsQ5Ifkdfsn0UaQE7JffKs5geoAe7JiBQO2hHSQN7A==", "inBundle": true, "dependencies": { "@npmcli/git": "^2.0.1", @@ -4767,9 +4796,9 @@ } }, "node_modules/pacote": { - "version": "11.1.12", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.1.12.tgz", - "integrity": "sha512-suazooYMzefXr3glexAX4+q+qqH3wrzchtj+EivwiCCr/tsaHe9HtdHSx3R8YPjulAhojBZ2JkAVy13QwA8Jpg==", + "version": "11.1.13", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.1.13.tgz", + "integrity": "sha512-oJ7Bg7p3izrIMhZPHCCHmMHQl+xb+pKBXL5ZYeM2oCZrw6sBRSx7f8l7F+95V2qA0BP3c1cNaaBmUNkbo6Hn9w==", "inBundle": true, "dependencies": { "@npmcli/git": "^2.0.1", @@ -4783,7 +4812,7 @@ "minipass": "^3.1.3", "mkdirp": "^1.0.3", "npm-package-arg": "^8.0.1", - "npm-packlist": "^2.1.0", + "npm-packlist": "^2.1.4", "npm-pick-manifest": "^6.0.0", "npm-registry-fetch": "^9.0.0", "promise-retry": "^1.1.1", @@ -4933,9 +4962,9 @@ } }, "node_modules/prebuild-install": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", - "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.0.0.tgz", + "integrity": "sha512-h2ZJ1PXHKWZpp1caLw0oX9sagVpL2YTk+ZwInQbQ3QqNd4J03O6MpFNmMTJlkfgPENWqe5kP0WjQLqz5OjLfsw==", "dev": true, "dependencies": { "detect-libc": "^1.0.3", @@ -7914,15 +7943,15 @@ } }, "node_modules/tar-fs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", - "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dev": true, "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", - "tar-stream": "^2.0.0" + "tar-stream": "^2.1.4" } }, "node_modules/tar-fs/node_modules/chownr": { @@ -9065,13 +9094,14 @@ } }, "@npmcli/arborist": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-1.0.8.tgz", - "integrity": "sha512-LAopKkhAnBr6/cbIpH9VeNS4yLWMFf6AFKC7x3XHvNFDMy8cmvEjWtjcpV8ACjPPm4UbjIzQ/n4qrxaA0ZyBDA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-1.0.9.tgz", + "integrity": "sha512-bvaPKdlT4F0U2JT0eV1fprv9dWdjFxY+O7WbXMvABvyO81kUPTJTBe1HhsGTIqXTrt2cOqXtLJI31Xs7iugptg==", "requires": { "@npmcli/installed-package-contents": "^1.0.5", "@npmcli/map-workspaces": "^1.0.1", "@npmcli/metavuln-calculator": "^1.0.0", + "@npmcli/move-file": "^1.0.1", "@npmcli/name-from-folder": "^1.0.1", "@npmcli/node-gyp": "^1.0.0", "@npmcli/run-script": "^1.7.2", @@ -9477,13 +9507,13 @@ "dev": true }, "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, "buffer-from": { @@ -9670,14 +9700,14 @@ "version": "1.0.4" }, "cmark-gfm": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/cmark-gfm/-/cmark-gfm-0.8.3.tgz", - "integrity": "sha512-DgFD2xlYgO46BQULAFTKvHja2TtnuxJQw3+4msxgRngohIzZR9hrkhqIIWwn/Kad2r/X8C1OQG8PMZwVAsI1vw==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/cmark-gfm/-/cmark-gfm-0.8.4.tgz", + "integrity": "sha512-SzcGygfWYk35SAJ6nO/w8Yng0mMOY4225iwL+joR+WAf/GS5b+bzZdpPeSE66Hrx+QW7NaoZbwjfDPSbqAoF2A==", "dev": true, "requires": { "bindings": "^1.5.0", "node-addon-api": "^3.0.0", - "prebuild-install": "^5.3.5" + "prebuild-install": "^6.0.0" } }, "cmd-shim": { @@ -10913,9 +10943,9 @@ } }, "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true }, "ignore": { @@ -11499,9 +11529,9 @@ } }, "libnpmversion": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/libnpmversion/-/libnpmversion-1.0.6.tgz", - "integrity": "sha512-kdE2ilP0swnRZFyuBUGUFDb4NV0mi1rxbdQfFb5rfgT9o5YpifwMH/7LdRnXoAofuIFGy+4BfI2eletqwsNUpg==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/libnpmversion/-/libnpmversion-1.0.7.tgz", + "integrity": "sha512-WNJOnu7pqXv66Szz8pBBf7xFdPobd6fRjf1n2wBjmhy1bsQ5Ifkdfsn0UaQE7JffKs5geoAe7JiBQO2hHSQN7A==", "requires": { "@npmcli/git": "^2.0.1", "@npmcli/run-script": "^1.2.1", @@ -12186,9 +12216,9 @@ } }, "pacote": { - "version": "11.1.12", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.1.12.tgz", - "integrity": "sha512-suazooYMzefXr3glexAX4+q+qqH3wrzchtj+EivwiCCr/tsaHe9HtdHSx3R8YPjulAhojBZ2JkAVy13QwA8Jpg==", + "version": "11.1.13", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.1.13.tgz", + "integrity": "sha512-oJ7Bg7p3izrIMhZPHCCHmMHQl+xb+pKBXL5ZYeM2oCZrw6sBRSx7f8l7F+95V2qA0BP3c1cNaaBmUNkbo6Hn9w==", "requires": { "@npmcli/git": "^2.0.1", "@npmcli/installed-package-contents": "^1.0.5", @@ -12201,7 +12231,7 @@ "minipass": "^3.1.3", "mkdirp": "^1.0.3", "npm-package-arg": "^8.0.1", - "npm-packlist": "^2.1.0", + "npm-packlist": "^2.1.4", "npm-pick-manifest": "^6.0.0", "npm-registry-fetch": "^9.0.0", "promise-retry": "^1.1.1", @@ -12304,9 +12334,9 @@ } }, "prebuild-install": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", - "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.0.0.tgz", + "integrity": "sha512-h2ZJ1PXHKWZpp1caLw0oX9sagVpL2YTk+ZwInQbQ3QqNd4J03O6MpFNmMTJlkfgPENWqe5kP0WjQLqz5OjLfsw==", "dev": true, "requires": { "detect-libc": "^1.0.3", @@ -14513,15 +14543,15 @@ } }, "tar-fs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", - "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dev": true, "requires": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", - "tar-stream": "^2.0.0" + "tar-stream": "^2.1.4" }, "dependencies": { "chownr": { diff --git a/package.json b/package.json index 1c8461587..5ac2f1253 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "7.0.8", + "version": "7.0.9", "name": "npm", "description": "a package manager for JavaScript", "keywords": [ @@ -42,7 +42,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@npmcli/arborist": "^1.0.8", + "@npmcli/arborist": "^1.0.9", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^1.2.1", "@npmcli/run-script": "^1.7.5", @@ -76,7 +76,7 @@ "libnpmpublish": "^4.0.0", "libnpmsearch": "^3.0.1", "libnpmteam": "^2.0.2", - "libnpmversion": "^1.0.6", + "libnpmversion": "^1.0.7", "make-fetch-happen": "^8.0.9", "mkdirp": "^1.0.4", "mkdirp-infer-owner": "^2.0.0", @@ -92,7 +92,7 @@ "npm-user-validate": "^1.0.1", "npmlog": "~4.1.2", "opener": "^1.5.2", - "pacote": "^11.1.12", + "pacote": "^11.1.13", "parse-conflict-json": "^1.1.1", "qrcode-terminal": "^0.12.0", "read": "~1.0.7", @@ -180,7 +180,7 @@ "write-file-atomic" ], "devDependencies": { - "cmark-gfm": "^0.8.3", + "cmark-gfm": "^0.8.4", "eslint": "^7.12.1", "eslint-plugin-import": "^2.22.1", "eslint-plugin-node": "^11.1.0", diff --git a/scripts/install.sh b/scripts/install.sh index 7f66151da..4458de87f 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -8,7 +8,7 @@ # shell living at /bin/sh. # # See this helpful document on writing portable shell scripts: -# https://www.gnu.org/s/hello/manual/autoconf/Portable-Shell.html +# http://www.gnu.org/s/hello/manual/autoconf/Portable-Shell.html # # The only shell it won't ever work on is cmd.exe. @@ -23,32 +23,27 @@ if [ "x$0" = "xsh" ]; then if [ $ret -eq 0 ]; then (exit 0) else - echo "Uninstalling npm-install-$$.sh" >&2 rm npm-install-$$.sh - echo "Failed to download script" >&2 + echo "failed to download script" >&2 exit $ret fi sh npm-install-$$.sh ret=$? - echo "Uninstalling npm-install-$$.sh" >&2 rm npm-install-$$.sh exit $ret fi -# See what "npm_config_*" things there are in the env, -# and make them permanent. -# If this fails, it's not such a big deal. -configures="`env | grep 'npm_config_' | sed -e 's|^npm_config_||g'`" - +debug=0 npm_config_loglevel="error" if [ "x$npm_debug" = "x" ]; then (exit 0) else - echo "Running in debug mode." - echo "Note that this requires bash or zsh." + echo "running in debug mode." + echo "note that this requires bash or zsh." set -o xtrace set -o pipefail npm_config_loglevel="verbose" + debug=1 fi export npm_config_loglevel @@ -61,33 +56,20 @@ if [ $ret -ne 0 ]; then ret=$? fi if [ $ret -eq 0 ] && [ -x "$node" ]; then + if [ $debug -eq 1 ]; then + echo "found 'node' at: $node" + echo -n "version: " + $node --version + echo "" + fi (exit 0) else echo "npm cannot be installed without node.js." >&2 - echo "Install node first, and then try again." >&2 + echo "install node first, and then try again." >&2 echo "" >&2 - echo "Maybe node is installed, but not in the PATH?" >&2 - echo "Note that running as sudo can change envs." >&2 - echo "" - echo "PATH=$PATH" >&2 exit $ret fi -# set the temp dir -TMP="${TMPDIR}" -if [ "x$TMP" = "x" ]; then - TMP="/tmp" -fi -TMP="${TMP}/npm.$$" -rm -rf "$TMP" || true -mkdir "$TMP" -if [ $? -ne 0 ]; then - echo "failed to mkdir $TMP" >&2 - exit 1 -fi - -BACK="$PWD" - ret=0 tar="${TAR}" if [ -z "$tar" ]; then @@ -99,10 +81,11 @@ if [ -z "$tar" ]; then fi if [ $ret -eq 0 ] && [ -x "$tar" ]; then - echo "tar=$tar" - if [ $tar --version > /dev/null 2>&1 ]; then - echo "version:" + if [ $debug -eq 1 ]; then + echo "found 'tar' at: $tar" + echo -n "version: " $tar --version + echo "" fi ret=$? fi @@ -110,76 +93,43 @@ fi if [ $ret -eq 0 ]; then (exit 0) else - echo "No suitable tar program found." + echo "this script requires 'tar', please install it and try again." exit 1 fi - - -# Try to find a suitable make -# If the MAKE environment var is set, use that. -# otherwise, try to find gmake, and then make. -# If no make is found, then just execute the necessary commands. - -# XXX For some reason, make is building all the docs every time. This -# is an annoying source of bugs. Figure out why this happens. -MAKE=NOMAKE - -if [ "x$MAKE" = "x" ]; then - make=`which gmake 2>&1` - if [ $? -eq 0 ] && [ -x "$make" ]; then - (exit 0) - else - make=`which make 2>&1` - if [ $? -eq 0 ] && [ -x "$make" ]; then - (exit 0) - else - make=NOMAKE - fi +curl=`which curl 2>&1` +ret=$? +if [ $ret -eq 0 ]; then + if [ $debug -eq 1 ]; then + echo "found 'curl' at: $curl" + echo -n "version: " + $curl --version | head -n 1 + echo "" fi -else - make="$MAKE" -fi - -if [ -x "$make" ]; then (exit 0) else - # echo "Installing without make. This may fail." >&2 - make=NOMAKE + echo "this script requires 'curl', please install it and try again." + exit 1 fi -# If there's no bash, then don't even try to clean -if [ -x "/bin/bash" ]; then - (exit 0) -else - clean="no" +# set the temp dir +TMP="${TMPDIR}" +if [ "x$TMP" = "x" ]; then + TMP="/tmp" fi - -node_version=`"$node" --version 2>&1` -ret=$? -if [ $ret -ne 0 ]; then - echo "You need node to run this program." >&2 - echo "node --version reports: $node_version" >&2 - echo "with exit code = $ret" >&2 - echo "Please install node before continuing." >&2 - exit $ret +TMP="${TMP}/npm.$$" +rm -rf "$TMP" || true +mkdir "$TMP" +if [ $? -ne 0 ]; then + echo "failed to mkdir $TMP" >&2 + exit 1 fi +BACK="$PWD" + t="${npm_install}" if [ -z "$t" ]; then - # switch based on node version. - # note that we can only use strict sh-compatible patterns here. - case $node_version in - 0.[01234567].* | v0.[01234567].*) - echo "You are using an outdated and unsupported version of" >&2 - echo "node ($node_version). Please update node and try again." >&2 - exit 99 - ;; - *) - echo "install npm@latest" - t="latest" - ;; - esac + t="latest" fi # need to echo "" after, because Posix sed doesn't treat EOF @@ -201,7 +151,7 @@ if [ "x$url" = "x" ]; then fi fi if [ $ret -ne 0 ]; then - echo "Failed to get tarball url for npm/$t" >&2 + echo "failed to get tarball url for npm/$t" >&2 exit $ret fi @@ -209,37 +159,19 @@ fi echo "fetching: $url" >&2 cd "$TMP" \ - && curl -SsL "$url" \ - | $tar -xzf - \ - && cd "$TMP"/* \ - && (ret=0 - if [ $ret -ne 0 ]; then - echo "Aborted 0.x cleanup. Exiting." >&2 - exit $ret - fi) \ - && (if [ "x$configures" = "x" ]; then - (exit 0) - else - echo "./configure $configures" - echo "$configures" > npmrc - fi) \ - && (if [ "$make" = "NOMAKE" ]; then - (exit 0) - elif "$make" uninstall install; then - (exit 0) - else - make="NOMAKE" - fi - if [ "$make" = "NOMAKE" ]; then - "$node" bin/npm-cli.js rm npm -gf - "$node" bin/npm-cli.js install -gf $("$node" bin/npm-cli.js pack | tail -1) - fi) \ + && curl -SsL -o npm.tgz "$url" \ + && $tar -xzf npm.tgz \ + && cd "$TMP"/package \ + && echo "removing existing npm" \ + && "$node" bin/npm-cli.js rm npm -gf --loglevel=silent \ + && echo "installing npm@$t" \ + && "$node" bin/npm-cli.js install -gf ../npm.tgz \ && cd "$BACK" \ && rm -rf "$TMP" \ - && echo "It worked" + && echo "successfully installed npm@$t" ret=$? if [ $ret -ne 0 ]; then - echo "It failed" >&2 + echo "failed!" >&2 fi exit $ret diff --git a/test/lib/adduser.js b/test/lib/adduser.js index 4d2233b18..22c7c49cf 100644 --- a/test/lib/adduser.js +++ b/test/lib/adduser.js @@ -13,6 +13,7 @@ const _flatOptions = { let failSave = false let deletedConfig = {} +let registryOutput = '' let setConfig = {} const authDummy = () => Promise.resolve({ message: 'success', @@ -32,7 +33,10 @@ const deleteMock = (key, where) => { } const adduser = requireInject('../../lib/adduser.js', { npmlog: { - disableProgress: () => null + disableProgress: () => null, + notice: (_, msg) => { + registryOutput = msg + }, }, '../../lib/npm.js': { flatOptions: _flatOptions, @@ -69,6 +73,12 @@ test('simple login', (t) => { adduser([], (err) => { t.ifError(err, 'npm adduser') + t.equal( + registryOutput, + 'Log in on https://registry.npmjs.org/', + 'should have correct message result' + ) + t.deepEqual( deletedConfig, { @@ -102,6 +112,7 @@ test('simple login', (t) => { 'should output auth success msg' ) + registryOutput = '' deletedConfig = {} setConfig = {} result = '' diff --git a/test/lib/cache.js b/test/lib/cache.js new file mode 100644 index 000000000..9c27386ed --- /dev/null +++ b/test/lib/cache.js @@ -0,0 +1,232 @@ +const t = require('tap') +const requireInject = require('require-inject') +const path = require('path') + +const usageUtil = () => 'usage instructions' + +const flatOptions = { + force: false +} + +const npm = { + flatOptions, + cache: '/fake/path' +} + +let rimrafPath = '' +const rimraf = (path, cb) => { + rimrafPath = path + return cb() +} + +let logOutput = [] +const npmlog = { + silly: (...args) => { + logOutput.push(['silly', ...args]) + } +} + +let tarballStreamSpec = '' +let tarballStreamOpts = {} +const pacote = { + tarball: { + stream: (spec, cb, opts) => { + tarballStreamSpec = spec + tarballStreamOpts = opts + return cb({ + resume: () => {}, + promise: () => Promise.resolve() + }) + } + } +} + +let outputOutput = [] +const output = (msg) => { + outputOutput.push(msg) +} + +let cacacheVerifyPath = '' +const cacacheVerifyStats = { + keptSize: 100, + verifiedContent: 1, + totalEntries: 1, + runTime: { total: 2000 } +} +const cacache = { + verify: (path) => { + cacacheVerifyPath = path + return cacacheVerifyStats + } +} + +const mocks = { + cacache, + npmlog, + pacote, + rimraf, + '../../lib/npm.js': npm, + '../../lib/utils/output.js': output, + '../../lib/utils/usage.js': usageUtil +} + +const cache = requireInject('../../lib/cache.js', mocks) + +t.test('cache no args', t => { + cache([], err => { + t.equal(err.message, 'usage instructions', 'should throw usage instructions') + t.end() + }) +}) + +t.test('cache clean', t => { + cache(['clean'], err => { + t.match(err.message, 'the npm cache self-heals', 'should throw warning') + t.end() + }) +}) + +t.test('cache clean (force)', t => { + flatOptions.force = true + t.teardown(() => { + rimrafPath = '' + flatOptions.force = false + }) + + cache(['clear'], err => { + t.ifError(err) + t.equal(rimrafPath, path.join(npm.cache, '_cacache')) + t.end() + }) +}) + +t.test('cache clean with arg', t => { + cache(['rm', 'pkg'], err => { + t.match(err.message, 'does not accept arguments', 'should throw error') + t.end() + }) +}) + +t.test('cache add no arg', t => { + t.teardown(() => { + logOutput = [] + }) + + cache(['add'], err => { + t.strictSame(logOutput, [ + ['silly', 'cache add', 'args', []], + ], 'logs correctly') + t.equal(err.code, 'EUSAGE', 'throws usage error') + t.end() + }) +}) + +t.test('cache add pkg only', t => { + t.teardown(() => { + logOutput = [] + tarballStreamSpec = '' + tarballStreamOpts = {} + }) + + cache(['add', 'mypkg'], err => { + t.ifError(err) + t.strictSame(logOutput, [ + ['silly', 'cache add', 'args', ['mypkg']], + ['silly', 'cache add', 'spec', 'mypkg'] + ], 'logs correctly') + t.equal(tarballStreamSpec, 'mypkg', 'passes the correct spec to pacote') + t.same(tarballStreamOpts, flatOptions, 'passes the correct options to pacote') + t.end() + }) +}) + +t.test('cache add pkg w/ spec modifier', t => { + t.teardown(() => { + logOutput = [] + tarballStreamSpec = '' + tarballStreamOpts = {} + }) + + cache(['add', 'mypkg', 'latest'], err => { + t.ifError(err) + t.strictSame(logOutput, [ + ['silly', 'cache add', 'args', ['mypkg', 'latest']], + ['silly', 'cache add', 'spec', 'mypkg@latest'] + ], 'logs correctly') + t.equal(tarballStreamSpec, 'mypkg@latest', 'passes the correct spec to pacote') + t.same(tarballStreamOpts, flatOptions, 'passes the correct options to pacote') + t.end() + }) +}) + +t.test('cache verify', t => { + t.teardown(() => { + outputOutput = [] + cacacheVerifyPath = '' + }) + + cache(['verify'], err => { + t.ifError(err) + t.match(outputOutput, [ + `Cache verified and compressed (${path.join(npm.cache, '_cacache')})`, + 'Content verified: 1 (100 bytes)', + 'Index entries: 1', + 'Finished in 2s' + ], 'prints correct output') + t.end() + }) +}) + +t.test('cache verify w/ extra output', t => { + npm.cache = `${process.env.HOME}/fake/path` + cacacheVerifyStats.badContentCount = 1 + cacacheVerifyStats.reclaimedCount = 2 + cacacheVerifyStats.reclaimedSize = 200 + cacacheVerifyStats.missingContent = 3 + t.teardown(() => { + npm.cache = '/fake/path' + outputOutput = [] + cacacheVerifyPath = '' + delete cacacheVerifyStats.badContentCount + delete cacacheVerifyStats.reclaimedCount + delete cacacheVerifyStats.reclaimedSize + delete cacacheVerifyStats.missingContent + }) + + cache(['check'], err => { + t.ifError(err) + t.match(outputOutput, [ + `Cache verified and compressed (~${path.join('/fake/path', '_cacache')})`, + 'Content verified: 1 (100 bytes)', + 'Corrupted content removed: 1', + 'Content garbage-collected: 2 (200 bytes)', + 'Missing content: 3', + 'Index entries: 1', + 'Finished in 2s' + ], 'prints correct output') + t.end() + }) +}) + +t.test('cache completion', t => { + const { completion } = cache + + const testComp = (argv, expect) => { + completion({ conf: { argv: { remain: argv } } }, (err, res) => { + t.ifError(err) + t.strictSame(res, expect, argv.join(' ')) + }) + } + + testComp(['npm', 'cache'], [ + 'add', + 'clean', + 'verify' + ]) + + testComp(['npm', 'cache', 'add'], []) + testComp(['npm', 'cache', 'clean'], []) + testComp(['npm', 'cache', 'verify'], []) + + t.end() +}) |