diff --git a/AUTHORS b/AUTHORS index c3685720598a9..a0999c732f232 100644 --- a/AUTHORS +++ b/AUTHORS @@ -789,3 +789,5 @@ Aluneed <31174087+aluneed@users.noreply.github.com> relrelb Cameron Tacklind Demira Dimitrova +AkiJoey +austincho diff --git a/CHANGELOG.md b/CHANGELOG.md index c36045f27b683..d3f915d6a0ee1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,40 @@ +## v7.20.6 (2021-08-12) + +### DEPENDENCIES + +* [`5bebf280f`](https://github.com/npm/cli/commit/5bebf280f228e818524f6989caab1cfba1ffaf90) + `tar@6.1.8` + * fix: reserve paths case-insensitively +* [`5d89de44d`](https://github.com/npm/cli/commit/5d89de44daa636dc151eaefcafabb357540d35ce) + `tar@6.1.7`: + * fix: normalize paths on Windows systems +* [`a1bdbea97`](https://github.com/npm/cli/commit/a1bdbea974ebfc6694b4c8ad5da86215c2924dde) + [#3569](https://github.com/npm/cli/issues/3569) + * remove byte-size + ([@wraithgar](https://github.com/wraithgar)) +* [`61782fa85`](https://github.com/npm/cli/commit/61782fa858c278455ce144f975c6b0e3ea2d9944) + `@npmcli/map-workspaces@1.0.4`: + * fix: better error message for duplicate workspace names +* [`b88f770fa`](https://github.com/npm/cli/commit/b88f770faa2651ca0833e1c9eb361e9e07e0bbc3) + `@npmcli/arborist@2.8.1`: + * [#3632] Fix "cannot read property path of null" error in 'npm dedupe' + * fix(shrinkwrap): always set name on the root node + +### DOCUMENTATION + +* [`001f2c1b7`](https://github.com/npm/cli/commit/001f2c1b7e9474049a45709f0e80ee3c474a4ba9) + [#3621](https://github.com/npm/cli/issues/3621) + fix(docs): do not include certain files + ([@AkiJoey](https://github.com/AkiJoey)) +* [`d1812f1a6`](https://github.com/npm/cli/commit/d1812f1a627d6a4d4cb6d07d7735d2d2cc2cf264) + [#3630](https://github.com/npm/cli/issues/3630) + fix(docs): update npm-publish access flag info + ([@austincho](https://github.com/austincho)) +* [`d5a099c7b`](https://github.com/npm/cli/commit/d5a099c7bf62977a5a5d8242c61f323a88e27c73) + [#3615](https://github.com/npm/cli/issues/3615) + fix(readme): add nvm-windows to installers links + ([@Yash-Singh1](https://github.com/Yash-Singh1)) + ## v7.20.5 (2021-08-05) ### DEPENDENCIES diff --git a/README.md b/README.md index 01de9e8f69445..822cdecc29294 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ If you're looking to manage multiple versions of **`node`** &/or **`npm`**, cons * [**`volta`**](https://github.com/volta-cli/volta) * [**`nodenv`**](https://github.com/nodenv/nodenv) * [**`asdf-nodejs`**](https://github.com/asdf-vm/asdf-nodejs) +* [**`nvm-windows`**](https://github.com/coreybutler/nvm-windows) ### Usage diff --git a/docs/content/commands/npm-publish.md b/docs/content/commands/npm-publish.md index 0d25d7d29da8d..9eb060a78be29 100644 --- a/docs/content/commands/npm-publish.md +++ b/docs/content/commands/npm-publish.md @@ -132,6 +132,11 @@ If you want your scoped package to be publicly viewable (and installable) set `--access=public`. The only valid values for `access` are `public` and `restricted`. Unscoped packages _always_ have an access level of `public`. +Note: Using the `--access` flag on the `npm publish` command will only set +the package access level on the initial publish of the package. Any subsequent `npm publish` +commands using the `--access` flag will not have an effect to the access level. +To make changes to the access level after the initial publish use `npm access`. + #### `dry-run` * Default: false diff --git a/docs/content/configuring-npm/package-json.md b/docs/content/configuring-npm/package-json.md index 0fc5dc5075ee3..856adb3366cb0 100644 --- a/docs/content/configuring-npm/package-json.md +++ b/docs/content/configuring-npm/package-json.md @@ -286,12 +286,10 @@ Certain files are always included, regardless of settings: * `package.json` * `README` -* `CHANGES` / `CHANGELOG` / `HISTORY` * `LICENSE` / `LICENCE` -* `NOTICE` * The file in the "main" field -`README`, `CHANGES`, `LICENSE` & `NOTICE` can have any case and extension. +`README` & `LICENSE` can have any case and extension. Conversely, some files are always ignored: diff --git a/lib/utils/format-bytes.js b/lib/utils/format-bytes.js new file mode 100644 index 0000000000000..87fb561aabef1 --- /dev/null +++ b/lib/utils/format-bytes.js @@ -0,0 +1,22 @@ +// Convert bytes to printable output, for file reporting in tarballs +// Only supports up to GB because that's way larger than anything the registry +// supports anyways. + +const formatBytes = (bytes, space = true) => { + let spacer = '' + if (space) + spacer = ' ' + + if (bytes < 1000) // B + return `${bytes}${spacer}B` + + if (bytes < 1000000) // kB + return `${(bytes / 1000).toFixed(1)}${spacer}kB` + + if (bytes < 1000000000) // MB + return `${(bytes / 1000000).toFixed(1)}${spacer}MB` + + return `${(bytes / 1000000000).toFixed(1)}${spacer}GB` +} + +module.exports = formatBytes diff --git a/lib/utils/tar.js b/lib/utils/tar.js index 9e7c3329530ee..c3071c1bd47a5 100644 --- a/lib/utils/tar.js +++ b/lib/utils/tar.js @@ -1,7 +1,7 @@ const tar = require('tar') const ssri = require('ssri') const npmlog = require('npmlog') -const byteSize = require('byte-size') +const formatBytes = require('./format-bytes.js') const columnify = require('columnify') const logTar = (tarball, opts = {}) => { @@ -11,9 +11,9 @@ const logTar = (tarball, opts = {}) => { log.notice('=== Tarball Contents ===') if (tarball.files.length) { log.notice('', columnify(tarball.files.map((f) => { - const bytes = byteSize(f.size) + const bytes = formatBytes(f.size, false) return (/^node_modules\//.test(f.path)) ? null - : { path: f.path, size: `${bytes.value}${bytes.unit}` } + : { path: f.path, size: `${bytes}` } }).filter(f => f), { include: ['size', 'path'], showHeaders: false, @@ -28,8 +28,8 @@ const logTar = (tarball, opts = {}) => { { name: 'name:', value: tarball.name }, { name: 'version:', value: tarball.version }, tarball.filename && { name: 'filename:', value: tarball.filename }, - { name: 'package size:', value: byteSize(tarball.size) }, - { name: 'unpacked size:', value: byteSize(tarball.unpackedSize) }, + { name: 'package size:', value: formatBytes(tarball.size) }, + { name: 'unpacked size:', value: formatBytes(tarball.unpackedSize) }, { name: 'shasum:', value: tarball.shasum }, { name: 'integrity:', diff --git a/lib/view.js b/lib/view.js index 47e631f5565c0..f4fc5974eeeca 100644 --- a/lib/view.js +++ b/lib/view.js @@ -1,6 +1,5 @@ // npm view [pkg [pkg ...]] -const byteSize = require('byte-size') const color = require('ansicolors') const columns = require('cli-columns') const fs = require('fs') @@ -8,6 +7,7 @@ const jsonParse = require('json-parse-even-better-errors') const log = require('npmlog') const npa = require('npm-package-arg') const { resolve } = require('path') +const formatBytes = require('./utils/format-bytes.js') const relativeDate = require('tiny-relative-date') const semver = require('semver') const style = require('ansistyles') @@ -315,7 +315,7 @@ class View extends BaseCommand { tags.push(`${style.bright(color.green(t))}: ${version}`) }) const unpackedSize = manifest.dist.unpackedSize && - byteSize(manifest.dist.unpackedSize) + formatBytes(manifest.dist.unpackedSize, true) const licenseField = manifest.license || 'Proprietary' const info = { name: color.green(manifest.name), @@ -356,7 +356,7 @@ class View extends BaseCommand { manifest.dist.integrity && color.yellow(manifest.dist.integrity), fileCount: manifest.dist.fileCount && color.yellow(manifest.dist.fileCount), - unpackedSize: unpackedSize && color.yellow(unpackedSize.value) + ' ' + unpackedSize.unit, + unpackedSize: unpackedSize && color.yellow(unpackedSize), } if (info.license.toLowerCase().trim() === 'proprietary') info.license = style.bright(color.red(info.license)) diff --git a/node_modules/@npmcli/arborist/bin/dedupe.js b/node_modules/@npmcli/arborist/bin/dedupe.js new file mode 100644 index 0000000000000..96f754e34ca9e --- /dev/null +++ b/node_modules/@npmcli/arborist/bin/dedupe.js @@ -0,0 +1,46 @@ +const Arborist = require('../') + +const options = require('./lib/options.js') +const print = require('./lib/print-tree.js') +require('./lib/logging.js') +require('./lib/timers.js') + +const printDiff = diff => { + const {depth} = require('treeverse') + depth({ + tree: diff, + visit: d => { + if (d.location === '') + return + switch (d.action) { + case 'REMOVE': + console.error('REMOVE', d.actual.location) + break + case 'ADD': + console.error('ADD', d.ideal.location, d.ideal.resolved) + break + case 'CHANGE': + console.error('CHANGE', d.actual.location, { + from: d.actual.resolved, + to: d.ideal.resolved, + }) + break + } + }, + getChildren: d => d.children, + }) +} + +const start = process.hrtime() +process.emit('time', 'install') +const arb = new Arborist(options) +arb.dedupe(options).then(tree => { + process.emit('timeEnd', 'install') + const end = process.hrtime(start) + print(tree) + if (options.dryRun) + printDiff(arb.diff) + console.error(`resolved ${tree.inventory.size} deps in ${end[0] + end[1] / 1e9}s`) + if (tree.meta && options.save) + tree.meta.save() +}).catch(er => console.error(require('util').inspect(er, { depth: Infinity }))) 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 7ef42289d297b..679d52582cb25 100644 --- a/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js +++ b/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js @@ -982,7 +982,6 @@ This is a one-time fix-up, please be patient... // Note that the virtual root will also have virtual copies of the // targets of any child Links, so that they resolve appropriately. const parent = parent_ || this[_virtualRoot](edge.from) - const realParent = edge.peer ? edge.from.resolveParent : edge.from const spec = npa.resolve(edge.name, edge.spec, edge.from.path) const first = await this[_nodeFromSpec](edge.name, spec, parent, edge) @@ -1013,16 +1012,6 @@ This is a one-time fix-up, please be patient... required.has(secondEdge.from) && secondEdge.type !== 'peerOptional')) required.add(node) - // handle otherwise unresolvable dependency nesting loops by - // creating a symbolic link - // a1 -> b1 -> a2 -> b2 -> a1 -> ... - // instead of nesting forever, when the loop occurs, create - // a symbolic link to the earlier instance - for (let p = edge.from.resolveParent; p; p = p.resolveParent) { - if (p.matches(node) && !p.isTop) - return new Link({ parent: realParent, target: p }) - } - // keep track of the thing that caused this node to be included. const src = parent.sourceReference this[_peerSetSource].set(node, src) diff --git a/node_modules/@npmcli/arborist/lib/can-place-dep.js b/node_modules/@npmcli/arborist/lib/can-place-dep.js index cf6b800c44ea2..9601ad7af3163 100644 --- a/node_modules/@npmcli/arborist/lib/can-place-dep.js +++ b/node_modules/@npmcli/arborist/lib/can-place-dep.js @@ -73,8 +73,10 @@ class CanPlaceDep { if (!edge) throw new Error('no edge provided to CanPlaceDep') - this._nodeSnapshot = JSON.stringify(dep) - this._treeSnapshot = JSON.stringify(target.root) + this._treeSnapshot = JSON.stringify([...target.root.inventory.entries()] + .map(([loc, {packageName, version, resolved}]) => { + return [loc, packageName, version, resolved] + }).sort(([a], [b]) => a.localeCompare(b, 'en'))) }) // the result of whether we can place it or not @@ -110,15 +112,10 @@ class CanPlaceDep { this.canPlaceSelf = this.canPlace debug(() => { - const nodeSnapshot = JSON.stringify(dep) - const treeSnapshot = JSON.stringify(target.root) - /* istanbul ignore if */ - if (this._nodeSnapshot !== nodeSnapshot) { - throw Object.assign(new Error('dep changed in CanPlaceDep'), { - expect: this._nodeSnapshot, - actual: nodeSnapshot, - }) - } + const treeSnapshot = JSON.stringify([...target.root.inventory.entries()] + .map(([loc, {packageName, version, resolved}]) => { + return [loc, packageName, version, resolved] + }).sort(([a], [b]) => a.localeCompare(b, 'en'))) /* istanbul ignore if */ if (this._treeSnapshot !== treeSnapshot) { throw Object.assign(new Error('tree changed in CanPlaceDep'), { diff --git a/node_modules/@npmcli/arborist/lib/place-dep.js b/node_modules/@npmcli/arborist/lib/place-dep.js index 913b2ba6c2bc7..c0023e74ad8ea 100644 --- a/node_modules/@npmcli/arborist/lib/place-dep.js +++ b/node_modules/@npmcli/arborist/lib/place-dep.js @@ -16,6 +16,7 @@ const { } = CanPlaceDep const debug = require('./debug.js') +const Link = require('./link.js') const gatherDepSet = require('./gather-dep-set.js') const peerEntrySets = require('./peer-entry-sets.js') @@ -256,6 +257,20 @@ class PlaceDep { return } + // we were told to place it here in the target, so either it does not + // already exist in the tree, OR it's shadowed. + // handle otherwise unresolvable dependency nesting loops by + // creating a symbolic link + // a1 -> b1 -> a2 -> b2 -> a1 -> ... + // instead of nesting forever, when the loop occurs, create + // a symbolic link to the earlier instance + for (let p = target; p; p = p.resolveParent) { + if (p.matches(dep) && !p.isTop) { + this.placed = new Link({ parent: target, target: p }) + return + } + } + // XXX if we are replacing SOME of a peer entry group, we will need to // remove any that are not being replaced and will now be invalid, and // re-evaluate them deeper into the tree. @@ -268,7 +283,7 @@ class PlaceDep { integrity: dep.integrity, legacyPeerDeps: this.legacyPeerDeps, error: dep.errors[0], - ...(dep.isLink ? { target: dep.target, realpath: dep.target.path } : {}), + ...(dep.isLink ? { target: dep.target, realpath: dep.realpath } : {}), }) this.oldDep = target.children.get(this.name) diff --git a/node_modules/@npmcli/arborist/lib/shrinkwrap.js b/node_modules/@npmcli/arborist/lib/shrinkwrap.js index ebbe004de72d6..83cb1f66f3a10 100644 --- a/node_modules/@npmcli/arborist/lib/shrinkwrap.js +++ b/node_modules/@npmcli/arborist/lib/shrinkwrap.js @@ -255,9 +255,11 @@ class Shrinkwrap { if (val) meta[key.replace(/^_/, '')] = val }) - // we only include name if different from the node path name + // we only include name if different from the node path name, and for the + // root to help prevent churn based on the name of the directory the + // project is in const pname = node.packageName - if (pname && pname !== node.name) + if (pname && (node === node.root || pname !== node.name)) meta.name = pname if (node.isTop && node.package.devDependencies) diff --git a/node_modules/@npmcli/arborist/package.json b/node_modules/@npmcli/arborist/package.json index 56046eaa5f357..01f018a629339 100644 --- a/node_modules/@npmcli/arborist/package.json +++ b/node_modules/@npmcli/arborist/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/arborist", - "version": "2.8.0", + "version": "2.8.1", "description": "Manage node_modules trees", "dependencies": { "@npmcli/installed-package-contents": "^1.0.7", diff --git a/node_modules/@npmcli/map-workspaces/index.js b/node_modules/@npmcli/map-workspaces/index.js index b06662154a83a..7587db717f362 100644 --- a/node_modules/@npmcli/map-workspaces/index.js +++ b/node_modules/@npmcli/map-workspaces/index.js @@ -129,7 +129,12 @@ async function mapWorkspaces (opts = {}) { if (seen.has(name) && seen.get(name) !== packagePathname) { throw getError({ Type: Error, - message: 'must not have multiple workspaces with the same name', + message: [ + 'must not have multiple workspaces with the same name', + `package '${name}' has conflicts in the following paths:`, + ' ' + seen.get(name), + ' ' + packagePathname + ].join('\n'), code: 'EDUPLICATEWORKSPACE' }) } diff --git a/node_modules/@npmcli/map-workspaces/package.json b/node_modules/@npmcli/map-workspaces/package.json index 2445c12f9c308..17cc4197e9e2b 100644 --- a/node_modules/@npmcli/map-workspaces/package.json +++ b/node_modules/@npmcli/map-workspaces/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/map-workspaces", - "version": "1.0.3", + "version": "1.0.4", "files": [ "index.js" ], diff --git a/node_modules/byte-size/LICENSE b/node_modules/byte-size/LICENSE deleted file mode 100644 index 5699dfbe51830..0000000000000 --- a/node_modules/byte-size/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014-21 Lloyd Brookes <75pound@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/node_modules/byte-size/dist/index.js b/node_modules/byte-size/dist/index.js deleted file mode 100644 index dd1debda59abd..0000000000000 --- a/node_modules/byte-size/dist/index.js +++ /dev/null @@ -1,123 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.byteSize = factory()); -}(this, (function () { 'use strict'; - - /** - * @module byte-size - */ - - let defaultOptions = {}; - const _options = new WeakMap(); - - class ByteSize { - constructor (bytes, options) { - options = Object.assign({ - units: 'metric', - precision: 1 - }, defaultOptions, options); - _options.set(this, options); - - const tables = { - metric: [ - { from: 0 , to: 1e3 , unit: 'B' , long: 'bytes' }, - { from: 1e3 , to: 1e6 , unit: 'kB', long: 'kilobytes' }, - { from: 1e6 , to: 1e9 , unit: 'MB', long: 'megabytes' }, - { from: 1e9 , to: 1e12, unit: 'GB', long: 'gigabytes' }, - { from: 1e12, to: 1e15, unit: 'TB', long: 'terabytes' }, - { from: 1e15, to: 1e18, unit: 'PB', long: 'petabytes' }, - { from: 1e18, to: 1e21, unit: 'EB', long: 'exabytes' }, - { from: 1e21, to: 1e24, unit: 'ZB', long: 'zettabytes' }, - { from: 1e24, to: 1e27, unit: 'YB', long: 'yottabytes' }, - ], - metric_octet: [ - { from: 0 , to: 1e3 , unit: 'o' , long: 'octets' }, - { from: 1e3 , to: 1e6 , unit: 'ko', long: 'kilooctets' }, - { from: 1e6 , to: 1e9 , unit: 'Mo', long: 'megaoctets' }, - { from: 1e9 , to: 1e12, unit: 'Go', long: 'gigaoctets' }, - { from: 1e12, to: 1e15, unit: 'To', long: 'teraoctets' }, - { from: 1e15, to: 1e18, unit: 'Po', long: 'petaoctets' }, - { from: 1e18, to: 1e21, unit: 'Eo', long: 'exaoctets' }, - { from: 1e21, to: 1e24, unit: 'Zo', long: 'zettaoctets' }, - { from: 1e24, to: 1e27, unit: 'Yo', long: 'yottaoctets' }, - ], - iec: [ - { from: 0 , to: Math.pow(1024, 1), unit: 'B' , long: 'bytes' }, - { from: Math.pow(1024, 1), to: Math.pow(1024, 2), unit: 'KiB', long: 'kibibytes' }, - { from: Math.pow(1024, 2), to: Math.pow(1024, 3), unit: 'MiB', long: 'mebibytes' }, - { from: Math.pow(1024, 3), to: Math.pow(1024, 4), unit: 'GiB', long: 'gibibytes' }, - { from: Math.pow(1024, 4), to: Math.pow(1024, 5), unit: 'TiB', long: 'tebibytes' }, - { from: Math.pow(1024, 5), to: Math.pow(1024, 6), unit: 'PiB', long: 'pebibytes' }, - { from: Math.pow(1024, 6), to: Math.pow(1024, 7), unit: 'EiB', long: 'exbibytes' }, - { from: Math.pow(1024, 7), to: Math.pow(1024, 8), unit: 'ZiB', long: 'zebibytes' }, - { from: Math.pow(1024, 8), to: Math.pow(1024, 9), unit: 'YiB', long: 'yobibytes' }, - ], - iec_octet: [ - { from: 0 , to: Math.pow(1024, 1), unit: 'o' , long: 'octets' }, - { from: Math.pow(1024, 1), to: Math.pow(1024, 2), unit: 'Kio', long: 'kibioctets' }, - { from: Math.pow(1024, 2), to: Math.pow(1024, 3), unit: 'Mio', long: 'mebioctets' }, - { from: Math.pow(1024, 3), to: Math.pow(1024, 4), unit: 'Gio', long: 'gibioctets' }, - { from: Math.pow(1024, 4), to: Math.pow(1024, 5), unit: 'Tio', long: 'tebioctets' }, - { from: Math.pow(1024, 5), to: Math.pow(1024, 6), unit: 'Pio', long: 'pebioctets' }, - { from: Math.pow(1024, 6), to: Math.pow(1024, 7), unit: 'Eio', long: 'exbioctets' }, - { from: Math.pow(1024, 7), to: Math.pow(1024, 8), unit: 'Zio', long: 'zebioctets' }, - { from: Math.pow(1024, 8), to: Math.pow(1024, 9), unit: 'Yio', long: 'yobioctets' }, - ], - }; - Object.assign(tables, options.customUnits); - - const prefix = bytes < 0 ? '-' : ''; - bytes = Math.abs(bytes); - const table = tables[options.units]; - if (table) { - const units = table.find(u => bytes >= u.from && bytes < u.to); - if (units) { - const value = units.from === 0 - ? prefix + bytes - : prefix + (bytes / units.from).toFixed(options.precision); - this.value = value; - this.unit = units.unit; - this.long = units.long; - } else { - this.value = prefix + bytes; - this.unit = ''; - this.long = ''; - } - } else { - throw new Error(`Invalid units specified: ${options.units}`) - } - } - - toString () { - const options = _options.get(this); - return options.toStringFn ? options.toStringFn.bind(this)() : `${this.value} ${this.unit}` - } - } - - /** - * Returns an object with the spec `{ value: string, unit: string, long: string }`. The returned object defines a `toString` method meaning it can be used in any string context. - * @param {number} - The bytes value to convert. - * @param [options] {object} - Optional config. - * @param [options.precision] {number} - Number of decimal places. Defaults to `1`. - * @param [options.units] {string} - Specify `'metric'`, `'iec'`, `'metric_octet'`, `'iec_octet'` or the name of a property from the custom units table in `options.customUnits`. Defaults to `metric`. - * @param [options.customUnits] {object} - An object containing one or more custom unit lookup tables. - * @param [options.toStringFn] {function} - A `toString` function to override the default. - * @returns {object} - * @alias module:byte-size - */ - function byteSize (bytes, options) { - return new ByteSize(bytes, options) - } - - /** - * Set the default `byteSize` options for the duration of the process. - * @param options {object} - A `byteSize` options object. - */ - byteSize.defaultOptions = function (options) { - defaultOptions = options; - }; - - return byteSize; - -}))); diff --git a/node_modules/byte-size/index.mjs b/node_modules/byte-size/index.mjs deleted file mode 100644 index bd6548c686aa5..0000000000000 --- a/node_modules/byte-size/index.mjs +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @module byte-size - */ - -let defaultOptions = {} -const _options = new WeakMap() - -class ByteSize { - constructor (bytes, options) { - options = Object.assign({ - units: 'metric', - precision: 1 - }, defaultOptions, options) - _options.set(this, options) - - const tables = { - metric: [ - { from: 0 , to: 1e3 , unit: 'B' , long: 'bytes' }, - { from: 1e3 , to: 1e6 , unit: 'kB', long: 'kilobytes' }, - { from: 1e6 , to: 1e9 , unit: 'MB', long: 'megabytes' }, - { from: 1e9 , to: 1e12, unit: 'GB', long: 'gigabytes' }, - { from: 1e12, to: 1e15, unit: 'TB', long: 'terabytes' }, - { from: 1e15, to: 1e18, unit: 'PB', long: 'petabytes' }, - { from: 1e18, to: 1e21, unit: 'EB', long: 'exabytes' }, - { from: 1e21, to: 1e24, unit: 'ZB', long: 'zettabytes' }, - { from: 1e24, to: 1e27, unit: 'YB', long: 'yottabytes' }, - ], - metric_octet: [ - { from: 0 , to: 1e3 , unit: 'o' , long: 'octets' }, - { from: 1e3 , to: 1e6 , unit: 'ko', long: 'kilooctets' }, - { from: 1e6 , to: 1e9 , unit: 'Mo', long: 'megaoctets' }, - { from: 1e9 , to: 1e12, unit: 'Go', long: 'gigaoctets' }, - { from: 1e12, to: 1e15, unit: 'To', long: 'teraoctets' }, - { from: 1e15, to: 1e18, unit: 'Po', long: 'petaoctets' }, - { from: 1e18, to: 1e21, unit: 'Eo', long: 'exaoctets' }, - { from: 1e21, to: 1e24, unit: 'Zo', long: 'zettaoctets' }, - { from: 1e24, to: 1e27, unit: 'Yo', long: 'yottaoctets' }, - ], - iec: [ - { from: 0 , to: Math.pow(1024, 1), unit: 'B' , long: 'bytes' }, - { from: Math.pow(1024, 1), to: Math.pow(1024, 2), unit: 'KiB', long: 'kibibytes' }, - { from: Math.pow(1024, 2), to: Math.pow(1024, 3), unit: 'MiB', long: 'mebibytes' }, - { from: Math.pow(1024, 3), to: Math.pow(1024, 4), unit: 'GiB', long: 'gibibytes' }, - { from: Math.pow(1024, 4), to: Math.pow(1024, 5), unit: 'TiB', long: 'tebibytes' }, - { from: Math.pow(1024, 5), to: Math.pow(1024, 6), unit: 'PiB', long: 'pebibytes' }, - { from: Math.pow(1024, 6), to: Math.pow(1024, 7), unit: 'EiB', long: 'exbibytes' }, - { from: Math.pow(1024, 7), to: Math.pow(1024, 8), unit: 'ZiB', long: 'zebibytes' }, - { from: Math.pow(1024, 8), to: Math.pow(1024, 9), unit: 'YiB', long: 'yobibytes' }, - ], - iec_octet: [ - { from: 0 , to: Math.pow(1024, 1), unit: 'o' , long: 'octets' }, - { from: Math.pow(1024, 1), to: Math.pow(1024, 2), unit: 'Kio', long: 'kibioctets' }, - { from: Math.pow(1024, 2), to: Math.pow(1024, 3), unit: 'Mio', long: 'mebioctets' }, - { from: Math.pow(1024, 3), to: Math.pow(1024, 4), unit: 'Gio', long: 'gibioctets' }, - { from: Math.pow(1024, 4), to: Math.pow(1024, 5), unit: 'Tio', long: 'tebioctets' }, - { from: Math.pow(1024, 5), to: Math.pow(1024, 6), unit: 'Pio', long: 'pebioctets' }, - { from: Math.pow(1024, 6), to: Math.pow(1024, 7), unit: 'Eio', long: 'exbioctets' }, - { from: Math.pow(1024, 7), to: Math.pow(1024, 8), unit: 'Zio', long: 'zebioctets' }, - { from: Math.pow(1024, 8), to: Math.pow(1024, 9), unit: 'Yio', long: 'yobioctets' }, - ], - } - Object.assign(tables, options.customUnits) - - const prefix = bytes < 0 ? '-' : '' - bytes = Math.abs(bytes) - const table = tables[options.units] - if (table) { - const units = table.find(u => bytes >= u.from && bytes < u.to) - if (units) { - const value = units.from === 0 - ? prefix + bytes - : prefix + (bytes / units.from).toFixed(options.precision) - this.value = value - this.unit = units.unit - this.long = units.long - } else { - this.value = prefix + bytes - this.unit = '' - this.long = '' - } - } else { - throw new Error(`Invalid units specified: ${options.units}`) - } - } - - toString () { - const options = _options.get(this) - return options.toStringFn ? options.toStringFn.bind(this)() : `${this.value} ${this.unit}` - } -} - -/** - * Returns an object with the spec `{ value: string, unit: string, long: string }`. The returned object defines a `toString` method meaning it can be used in any string context. - * @param {number} - The bytes value to convert. - * @param [options] {object} - Optional config. - * @param [options.precision] {number} - Number of decimal places. Defaults to `1`. - * @param [options.units] {string} - Specify `'metric'`, `'iec'`, `'metric_octet'`, `'iec_octet'` or the name of a property from the custom units table in `options.customUnits`. Defaults to `metric`. - * @param [options.customUnits] {object} - An object containing one or more custom unit lookup tables. - * @param [options.toStringFn] {function} - A `toString` function to override the default. - * @returns {object} - * @alias module:byte-size - */ -function byteSize (bytes, options) { - return new ByteSize(bytes, options) -} - -/** - * Set the default `byteSize` options for the duration of the process. - * @param options {object} - A `byteSize` options object. - */ -byteSize.defaultOptions = function (options) { - defaultOptions = options -} - -export default byteSize diff --git a/node_modules/byte-size/package.json b/node_modules/byte-size/package.json deleted file mode 100644 index b5f454592da10..0000000000000 --- a/node_modules/byte-size/package.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "byte-size", - "author": "Lloyd Brookes <75pound@gmail.com>", - "contributors": [ - { - "name": "Raul Perez", - "email": "repejota@gmail.com", - "url": "http://repejota.com" - } - ], - "version": "7.0.1", - "main": "dist/index.js", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "description": "Convert a bytes or octets value (e.g. 34565346) to a human-readable string ('34.6 MB'). Choose between metric or IEC units.", - "repository": "https://github.com/75lb/byte-size", - "files": [ - "index.mjs", - "dist/index.js" - ], - "keywords": [ - "convert", - "bytes", - "octet", - "size", - "human", - "readable", - "metric", - "IEC" - ], - "scripts": { - "test": "npm run dist && npm run test:esm && npm run test:web", - "test:esm": "esm-runner test.mjs", - "test:web": "web-runner test.mjs", - "docs": "jsdoc2md -t README.hbs dist/index.js > README.md", - "cover": "c8 npm test && c8 report --reporter=text-lcov | coveralls", - "dist": "rollup -f umd -n byteSize -o dist/index.js index.mjs" - }, - "devDependencies": { - "@test-runner/web": "^0.3.5", - "coveralls": "^3.1.0", - "esm-runner": "^0.3.4", - "isomorphic-assert": "^0.1.1", - "jsdoc-to-markdown": "^7.0.0", - "rollup": "^2.40.0", - "test-object-model": "^0.6.1" - }, - "standard": { - "ignore": [ - "dist" - ] - } -} diff --git a/node_modules/tar/lib/mkdir.js b/node_modules/tar/lib/mkdir.js index aed398fcdcd44..a0719e6c36ed3 100644 --- a/node_modules/tar/lib/mkdir.js +++ b/node_modules/tar/lib/mkdir.js @@ -8,6 +8,7 @@ const mkdirp = require('mkdirp') const fs = require('fs') const path = require('path') const chownr = require('chownr') +const normPath = require('./normalize-windows-path.js') class SymlinkError extends Error { constructor (symlink, path) { @@ -33,7 +34,20 @@ class CwdError extends Error { } } +const cGet = (cache, key) => cache.get(normPath(key)) +const cSet = (cache, key, val) => cache.set(normPath(key), val) + +const checkCwd = (dir, cb) => { + fs.stat(dir, (er, st) => { + if (er || !st.isDirectory()) + er = new CwdError(dir, er && er.code || 'ENOTDIR') + cb(er) + }) +} + module.exports = (dir, opt, cb) => { + dir = normPath(dir) + // if there's any overlap between mask and mode, // then we'll need an explicit chmod const umask = opt.umask @@ -49,13 +63,13 @@ module.exports = (dir, opt, cb) => { const preserve = opt.preserve const unlink = opt.unlink const cache = opt.cache - const cwd = opt.cwd + const cwd = normPath(opt.cwd) const done = (er, created) => { if (er) cb(er) else { - cache.set(dir, true) + cSet(cache, dir, true) if (created && doChown) chownr(created, uid, gid, er => done(er)) else if (needChmod) @@ -65,22 +79,17 @@ module.exports = (dir, opt, cb) => { } } - if (cache && cache.get(dir) === true) + if (cache && cGet(cache, dir) === true) return done() - if (dir === cwd) { - return fs.stat(dir, (er, st) => { - if (er || !st.isDirectory()) - er = new CwdError(dir, er && er.code || 'ENOTDIR') - done(er) - }) - } + if (dir === cwd) + return checkCwd(dir, done) if (preserve) return mkdirp(dir, {mode}).then(made => done(null, made), done) - const sub = path.relative(cwd, dir) - const parts = sub.split(/\/|\\/) + const sub = normPath(path.relative(cwd, dir)) + const parts = sub.split('/') mkdir_(cwd, parts, mode, cache, unlink, cwd, null, done) } @@ -88,22 +97,19 @@ const mkdir_ = (base, parts, mode, cache, unlink, cwd, created, cb) => { if (!parts.length) return cb(null, created) const p = parts.shift() - const part = base + '/' + p - if (cache.get(part)) + const part = normPath(path.resolve(base + '/' + p)) + if (cGet(cache, part)) return mkdir_(part, parts, mode, cache, unlink, cwd, created, cb) fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb)) } const onmkdir = (part, parts, mode, cache, unlink, cwd, created, cb) => er => { if (er) { - if (er.path && path.dirname(er.path) === cwd && - (er.code === 'ENOTDIR' || er.code === 'ENOENT')) - return cb(new CwdError(cwd, er.code)) - fs.lstat(part, (statEr, st) => { - if (statEr) + if (statEr) { + statEr.path = statEr.path && normPath(statEr.path) cb(statEr) - else if (st.isDirectory()) + } else if (st.isDirectory()) mkdir_(part, parts, mode, cache, unlink, cwd, created, cb) else if (unlink) { fs.unlink(part, er => { @@ -122,7 +128,21 @@ const onmkdir = (part, parts, mode, cache, unlink, cwd, created, cb) => er => { } } +const checkCwdSync = dir => { + let ok = false + let code = 'ENOTDIR' + try { + ok = fs.statSync(dir).isDirectory() + } catch (er) { + code = er.code + } finally { + if (!ok) + throw new CwdError(dir, code) + } +} + module.exports.sync = (dir, opt) => { + dir = normPath(dir) // if there's any overlap between mask and mode, // then we'll need an explicit chmod const umask = opt.umask @@ -138,64 +158,51 @@ module.exports.sync = (dir, opt) => { const preserve = opt.preserve const unlink = opt.unlink const cache = opt.cache - const cwd = opt.cwd + const cwd = normPath(opt.cwd) const done = (created) => { - cache.set(dir, true) + cSet(cache, dir, true) if (created && doChown) chownr.sync(created, uid, gid) if (needChmod) fs.chmodSync(dir, mode) } - if (cache && cache.get(dir) === true) + if (cache && cGet(cache, dir) === true) return done() if (dir === cwd) { - let ok = false - let code = 'ENOTDIR' - try { - ok = fs.statSync(dir).isDirectory() - } catch (er) { - code = er.code - } finally { - if (!ok) - throw new CwdError(dir, code) - } - done() - return + checkCwdSync(cwd) + return done() } if (preserve) return done(mkdirp.sync(dir, mode)) - const sub = path.relative(cwd, dir) - const parts = sub.split(/\/|\\/) + const sub = normPath(path.relative(cwd, dir)) + const parts = sub.split('/') let created = null for (let p = parts.shift(), part = cwd; p && (part += '/' + p); p = parts.shift()) { - if (cache.get(part)) + part = normPath(path.resolve(part)) + if (cGet(cache, part)) continue try { fs.mkdirSync(part, mode) created = created || part - cache.set(part, true) + cSet(cache, part, true) } catch (er) { - if (er.path && path.dirname(er.path) === cwd && - (er.code === 'ENOTDIR' || er.code === 'ENOENT')) - return new CwdError(cwd, er.code) - const st = fs.lstatSync(part) if (st.isDirectory()) { - cache.set(part, true) + cSet(cache, part, true) continue } else if (unlink) { fs.unlinkSync(part) fs.mkdirSync(part, mode) created = created || part - cache.set(part, true) + cSet(cache, part, true) continue } else if (st.isSymbolicLink()) return new SymlinkError(part, part + '/' + parts.join('/')) diff --git a/node_modules/tar/lib/normalize-windows-path.js b/node_modules/tar/lib/normalize-windows-path.js new file mode 100644 index 0000000000000..eb13ba01b7b04 --- /dev/null +++ b/node_modules/tar/lib/normalize-windows-path.js @@ -0,0 +1,8 @@ +// on windows, either \ or / are valid directory separators. +// on unix, \ is a valid character in filenames. +// so, on windows, and only on windows, we replace all \ chars with /, +// so that we can use / as our one and only directory separator char. + +const platform = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform +module.exports = platform !== 'win32' ? p => p + : p => p && p.replace(/\\/g, '/') diff --git a/node_modules/tar/lib/pack.js b/node_modules/tar/lib/pack.js index df7f9f1c8df5b..9522c10bfe4a4 100644 --- a/node_modules/tar/lib/pack.js +++ b/node_modules/tar/lib/pack.js @@ -54,6 +54,7 @@ const ONDRAIN = Symbol('ondrain') const fs = require('fs') const path = require('path') const warner = require('./warn-mixin.js') +const normPath = require('./normalize-windows-path.js') const Pack = warner(class Pack extends MiniPass { constructor (opt) { @@ -66,7 +67,7 @@ const Pack = warner(class Pack extends MiniPass { this.preservePaths = !!opt.preservePaths this.strict = !!opt.strict this.noPax = !!opt.noPax - this.prefix = (opt.prefix || '').replace(/(\\|\/)+$/, '') + this.prefix = normPath(opt.prefix || '') this.linkCache = opt.linkCache || new Map() this.statCache = opt.statCache || new Map() this.readdirCache = opt.readdirCache || new Map() @@ -133,7 +134,7 @@ const Pack = warner(class Pack extends MiniPass { } [ADDTARENTRY] (p) { - const absolute = path.resolve(this.cwd, p.path) + const absolute = normPath(path.resolve(this.cwd, p.path)) // in this case, we don't have to wait for the stat if (!this.filter(p.path, p)) p.resume() @@ -149,7 +150,7 @@ const Pack = warner(class Pack extends MiniPass { } [ADDFSENTRY] (p) { - const absolute = path.resolve(this.cwd, p) + const absolute = normPath(path.resolve(this.cwd, p)) this[QUEUE].push(new PackJob(p, absolute)) this[PROCESS]() } diff --git a/node_modules/tar/lib/path-reservations.js b/node_modules/tar/lib/path-reservations.js index c0a16b0a1f901..167447af08057 100644 --- a/node_modules/tar/lib/path-reservations.js +++ b/node_modules/tar/lib/path-reservations.js @@ -7,6 +7,8 @@ // while still allowing maximal safe parallelization. const assert = require('assert') +const normPath = require('./normalize-windows-path.js') +const { join } = require('path') module.exports = () => { // path => [function or Set] @@ -18,10 +20,10 @@ module.exports = () => { const reservations = new Map() // return a set of parent dirs for a given path - const { join } = require('path') const getDirs = path => - join(path).split(/[\\/]/).slice(0, -1).reduce((set, path) => - set.length ? set.concat(join(set[set.length - 1], path)) : [path], []) + path.split('/').slice(0, -1).reduce((set, path) => + set.length ? set.concat(normPath(join(set[set.length - 1], path))) + : [path], []) // functions currently running const running = new Set() @@ -97,6 +99,7 @@ module.exports = () => { } const reserve = (paths, fn) => { + paths = paths.map(p => normPath(join(p)).toLowerCase()) const dirs = new Set( paths.map(path => getDirs(path)).reduce((a, b) => a.concat(b)) ) diff --git a/node_modules/tar/lib/read-entry.js b/node_modules/tar/lib/read-entry.js index 6661cba5ff9ef..183a6050ba0d2 100644 --- a/node_modules/tar/lib/read-entry.js +++ b/node_modules/tar/lib/read-entry.js @@ -1,5 +1,6 @@ 'use strict' const MiniPass = require('minipass') +const normPath = require('./normalize-windows-path.js') const SLURP = Symbol('slurp') module.exports = class ReadEntry extends MiniPass { @@ -46,7 +47,7 @@ module.exports = class ReadEntry extends MiniPass { this.ignore = true } - this.path = header.path + this.path = normPath(header.path) this.mode = header.mode if (this.mode) this.mode = this.mode & 0o7777 @@ -58,7 +59,7 @@ module.exports = class ReadEntry extends MiniPass { this.mtime = header.mtime this.atime = header.atime this.ctime = header.ctime - this.linkpath = header.linkpath + this.linkpath = normPath(header.linkpath) this.uname = header.uname this.gname = header.gname @@ -93,7 +94,7 @@ module.exports = class ReadEntry extends MiniPass { // a global extended header, because that's weird. if (ex[k] !== null && ex[k] !== undefined && !(global && k === 'path')) - this[k] = ex[k] + this[k] = k === 'path' || k === 'linkpath' ? normPath(ex[k]) : ex[k] } } } diff --git a/node_modules/tar/lib/replace.js b/node_modules/tar/lib/replace.js index e5e2a425536d6..1374f3f29c619 100644 --- a/node_modules/tar/lib/replace.js +++ b/node_modules/tar/lib/replace.js @@ -170,7 +170,8 @@ const replace = (opt, files, cb) => { fs.fstat(fd, (er, st) => { if (er) - return reject(er) + return fs.close(fd, () => reject(er)) + getPos(fd, st.size, (er, position) => { if (er) return reject(er) diff --git a/node_modules/tar/lib/unpack.js b/node_modules/tar/lib/unpack.js index 282e04f945c50..cf10d07347b69 100644 --- a/node_modules/tar/lib/unpack.js +++ b/node_modules/tar/lib/unpack.js @@ -15,6 +15,7 @@ const mkdir = require('./mkdir.js') const wc = require('./winchars.js') const pathReservations = require('./path-reservations.js') const stripAbsolutePath = require('./strip-absolute-path.js') +const normPath = require('./normalize-windows-path.js') const ONENTRY = Symbol('onEntry') const CHECKFS = Symbol('checkFs') @@ -39,14 +40,10 @@ const SKIP = Symbol('skip') const DOCHOWN = Symbol('doChown') const UID = Symbol('uid') const GID = Symbol('gid') +const CHECKED_CWD = Symbol('checkedCwd') const crypto = require('crypto') const getFlag = require('./get-write-flag.js') -/* istanbul ignore next */ -const neverCalled = () => { - throw new Error('sync function called cb somehow?!?') -} - // Unlinks on Windows are not atomic. // // This means that if you have a file entry, followed by another @@ -91,6 +88,17 @@ const uint32 = (a, b, c) => : b === b >>> 0 ? b : c +const pruneCache = (cache, abs) => { + // clear the cache if it's a case-insensitive match, since we can't + // know if the current file system is case-sensitive or not. + abs = normPath(abs).toLowerCase() + for (const path of cache.keys()) { + const plower = path.toLowerCase() + if (plower === abs || plower.toLowerCase().indexOf(abs + '/') === 0) + cache.delete(path) + } +} + class Unpack extends Parser { constructor (opt) { if (!opt) @@ -103,6 +111,8 @@ class Unpack extends Parser { super(opt) + this[CHECKED_CWD] = false + this.reservations = pathReservations() this.transform = typeof opt.transform === 'function' ? opt.transform : null @@ -168,7 +178,7 @@ class Unpack extends Parser { // links, and removes symlink directories rather than erroring this.unlink = !!opt.unlink - this.cwd = path.resolve(opt.cwd || process.cwd()) + this.cwd = normPath(path.resolve(opt.cwd || process.cwd())) this.strip = +opt.strip || 0 // if we're not chmodding, then we don't need the process umask this.processUmask = opt.noChmod ? 0 : process.umask() @@ -201,23 +211,23 @@ class Unpack extends Parser { [CHECKPATH] (entry) { if (this.strip) { - const parts = entry.path.split(/\/|\\/) + const parts = normPath(entry.path).split('/') if (parts.length < this.strip) return false entry.path = parts.slice(this.strip).join('/') - if (entry.path === '' && entry.type !== 'Directory' && entry.type !== 'GNUDumpDir') - return false if (entry.type === 'Link') { - const linkparts = entry.linkpath.split(/\/|\\/) + const linkparts = normPath(entry.linkpath).split('/') if (linkparts.length >= this.strip) entry.linkpath = linkparts.slice(this.strip).join('/') + else + return false } } if (!this.preservePaths) { - const p = entry.path - if (p.match(/(^|\/|\\)\.\.(\\|\/|$)/)) { + const p = normPath(entry.path) + if (p.split('/').includes('..')) { this.warn('TAR_ENTRY_ERROR', `path contains '..'`, { entry, path: p, @@ -237,18 +247,26 @@ class Unpack extends Parser { } } + if (path.isAbsolute(entry.path)) + entry.absolute = normPath(path.resolve(entry.path)) + else + entry.absolute = normPath(path.resolve(this.cwd, entry.path)) + + // an archive can set properties on the extraction directory, but it + // may not replace the cwd with a different kind of thing entirely. + if (entry.absolute === this.cwd && + entry.type !== 'Directory' && + entry.type !== 'GNUDumpDir') + return false + // only encode : chars that aren't drive letter indicators if (this.win32) { - const parsed = path.win32.parse(entry.path) - entry.path = parsed.root === '' ? wc.encode(entry.path) - : parsed.root + wc.encode(entry.path.substr(parsed.root.length)) + const { root: aRoot } = path.win32.parse(entry.absolute) + entry.absolute = aRoot + wc.encode(entry.absolute.substr(aRoot.length)) + const { root: pRoot } = path.win32.parse(entry.path) + entry.path = pRoot + wc.encode(entry.path.substr(pRoot.length)) } - if (path.isAbsolute(entry.path)) - entry.absolute = entry.path - else - entry.absolute = path.resolve(this.cwd, entry.path) - return true } @@ -293,7 +311,7 @@ class Unpack extends Parser { } [MKDIR] (dir, mode, cb) { - mkdir(dir, { + mkdir(normPath(dir), { uid: this.uid, gid: this.gid, processUid: this.processUid, @@ -338,6 +356,7 @@ class Unpack extends Parser { stream.on('error', er => { if (stream.fd) fs.close(stream.fd, () => {}) + // flush all the data out so that we aren't left hanging // if the error wasn't actually fatal. otherwise the parse // is blocked, and we never proceed. @@ -352,6 +371,7 @@ class Unpack extends Parser { /* istanbul ignore else - we should always have a fd by now */ if (stream.fd) fs.close(stream.fd, () => {}) + this[ONERROR](er, entry) fullyDone() return @@ -451,7 +471,8 @@ class Unpack extends Parser { } [HARDLINK] (entry, done) { - this[LINK](entry, path.resolve(this.cwd, entry.linkpath), 'link', done) + const linkpath = normPath(path.resolve(this.cwd, entry.linkpath)) + this[LINK](entry, linkpath, 'link', done) } [PEND] () { @@ -493,41 +514,79 @@ class Unpack extends Parser { // then that means we are about to delete the directory we created // previously, and it is no longer going to be a directory, and neither // is any of its children. - if (entry.type !== 'Directory') { - for (const path of this.dirCache.keys()) { - if (path === entry.absolute || - path.indexOf(entry.absolute + '/') === 0 || - path.indexOf(entry.absolute + '\\') === 0) - this.dirCache.delete(path) - } + if (entry.type !== 'Directory') + pruneCache(this.dirCache, entry.absolute) + + const checkCwd = () => { + this[MKDIR](this.cwd, this.dmode, er => { + if (er) { + this[ONERROR](er, entry) + done() + return + } + this[CHECKED_CWD] = true + start() + }) } - this[MKDIR](path.dirname(entry.absolute), this.dmode, er => { - if (er) { - this[ONERROR](er, entry) - done() - return + const start = () => { + if (entry.absolute !== this.cwd) { + const parent = normPath(path.dirname(entry.absolute)) + if (parent !== this.cwd) { + return this[MKDIR](parent, this.dmode, er => { + if (er) { + this[ONERROR](er, entry) + done() + return + } + afterMakeParent() + }) + } } - fs.lstat(entry.absolute, (er, st) => { + afterMakeParent() + } + + const afterMakeParent = () => { + fs.lstat(entry.absolute, (lstatEr, st) => { if (st && (this.keep || this.newer && st.mtime > entry.mtime)) { this[SKIP](entry) done() - } else if (er || this[ISREUSABLE](entry, st)) - this[MAKEFS](null, entry, done) - else if (st.isDirectory()) { + return + } + if (lstatEr || this[ISREUSABLE](entry, st)) + return this[MAKEFS](null, entry, done) + + if (st.isDirectory()) { if (entry.type === 'Directory') { - if (!this.noChmod && (!entry.mode || (st.mode & 0o7777) === entry.mode)) - this[MAKEFS](null, entry, done) - else { - fs.chmod(entry.absolute, entry.mode, - er => this[MAKEFS](er, entry, done)) - } - } else - fs.rmdir(entry.absolute, er => this[MAKEFS](er, entry, done)) - } else - unlinkFile(entry.absolute, er => this[MAKEFS](er, entry, done)) + const needChmod = !this.noChmod && + entry.mode && + (st.mode & 0o7777) !== entry.mode + const afterChmod = er => this[MAKEFS](er, entry, done) + if (!needChmod) + return afterChmod() + return fs.chmod(entry.absolute, entry.mode, afterChmod) + } + // not a dir entry, have to remove it. + if (entry.absolute !== this.cwd) { + return fs.rmdir(entry.absolute, er => + this[MAKEFS](er, entry, done)) + } + } + + // not a dir, and not reusable + // don't remove if the cwd, we want that error + if (entry.absolute === this.cwd) + return this[MAKEFS](null, entry, done) + + unlinkFile(entry.absolute, er => + this[MAKEFS](er, entry, done)) }) - }) + } + + if (this[CHECKED_CWD]) + start() + else + checkCwd() } [MAKEFS] (er, entry, done) { @@ -556,7 +615,7 @@ class Unpack extends Parser { } [LINK] (entry, linkpath, link, done) { - // XXX: get the type ('file' or 'dir') for windows + // XXX: get the type ('symlink' or 'junction') for windows fs[link](linkpath, entry.absolute, er => { if (er) this[ONERROR](er, entry) @@ -569,44 +628,67 @@ class Unpack extends Parser { } } +const callSync = fn => { + try { + return [null, fn()] + } catch (er) { + return [er, null] + } +} class UnpackSync extends Unpack { + [MAKEFS] (er, entry) { + return super[MAKEFS](er, entry, () => {}) + } + [CHECKFS] (entry) { - if (entry.type !== 'Directory') { - for (const path of this.dirCache.keys()) { - if (path === entry.absolute || - path.indexOf(entry.absolute + '/') === 0 || - path.indexOf(entry.absolute + '\\') === 0) - this.dirCache.delete(path) + if (entry.type !== 'Directory') + pruneCache(this.dirCache, entry.absolute) + + if (!this[CHECKED_CWD]) { + const er = this[MKDIR](this.cwd, this.dmode) + if (er) + return this[ONERROR](er, entry) + this[CHECKED_CWD] = true + } + + // don't bother to make the parent if the current entry is the cwd, + // we've already checked it. + if (entry.absolute !== this.cwd) { + const parent = normPath(path.dirname(entry.absolute)) + if (parent !== this.cwd) { + const mkParent = this[MKDIR](parent, this.dmode) + if (mkParent) + return this[ONERROR](mkParent, entry) } } - const er = this[MKDIR](path.dirname(entry.absolute), this.dmode, neverCalled) - if (er) - return this[ONERROR](er, entry) - try { - const st = fs.lstatSync(entry.absolute) - if (this.keep || this.newer && st.mtime > entry.mtime) - return this[SKIP](entry) - else if (this[ISREUSABLE](entry, st)) - return this[MAKEFS](null, entry, neverCalled) - else { - try { - if (st.isDirectory()) { - if (entry.type === 'Directory') { - if (!this.noChmod && entry.mode && (st.mode & 0o7777) !== entry.mode) - fs.chmodSync(entry.absolute, entry.mode) - } else - fs.rmdirSync(entry.absolute) - } else - unlinkFileSync(entry.absolute) - return this[MAKEFS](null, entry, neverCalled) - } catch (er) { - return this[ONERROR](er, entry) - } + const [lstatEr, st] = callSync(() => fs.lstatSync(entry.absolute)) + if (st && (this.keep || this.newer && st.mtime > entry.mtime)) + return this[SKIP](entry) + + if (lstatEr || this[ISREUSABLE](entry, st)) + return this[MAKEFS](null, entry) + + if (st.isDirectory()) { + if (entry.type === 'Directory') { + const needChmod = !this.noChmod && + entry.mode && + (st.mode & 0o7777) !== entry.mode + const [er] = needChmod ? callSync(() => { + fs.chmodSync(entry.absolute, entry.mode) + }) : [] + return this[MAKEFS](er, entry) } - } catch (er) { - return this[MAKEFS](null, entry, neverCalled) + // not a dir entry, have to remove it + const [er] = callSync(() => fs.rmdirSync(entry.absolute)) + this[MAKEFS](er, entry) } + + // not a dir, and not reusable. + // don't remove if it's the cwd, since we want that error. + const [er] = entry.absolute === this.cwd ? [] + : callSync(() => unlinkFileSync(entry.absolute)) + this[MAKEFS](er, entry) } [FILE] (entry, _) { @@ -700,7 +782,7 @@ class UnpackSync extends Unpack { [MKDIR] (dir, mode) { try { - return mkdir.sync(dir, { + return mkdir.sync(normPath(dir), { uid: this.uid, gid: this.gid, processUid: this.processUid, diff --git a/node_modules/tar/lib/write-entry.js b/node_modules/tar/lib/write-entry.js index 0457f3aefe2a8..3702f2ae51979 100644 --- a/node_modules/tar/lib/write-entry.js +++ b/node_modules/tar/lib/write-entry.js @@ -4,12 +4,14 @@ const Pax = require('./pax.js') const Header = require('./header.js') const fs = require('fs') const path = require('path') +const normPath = require('./normalize-windows-path.js') +const stripSlash = require('./strip-trailing-slashes.js') const prefixPath = (path, prefix) => { if (!prefix) - return path - path = path.replace(/^\.([/\\]|$)/, '') - return prefix + '/' + path + return normPath(path) + path = normPath(path).replace(/^\.(\/|$)/, '') + return stripSlash(prefix) + '/' + path } const maxReadSize = 16 * 1024 * 1024 @@ -31,6 +33,7 @@ const MODE = Symbol('mode') const AWAITDRAIN = Symbol('awaitDrain') const ONDRAIN = Symbol('ondrain') const PREFIX = Symbol('prefix') +const HAD_ERROR = Symbol('hadError') const warner = require('./warn-mixin.js') const winchars = require('./winchars.js') const stripAbsolutePath = require('./strip-absolute-path.js') @@ -43,22 +46,22 @@ const WriteEntry = warner(class WriteEntry extends MiniPass { super(opt) if (typeof p !== 'string') throw new TypeError('path is required') - this.path = p + this.path = normPath(p) // suppress atime, ctime, uid, gid, uname, gname this.portable = !!opt.portable // until node has builtin pwnam functions, this'll have to do - this.myuid = process.getuid && process.getuid() + this.myuid = process.getuid && process.getuid() || 0 this.myuser = process.env.USER || '' this.maxReadSize = opt.maxReadSize || maxReadSize this.linkCache = opt.linkCache || new Map() this.statCache = opt.statCache || new Map() this.preservePaths = !!opt.preservePaths - this.cwd = opt.cwd || process.cwd() + this.cwd = normPath(opt.cwd || process.cwd()) this.strict = !!opt.strict this.noPax = !!opt.noPax this.noMtime = !!opt.noMtime this.mtime = opt.mtime || null - this.prefix = opt.prefix || null + this.prefix = opt.prefix ? normPath(opt.prefix) : null this.fd = null this.blockLen = null @@ -83,11 +86,13 @@ const WriteEntry = warner(class WriteEntry extends MiniPass { this.win32 = !!opt.win32 || process.platform === 'win32' if (this.win32) { + // force the \ to / normalization, since we might not *actually* + // be on windows, but want \ to be considered a path separator. this.path = winchars.decode(this.path.replace(/\\/g, '/')) p = p.replace(/\\/g, '/') } - this.absolute = opt.absolute || path.resolve(this.cwd, p) + this.absolute = normPath(opt.absolute || path.resolve(this.cwd, p)) if (this.path === '') this.path = './' @@ -105,6 +110,12 @@ const WriteEntry = warner(class WriteEntry extends MiniPass { this[LSTAT]() } + emit (ev, ...data) { + if (ev === 'error') + this[HAD_ERROR] = true + return super.emit(ev, ...data) + } + [LSTAT] () { fs.lstat(this.absolute, (er, stat) => { if (er) @@ -201,14 +212,14 @@ const WriteEntry = warner(class WriteEntry extends MiniPass { } [ONREADLINK] (linkpath) { - this.linkpath = linkpath.replace(/\\/g, '/') + this.linkpath = normPath(linkpath) this[HEADER]() this.end() } [HARDLINK] (linkpath) { this.type = 'Link' - this.linkpath = path.relative(this.cwd, linkpath).replace(/\\/g, '/') + this.linkpath = normPath(path.relative(this.cwd, linkpath)) this.stat.size = 0 this[HEADER]() this.end() @@ -242,6 +253,9 @@ const WriteEntry = warner(class WriteEntry extends MiniPass { [ONOPENFILE] (fd) { this.fd = fd + if (this[HAD_ERROR]) + return this[CLOSE]() + this.blockLen = 512 * Math.ceil(this.stat.size / 512) this.blockRemain = this.blockLen const bufLen = Math.min(this.blockLen, this.maxReadSize) @@ -403,7 +417,7 @@ const WriteEntryTar = warner(class WriteEntryTar extends MiniPass { this.prefix = opt.prefix || null - this.path = readEntry.path + this.path = normPath(readEntry.path) this.mode = this[MODE](readEntry.mode) this.uid = this.portable ? null : readEntry.uid this.gid = this.portable ? null : readEntry.gid @@ -413,7 +427,7 @@ const WriteEntryTar = warner(class WriteEntryTar extends MiniPass { this.mtime = this.noMtime ? null : opt.mtime || readEntry.mtime this.atime = this.portable ? null : readEntry.atime this.ctime = this.portable ? null : readEntry.ctime - this.linkpath = readEntry.linkpath + this.linkpath = normPath(readEntry.linkpath) if (typeof opt.onwarn === 'function') this.on('warn', opt.onwarn) diff --git a/node_modules/tar/package.json b/node_modules/tar/package.json index fbde61edcc51e..42f55d0356ca4 100644 --- a/node_modules/tar/package.json +++ b/node_modules/tar/package.json @@ -2,13 +2,15 @@ "author": "Isaac Z. Schlueter (http://blog.izs.me/)", "name": "tar", "description": "tar for node", - "version": "6.1.6", + "version": "6.1.8", "repository": { "type": "git", "url": "https://github.com/npm/node-tar.git" }, "scripts": { - "test": "tap", + "test:posix": "tap", + "test:win32": "tap --lines=98 --branches=98 --statements=98 --functions=98", + "test": "node test/fixtures/test.js", "posttest": "npm run lint", "eslint": "eslint", "lint": "npm run eslint -- test lib", diff --git a/package-lock.json b/package-lock.json index a7fbf4624c30a..682d82969f9c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,23 +1,23 @@ { "name": "npm", - "version": "7.20.5", + "version": "7.20.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "npm", - "version": "7.20.5", + "version": "7.20.6", "bundleDependencies": [ "@npmcli/arborist", "@npmcli/ci-detect", "@npmcli/config", + "@npmcli/map-workspaces", "@npmcli/package-json", "@npmcli/run-script", "abbrev", "ansicolors", "ansistyles", "archy", - "byte-size", "cacache", "chalk", "chownr", @@ -83,16 +83,16 @@ "packages/*" ], "dependencies": { - "@npmcli/arborist": "^2.8.0", + "@npmcli/arborist": "^2.8.1", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^2.2.0", + "@npmcli/map-workspaces": "^1.0.4", "@npmcli/package-json": "^1.0.1", "@npmcli/run-script": "^1.8.5", "abbrev": "~1.1.1", "ansicolors": "~0.3.2", "ansistyles": "~0.1.3", "archy": "~1.0.0", - "byte-size": "^7.0.1", "cacache": "^15.2.0", "chalk": "^4.1.2", "chownr": "^2.0.0", @@ -144,7 +144,7 @@ "rimraf": "^3.0.2", "semver": "^7.3.5", "ssri": "^8.0.1", - "tar": "^6.1.6", + "tar": "^6.1.8", "text-table": "~0.2.0", "tiny-relative-date": "^1.3.0", "treeverse": "^1.0.4", @@ -756,9 +756,9 @@ } }, "node_modules/@npmcli/arborist": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.8.0.tgz", - "integrity": "sha512-R9rTyak1rGdmVTyiU14dgBb+qMllY3B6I8hp7FB4xXsU9dJDrYZJR8I+191CMo5Y1941jTDCtNcXXW9TldPEFQ==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.8.1.tgz", + "integrity": "sha512-kbBWllN4CcdeN032Rw6b+TIsyoxWcv4YNN5gzkMCe8cCu0llwlq5P7uAD2oyL24QdmGlrlg/Yp0L1JF+HD8g9Q==", "inBundle": true, "dependencies": { "@npmcli/installed-package-contents": "^1.0.7", @@ -867,9 +867,9 @@ } }, "node_modules/@npmcli/map-workspaces": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.3.tgz", - "integrity": "sha512-SdlRlOoQw4WKD4vtb/n5gUkobEABYBEOo8fRE4L8CtBkyWDSvIrReTfKvQ/Jc/LQqDaaZ5iv1iMSQzKCUr1n1A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.4.tgz", + "integrity": "sha512-wVR8QxhyXsFcD/cORtJwGQodeeaDf0OxcHie8ema4VgFeqwYkFsDPnSrIRSytX8xR6nKPAH89WnwTcaU608b/Q==", "inBundle": true, "dependencies": { "@npmcli/name-from-folder": "^1.0.1", @@ -1528,15 +1528,6 @@ "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", "inBundle": true }, - "node_modules/byte-size": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-7.0.1.tgz", - "integrity": "sha512-crQdqyCwhokxwV1UyDzLZanhkugAgft7vt0qbbdt60C6Zf3CAiGmtUCylbtYwrU6loOUw3euGrNtW1J651ot1A==", - "inBundle": true, - "engines": { - "node": ">=10" - } - }, "node_modules/cacache": { "version": "15.2.0", "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.2.0.tgz", @@ -2551,9 +2542,9 @@ } }, "node_modules/eslint": { - "version": "7.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.31.0.tgz", - "integrity": "sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA==", + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "dev": true, "dependencies": { "@babel/code-frame": "7.12.11", @@ -2608,34 +2599,28 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.5.tgz", + "integrity": "sha512-XMoPKjSpXbkeJ7ZZ9icLnJMTY5Mc1kZbCakHquaFsXPpyWOwK0TK6CODO+0ca54UoM9LKOxyUNnoVZRl8TeaAg==", "dev": true, "dependencies": { - "debug": "^2.6.9", - "resolve": "^1.13.1" + "debug": "^3.2.7", + "resolve": "^1.20.0" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, "node_modules/eslint-module-utils": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", - "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz", + "integrity": "sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==", "dev": true, "dependencies": { "debug": "^3.2.7", @@ -2674,17 +2659,17 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.23.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", - "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.0.tgz", + "integrity": "sha512-Kc6xqT9hiYi2cgybOc0I2vC9OgAYga5o/rAFinam/yF/t5uBqxQbauNPMC6fgb640T/89P0gFoO27FOilJ/Cqg==", "dev": true, "dependencies": { "array-includes": "^3.1.3", "array.prototype.flat": "^1.2.4", "debug": "^2.6.9", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.1", + "eslint-import-resolver-node": "^0.3.5", + "eslint-module-utils": "^2.6.2", "find-up": "^2.0.0", "has": "^1.0.3", "is-core-module": "^2.4.0", @@ -4422,9 +4407,9 @@ "inBundle": true }, "node_modules/jsdom": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.6.0.tgz", - "integrity": "sha512-Ty1vmF4NHJkolaEmdjtxTfSfkdb8Ywarwf63f+F8/mDD1uLSSWDxDuMiZxiPhwunLrn9LOSVItWj4bLYsLN3Dg==", + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", "dev": true, "dependencies": { "abab": "^2.0.5", @@ -4452,7 +4437,7 @@ "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^8.5.0", - "ws": "^7.4.5", + "ws": "^7.4.6", "xml-name-validator": "^3.0.0" }, "engines": { @@ -9466,9 +9451,9 @@ } }, "node_modules/tar": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.6.tgz", - "integrity": "sha512-oaWyu5dQbHaYcyZCTfyPpC+VmI62/OM2RTUYavTk1MDr1cwW5Boi3baeYQKiZbY2uSQJGr+iMOzb/JFxLrft+g==", + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.8.tgz", + "integrity": "sha512-sb9b0cp855NbkMJcskdSYA7b11Q8JsX4qe4pyUAfHp+Y6jBjJeek2ZVlwEfWayshEIwlIzXx0Fain3QG9JPm2A==", "inBundle": true, "dependencies": { "chownr": "^2.0.0", @@ -11012,9 +10997,9 @@ "dev": true }, "@npmcli/arborist": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.8.0.tgz", - "integrity": "sha512-R9rTyak1rGdmVTyiU14dgBb+qMllY3B6I8hp7FB4xXsU9dJDrYZJR8I+191CMo5Y1941jTDCtNcXXW9TldPEFQ==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.8.1.tgz", + "integrity": "sha512-kbBWllN4CcdeN032Rw6b+TIsyoxWcv4YNN5gzkMCe8cCu0llwlq5P7uAD2oyL24QdmGlrlg/Yp0L1JF+HD8g9Q==", "requires": { "@npmcli/installed-package-contents": "^1.0.7", "@npmcli/map-workspaces": "^1.0.2", @@ -11100,9 +11085,9 @@ } }, "@npmcli/map-workspaces": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.3.tgz", - "integrity": "sha512-SdlRlOoQw4WKD4vtb/n5gUkobEABYBEOo8fRE4L8CtBkyWDSvIrReTfKvQ/Jc/LQqDaaZ5iv1iMSQzKCUr1n1A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.4.tgz", + "integrity": "sha512-wVR8QxhyXsFcD/cORtJwGQodeeaDf0OxcHie8ema4VgFeqwYkFsDPnSrIRSytX8xR6nKPAH89WnwTcaU608b/Q==", "requires": { "@npmcli/name-from-folder": "^1.0.1", "glob": "^7.1.6", @@ -11599,11 +11584,6 @@ "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" }, - "byte-size": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-7.0.1.tgz", - "integrity": "sha512-crQdqyCwhokxwV1UyDzLZanhkugAgft7vt0qbbdt60C6Zf3CAiGmtUCylbtYwrU6loOUw3euGrNtW1J651ot1A==" - }, "cacache": { "version": "15.2.0", "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.2.0.tgz", @@ -12357,9 +12337,9 @@ } }, "eslint": { - "version": "7.31.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.31.0.tgz", - "integrity": "sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA==", + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "dev": true, "requires": { "@babel/code-frame": "7.12.11", @@ -12446,36 +12426,30 @@ } }, "eslint-import-resolver-node": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", - "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.5.tgz", + "integrity": "sha512-XMoPKjSpXbkeJ7ZZ9icLnJMTY5Mc1kZbCakHquaFsXPpyWOwK0TK6CODO+0ca54UoM9LKOxyUNnoVZRl8TeaAg==", "dev": true, "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" + "debug": "^3.2.7", + "resolve": "^1.20.0" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, "eslint-module-utils": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.1.tgz", - "integrity": "sha512-ZXI9B8cxAJIH4nfkhTwcRTEAnrVfobYqwjWy/QMCZ8rHkZHFjf9yO4BzpiF9kCSfNlMG54eKigISHpX0+AaT4A==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz", + "integrity": "sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==", "dev": true, "requires": { "debug": "^3.2.7", @@ -12504,17 +12478,17 @@ } }, "eslint-plugin-import": { - "version": "2.23.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", - "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.0.tgz", + "integrity": "sha512-Kc6xqT9hiYi2cgybOc0I2vC9OgAYga5o/rAFinam/yF/t5uBqxQbauNPMC6fgb640T/89P0gFoO27FOilJ/Cqg==", "dev": true, "requires": { "array-includes": "^3.1.3", "array.prototype.flat": "^1.2.4", "debug": "^2.6.9", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.1", + "eslint-import-resolver-node": "^0.3.5", + "eslint-module-utils": "^2.6.2", "find-up": "^2.0.0", "has": "^1.0.3", "is-core-module": "^2.4.0", @@ -13700,9 +13674,9 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsdom": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.6.0.tgz", - "integrity": "sha512-Ty1vmF4NHJkolaEmdjtxTfSfkdb8Ywarwf63f+F8/mDD1uLSSWDxDuMiZxiPhwunLrn9LOSVItWj4bLYsLN3Dg==", + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", "dev": true, "requires": { "abab": "^2.0.5", @@ -13730,7 +13704,7 @@ "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^8.5.0", - "ws": "^7.4.5", + "ws": "^7.4.6", "xml-name-validator": "^3.0.0" }, "dependencies": { @@ -17412,9 +17386,9 @@ } }, "tar": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.6.tgz", - "integrity": "sha512-oaWyu5dQbHaYcyZCTfyPpC+VmI62/OM2RTUYavTk1MDr1cwW5Boi3baeYQKiZbY2uSQJGr+iMOzb/JFxLrft+g==", + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.8.tgz", + "integrity": "sha512-sb9b0cp855NbkMJcskdSYA7b11Q8JsX4qe4pyUAfHp+Y6jBjJeek2ZVlwEfWayshEIwlIzXx0Fain3QG9JPm2A==", "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", diff --git a/package.json b/package.json index 357e066a5efa1..cee4f44d8cb68 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "7.20.5", + "version": "7.20.6", "name": "npm", "description": "a package manager for JavaScript", "workspaces": [ @@ -53,16 +53,16 @@ "./package.json": "./package.json" }, "dependencies": { - "@npmcli/arborist": "^2.8.0", + "@npmcli/arborist": "^2.8.1", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^2.2.0", + "@npmcli/map-workspaces": "^1.0.4", "@npmcli/package-json": "^1.0.1", "@npmcli/run-script": "^1.8.5", "abbrev": "~1.1.1", "ansicolors": "~0.3.2", "ansistyles": "~0.1.3", "archy": "~1.0.0", - "byte-size": "^7.0.1", "cacache": "^15.2.0", "chalk": "^4.1.2", "chownr": "^2.0.0", @@ -114,7 +114,7 @@ "rimraf": "^3.0.2", "semver": "^7.3.5", "ssri": "^8.0.1", - "tar": "^6.1.6", + "tar": "^6.1.8", "text-table": "~0.2.0", "tiny-relative-date": "^1.3.0", "treeverse": "^1.0.4", @@ -126,13 +126,13 @@ "@npmcli/arborist", "@npmcli/ci-detect", "@npmcli/config", + "@npmcli/map-workspaces", "@npmcli/package-json", "@npmcli/run-script", "abbrev", "ansicolors", "ansistyles", "archy", - "byte-size", "cacache", "chalk", "chownr", diff --git a/tap-snapshots/smoke-tests/index.js.test.cjs b/tap-snapshots/smoke-tests/index.js.test.cjs index 0a79e38cdfa03..c1316e04d7ad9 100644 --- a/tap-snapshots/smoke-tests/index.js.test.cjs +++ b/tap-snapshots/smoke-tests/index.js.test.cjs @@ -340,6 +340,7 @@ exports[`smoke-tests/index.js TAP npm install dev dep > should have expected dev "requires": true, "packages": { "": { + "name": "project", "version": "1.0.0", "license": "ISC", "dependencies": { @@ -426,6 +427,7 @@ exports[`smoke-tests/index.js TAP npm install prodDep@version > should have expe "requires": true, "packages": { "": { + "name": "project", "version": "1.0.0", "license": "ISC", "dependencies": { @@ -614,6 +616,7 @@ exports[`smoke-tests/index.js TAP npm uninstall > should have expected uninstall "requires": true, "packages": { "": { + "name": "project", "version": "1.0.0", "license": "ISC", "dependencies": { @@ -671,6 +674,7 @@ exports[`smoke-tests/index.js TAP npm update dep > should have expected update l "requires": true, "packages": { "": { + "name": "project", "version": "1.0.0", "license": "ISC", "dependencies": { diff --git a/tap-snapshots/test/lib/view.js.test.cjs b/tap-snapshots/test/lib/view.js.test.cjs index 41d7a80fe3b16..27ba7b1eb6927 100644 --- a/tap-snapshots/test/lib/view.js.test.cjs +++ b/tap-snapshots/test/lib/view.js.test.cjs @@ -77,7 +77,7 @@ dist .tarball:http://hm.blue.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -94,7 +94,7 @@ dist .tarball:http://hm.blue.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -118,7 +118,7 @@ dist .tarball:http://hm.green.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dependencies: red: 1.0.0 @@ -178,7 +178,7 @@ dist .tarball:http://hm.orange.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -200,7 +200,7 @@ dist .tarball:http://hm.green.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dependencies: red: 1.0.0 @@ -223,7 +223,7 @@ dist .tarball:http://hm.pink.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -238,7 +238,7 @@ dist .tarball:http://hm.black.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dependencies: 0: 1.0.0 @@ -280,7 +280,7 @@ dist .tarball:http://hm.cyan.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -297,7 +297,7 @@ dist .tarball:http://hm.blue.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -401,7 +401,7 @@ dist .tarball:http://hm.green.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dependencies: red: 1.0.0 @@ -421,7 +421,7 @@ dist .tarball:http://hm.orange.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dist-tags: latest: 1.0.0 @@ -469,7 +469,7 @@ dist .tarball:http://hm.green.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dependencies: red: 1.0.0 @@ -496,7 +496,7 @@ dist .tarball:http://hm.pink.com/1.0.0.tgz .shasum:123 .integrity:--- -.unpackedSize:1 B +.unpackedSize:1 B dist-tags: latest: 1.0.0 diff --git a/test/lib/utils/tar.js b/test/lib/utils/tar.js index 2662d47ace486..19d94916945db 100644 --- a/test/lib/utils/tar.js +++ b/test/lib/utils/tar.js @@ -57,6 +57,8 @@ t.test('should log tarball contents with unicode', async (t) => { logTar({ files: [], bundled: [], + size: 0, + unpackedSize: 0, integrity: '', }, { unicode: true }) t.end() @@ -75,6 +77,8 @@ t.test('should default to npmlog', async (t) => { logTar({ files: [], bundled: [], + size: 0, + unpackedSize: 0, integrity: '', }) t.end()