diff --git a/lib/install.js b/lib/install.js index 3580cdd003..dcd301e258 100644 --- a/lib/install.js +++ b/lib/install.js @@ -1,12 +1,13 @@ 'use strict' -const { createWriteStream, promises: fs } = require('graceful-fs') +const { createReadStream, createWriteStream, promises: fs } = require('graceful-fs') const os = require('os') const { backOff } = require('exponential-backoff') -const tar = require('tar') +const { unpackTar } = require('modern-tar/fs') const path = require('path') const { Transform, promises: { pipeline } } = require('stream') const crypto = require('crypto') +const { createGunzip } = require('zlib') const log = require('./log') const semver = require('semver') const { download } = require('./download') @@ -173,7 +174,6 @@ async function install (gyp, argv) { // now download the node tarball const tarPath = gyp.opts.tarball - let extractErrors = false let extractCount = 0 const contentShasums = {} const expectShasums = {} @@ -192,10 +192,11 @@ async function install (gyp, argv) { return isValid } - function onwarn (code, message) { - extractErrors = true - log.error('error while extracting tarball', code, message) - } + const extract = () => unpackTar(tarExtractDir, { + strict: true, + strip: 1, + filter: header => isValid(header.name) + }) // download the tarball and extract! // Omitted on Windows if only new node.lib is required @@ -208,13 +209,8 @@ async function install (gyp, argv) { try { if (shouldDownloadTarball) { if (tarPath) { - await tar.extract({ - file: tarPath, - strip: 1, - filter: isValid, - onwarn, - cwd: tarExtractDir - }) + // modern-tar recommends 256 KiB chunks for optimal extraction performance + await pipeline(createReadStream(tarPath, { highWaterMark: 256 * 1024 }), createGunzip(), extract()) } else { try { const res = await download(gyp, release.tarballUrl) @@ -231,12 +227,8 @@ async function install (gyp, argv) { contentShasums[filename] = checksum log.verbose('content checksum', filename, checksum) }), - tar.extract({ - strip: 1, - cwd: tarExtractDir, - filter: isValid, - onwarn - }) + createGunzip(), + extract() ) } catch (err) { // something went wrong downloading the tarball? @@ -250,7 +242,7 @@ async function install (gyp, argv) { } // invoked after the tarball has finished being extracted - if (extractErrors || extractCount === 0) { + if (extractCount === 0) { throw new Error('There was a fatal problem while downloading/extracting the tarball') } diff --git a/package.json b/package.json index 4b65ab84b2..8fb369b871 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "nopt": "^10.0.0", "proc-log": "^7.0.0", "semver": "^7.3.5", - "tar": "^7.5.4", + "modern-tar": "^0.8.4", "tinyglobby": "^0.2.12", "undici": "^8.4.1", "which": "^7.0.0"