From b0a4bd8a30b2e98a913f05d56e94e853da58c93c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 14 Feb 2017 00:35:58 -0800 Subject: [PATCH 01/10] deps: minimatch@3.0.3 --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 6459483..190cf4e 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "cacache": "^5.0.0", "dezalgo": "^1.0.3", "inflight": "^1.0.6", + "minimatch": "^3.0.3", "mississippi": "^1.2.0", "npm-registry-client": "^7.4.1", "realize-package-specifier": "^3.0.3", From 602729d3355124ea0e4c292d8a9c702421546e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 14 Feb 2017 00:36:28 -0800 Subject: [PATCH 02/10] util: added checksum-stream --- lib/util/checksum-stream.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 lib/util/checksum-stream.js diff --git a/lib/util/checksum-stream.js b/lib/util/checksum-stream.js new file mode 100644 index 0000000..6c6705b --- /dev/null +++ b/lib/util/checksum-stream.js @@ -0,0 +1,24 @@ +var crypto = require('crypto') +var through = require('mississippi').through + +module.exports = checksumStream +function checksumStream (digest, algorithm) { + var hash = crypto.createHash(algorithm || 'sha1') + var stream = through(function (chunk, enc, cb) { + hash.update(chunk, enc) + cb(null, chunk, enc) + }, function (cb) { + var streamDigest = hash.digest('hex') + if (digest && streamDigest !== digest) { + var err = new Error('checksum failed') + err.code = 'EBADCHECKSUM' + err.expected = digest + err.found = streamDigest + return cb(err) + } else { + stream.emit('digest', streamDigest) + cb() + } + }) + return stream +} From da7fa062fe6805192c1023376c4b825f5f22e9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 14 Feb 2017 00:38:31 -0800 Subject: [PATCH 03/10] manifest: standardize manifest format and centralize filling in deets --- lib/finalize-manifest.js | 129 +++++++++++++++++++++++++++++++++ lib/registry/manifest.js | 50 ++++--------- lib/registry/tarball.js | 10 +-- lib/util/extract-shrinkwrap.js | 68 ----------------- manifest.js | 4 +- 5 files changed, 151 insertions(+), 110 deletions(-) create mode 100644 lib/finalize-manifest.js delete mode 100644 lib/util/extract-shrinkwrap.js diff --git a/lib/finalize-manifest.js b/lib/finalize-manifest.js new file mode 100644 index 0000000..23809d2 --- /dev/null +++ b/lib/finalize-manifest.js @@ -0,0 +1,129 @@ +'use strict' + +var checksumStream = require('./util/checksum-stream') +var dezalgo = require('dezalgo') +var finished = require('mississippi').finished +var gunzip = require('./util/gunzip-maybe') +var minimatch = require('minimatch') +var normalize = require('normalize-package-data') +var optCheck = require('./util/opt-check') +var path = require('path') +var pipe = require('mississippi').pipe +var pipeline = require('mississippi').pipeline +var tar = require('tar-stream') +var through = require('mississippi').through + +module.exports = finalizeManifest +function finalizeManifest (pkg, spec, where, opts, cb) { + completeFromTarball(pkg, spec, where, opts, function (err) { + if (err) { return cb(err) } + // normalize should not add any fields, and once + // makeManifest completes, it should never be modified. + cb(null, new Manifest(pkg)) + }) +} + +module.exports.Manifest = Manifest +function Manifest (pkg) { + this.name = pkg.name + this.version = pkg.version + this.dependencies = pkg.dependencies || {} + this.optionalDependencies = pkg.optionalDependencies || {} + this.devDependencies = pkg.devDependencies || {} + var bundled = ( + pkg.bundledDependencies || + pkg.bundleDependencies || + false + ) + this.bundleDependencies = !!bundled.length || false + this.peerDependencies = pkg.peerDependencies || {} + + // This one depends entirely on each handler. + this._resolved = pkg._resolved + + // Filled in by completeFromTarball as needed. + this._shasum = pkg._shasum + this._shrinkwrap = pkg._shrinkwrap || null + this.bin = pkg.bin || null + + this._id = null // filled in by normalize-package-data, but unnecessary + + Object.preventExtensions(this) + normalize(this) + Object.freeze(this) +} + +// Some things aren't filled in by standard manifest fetching. +// If this function needs to do its work, it will grab the +// package tarball, extract it, and take whatever it needs +// from the stream. +function completeFromTarball (pkg, spec, where, opts, cb) { + cb = dezalgo(cb) + var needsShrinkwrap = !( + pkg._hasShrinkwrap === false || + pkg._shrinkwrap + ) + var needsBin = !!( + !pkg.bin && + pkg.directories && + pkg.directories.bin + ) + var needsShasum = !pkg._shasum + if (!needsShrinkwrap && !needsBin && !needsShasum) { + opts.log.silly('finalize-manifest', 'Skipping tarball extraction -- nothing needed.') + return cb(null) + } else { + opts = optCheck(opts) + opts.memoize = false + var tarball = require('./handlers/' + spec.type + '/tarball') + var tarData = tarball.fromManifest(pkg, spec, opts) + var shaStream = null + var extractorStream = null + + if (needsShrinkwrap || needsBin) { + opts.log.silly('finalize-manifest', 'parsing tarball for', spec.name) + var dirBin = pkg.directories && pkg.directories.bin + pkg.bin = pkg.bin || {} + var dataStream = tar.extract() + extractorStream = pipeline(gunzip(), dataStream) + dataStream.on('entry', function doEntry (header, fileStream, next) { + var filePath = header.name.replace(/[^/]+\//, '') + if (needsShrinkwrap && filePath === 'npm-shrinkwrap.json') { + var srData = '' + fileStream.on('data', function (d) { srData += d }) + + return finished(fileStream, function (err) { + if (err) { return dataStream.emit('error', err) } + try { + pkg._shrinkwrap = JSON.parse(srData) + next() + } catch (e) { + dataStream.emit('error', e) + } + }) + } else if (needsBin && minimatch(filePath, dirBin + '/**')) { + var relative = path.relative(dirBin, filePath) + if (relative && relative[0] !== '.') { + pkg.bin[path.basename(relative)] = path.join(dirBin, relative) + } + } + // Drain and get next one + fileStream.on('data', function () {}) + next() + }) + } else { + extractorStream = through() + } + if (needsShasum) { + shaStream = checksumStream(null, opts.hashAlgorithm) + shaStream.on('digest', function (d) { + pkg._shasum = d + }) + } else { + shaStream = through() + } + // Drain the end stream + extractorStream.on('data', function () {}) + return pipe(tarData, shaStream, extractorStream, cb) + } +} diff --git a/lib/registry/manifest.js b/lib/registry/manifest.js index 7ddb7fe..d83b523 100644 --- a/lib/registry/manifest.js +++ b/lib/registry/manifest.js @@ -1,12 +1,10 @@ 'use strict' -var extractShrinkwrap = require('../util/extract-shrinkwrap') var optCheck = require('../util/opt-check') var pickManifest = require('./pick-manifest') var pickRegistry = require('./pick-registry') var url = require('url') var request = require('./request') -var tarball = require('./tarball') module.exports = manifest function manifest (spec, opts, cb) { @@ -28,13 +26,21 @@ function manifest (spec, opts, cb) { defaultTag: opts.defaultTag }, function (err, manifest) { if (err) { return cb(err) } - opts.log.silly( - 'registry.manifest', - spec.name + '@' + spec.spec, - 'resolved to', - manifest.name + '@' + manifest.version + // Done here instead of ./finalize-manifest because these fields + // have to be filled in differently depending on type. + if (!manifest._shasum) { + manifest._shasum = manifest.dist && manifest.dist.shasum + } + manifest._resolved = ( + manifest.dist && manifest.dist.tarball + ) || url.resolve( + registry, + '/' + manifest.name + + '/-/' + manifest.name + + '-' + manifest.version + + '.tgz' ) - ensureShrinkwrap(manifest, registry, opts, cb) + cb(null, manifest) }) }) } @@ -45,31 +51,3 @@ function metadataUrl (registry, name) { : registry return url.resolve(normalized, name) } - -function ensureShrinkwrap (manifest, registry, opts, cb) { - if (manifest._hasShrinkwrap === false || manifest._shrinkwrap || !manifest.dist) { - opts.log.silly('registry.manifest', 'shrinkwrap extraction not needed') - cb(null, manifest) - } else { - opts.log.silly('registry.manifest', 'extracting shrinkwrap') - opts.memoize = false - var shrinkwrap - var tarstream = tarball.fromManifest(manifest, registry, opts) - extractShrinkwrap(tarstream, opts, function (err, sr) { - if (err) { return cb(err) } - shrinkwrap = sr - }) - tarstream.on('data', function () {}) - tarstream.on('error', cb) - tarstream.on('end', function () { - manifest._hasShrinkwrap = !!shrinkwrap - manifest._shrinkwrap = shrinkwrap - if (shrinkwrap) { - opts.log.silly('registry.manifest', 'shrinkwrap found') - } else { - opts.log.silly('registry.manifest', 'no shrinkwrap') - } - cb(null, manifest) - }) - } -} diff --git a/lib/registry/tarball.js b/lib/registry/tarball.js index 48437bf..633ba44 100644 --- a/lib/registry/tarball.js +++ b/lib/registry/tarball.js @@ -10,7 +10,6 @@ var through = require('mississippi').through module.exports = tarball function tarball (spec, opts) { opts = optCheck(opts) - var registry = pickRegistry(spec, opts) opts.log.verbose( 'registry.tarball', 'looking up registry-based metadata for ', spec @@ -23,7 +22,7 @@ function tarball (spec, opts) { 'registry metadata found. Downloading ', manifest.name + '@' + manifest.version ) pipe( - fromManifest(manifest, registry), + fromManifest(manifest, spec, opts), stream ) }) @@ -31,9 +30,10 @@ function tarball (spec, opts) { } module.exports.fromManifest = fromManifest -function fromManifest (manifest, registry, opts) { +function fromManifest (manifest, spec, opts) { opts = optCheck(opts) - var uri = manifest.dist && manifest.dist.tarball - opts.digest = manifest.dist && manifest.dist.shasum + var registry = pickRegistry(spec, opts) + var uri = manifest._resolved + opts.digest = manifest._shasum return request.stream(uri, registry, opts) } diff --git a/lib/util/extract-shrinkwrap.js b/lib/util/extract-shrinkwrap.js deleted file mode 100644 index 2b7d50a..0000000 --- a/lib/util/extract-shrinkwrap.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict' - -var finished = require('mississippi').finished -var gunzip = require('./gunzip-maybe') -var pipe = require('mississippi').pipe -var pipeline = require('mississippi').pipeline -var through = require('mississippi').through - -// `tar-stream` is significantly faster than `node-tar`, but there's -// a risk that `tar-stream` can cause some incompatibilities. -// -// It's worth keeping an eye out for issues caused by this, and -// swap out the module for node-tar if they rear their head. -var tar = require('tar-stream') - -// Picks out just the `npm-shrinkwrap.json` from a package -// tarball (coming through `pkgStream`), and stops parsing the -// tarball as soon as the file is found. -module.exports = extractShrinkwrap -function extractShrinkwrap (pkgStream, opts, cb) { - var extract = tar.extract() - - // The extra `through` is to compensate for misbehaving `pkgStream`s. - // For example, `request` streams are notoriously unreliable. - // This is a bit of defensive programming, not a fix for - // a specific known example of an issue. - var unzipped = pipeline(through(), gunzip(), extract) - - var shrinkwrap = null // we'll pop the data in here if found. - extract.on('entry', function onEntry (header, fileStream, next) { - if (header.name === 'package/npm-shrinkwrap.json') { - opts.log.silly('extract-shrinkwrap', 'found shrinkwrap') - // got a shrinkwrap! Now we don't need to look for entries anymore. - extract.removeListener('entry', onEntry) - - // Grab all the file data off the entry fileStream. - var data = '' - fileStream.on('data', function (d) { data += d }) - - finished(fileStream, function (err) { - if (err) { return extract.emit('error', err) } - try { - shrinkwrap = JSON.parse(data) - } catch (e) { - extract.emit('error', e) - } - // By destroying `unzipped`, this *should* stop `tar-stream` - // from continuing to waste resources on tarball parsing. - unzipped.unpipe() - cb(null, shrinkwrap) - }) - } else { - // Not a shrinkwrap. Autodrain this entry, and move on to the next. - fileStream.resume() - next() - } - }) - - // Any other streams that `pkgStream` is being piped to should - // remain unaffected by this, although there might be confusion - // around backpressure issues. - pipe(pkgStream, unzipped, function (err) { - // If we already successfully emitted a shrinkwrap, - // we literally don't care about any errors. - // Issues with `pkgStream` can be handled elsewhere if needed. - if (!shrinkwrap) { cb(err) } - }) -} diff --git a/manifest.js b/manifest.js index 0743ee6..f6e7d3a 100644 --- a/manifest.js +++ b/manifest.js @@ -1,5 +1,6 @@ 'use strict' +var finalizeManifest = require('./lib/finalize-manifest') var optCheck = require('./lib/util/opt-check') var rps = require('realize-package-specifier') @@ -17,7 +18,8 @@ function manifest (spec, opts, cb) { if (err) { return cb(err) } var fetcher = handlers[res.type] || (handlers[res.type] = require('./lib/handlers/' + res.type + '/manifest')) fetcher(res, opts, function (err, mani) { - cb(err, mani) + if (err) { return cb(err) } + finalizeManifest(mani, res, opts.where, opts, cb) }) }) } From 06df857f39836841dc606de7e16a4f9d8ee75818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 14 Feb 2017 01:17:02 -0800 Subject: [PATCH 04/10] lib: moved extract-stream out of util I would rather keep util for extractable/reusable/generic utilities. extract-stream has domain-specific knowledge. --- extract.js | 2 +- lib/{util => }/extract-stream.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename lib/{util => }/extract-stream.js (97%) diff --git a/extract.js b/extract.js index 008d194..1a96d24 100644 --- a/extract.js +++ b/extract.js @@ -1,7 +1,7 @@ 'use strict' var cache = require('./lib/cache') -var extractStream = require('./lib/util/extract-stream') +var extractStream = require('./lib/extract-stream') var pipe = require('mississippi').pipe var optCheck = require('./lib/util/opt-check') var rps = require('realize-package-specifier') diff --git a/lib/util/extract-stream.js b/lib/extract-stream.js similarity index 97% rename from lib/util/extract-stream.js rename to lib/extract-stream.js index bde642e..d9b569f 100644 --- a/lib/util/extract-stream.js +++ b/lib/extract-stream.js @@ -1,6 +1,6 @@ 'use strict' -var gunzip = require('./gunzip-maybe') +var gunzip = require('./lib/gunzip-maybe') var path = require('path') var pipeline = require('mississippi').pipeline var tar = require('tar-fs') From 65939fc832ceedd6540fb2e9e7d94d1b04235baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Tue, 14 Feb 2017 12:44:31 -0800 Subject: [PATCH 05/10] test: updating manifest tests to pass again --- test/registry.manifest.cache.js | 15 ++++++++++--- test/registry.manifest.js | 33 +++++++++++++++++++++------- test/registry.manifest.shrinkwrap.js | 6 +---- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/test/registry.manifest.cache.js b/test/registry.manifest.cache.js index 9472a99..7906557 100644 --- a/test/registry.manifest.cache.js +++ b/test/registry.manifest.cache.js @@ -7,20 +7,29 @@ var testDir = require('./util/test-dir') var tnock = require('./util/tnock') var CACHE = testDir(__filename) +var Manifest = require('../lib/finalize-manifest').Manifest var manifest = require('../manifest') -var PKG = { +var BASE = { name: 'foo', - version: '1.2.3' + version: '1.2.3', + _hasShrinkwrap: false, + _shasum: 'deadbeef', + _resolved: 'https://foo.bar/x.tgz', + dist: { + shasum: 'deadbeef', + tarball: 'https://foo.bar/x.tgz' + } } var META = { 'dist-tags': { latest: '1.2.3' }, versions: { - '1.2.3': PKG + '1.2.3': BASE } } +var PKG = new Manifest(BASE) npmlog.level = process.env.LOGLEVEL || 'silent' var OPTS = { diff --git a/test/registry.manifest.js b/test/registry.manifest.js index 6eda0db..cac27b0 100644 --- a/test/registry.manifest.js +++ b/test/registry.manifest.js @@ -4,11 +4,19 @@ var npmlog = require('npmlog') var test = require('tap').test var tnock = require('./util/tnock') +var Manifest = require('../lib/finalize-manifest').Manifest var manifest = require('../manifest') -var PKG = { +var BASE = { name: 'foo', - version: '1.2.3' + version: '1.2.3', + _hasShrinkwrap: false, + _shasum: 'deadbeef', + _resolved: 'https://foo.bar/x.tgz', + dist: { + shasum: 'deadbeef', + tarball: 'https://foo.bar/x.tgz' + } } var META = { @@ -35,7 +43,7 @@ var META = { name: 'foo', version: '1.2.1' }, - '1.2.3': PKG, + '1.2.3': BASE, '1.2.4': { name: 'foo', version: '1.2.4' @@ -46,6 +54,7 @@ var META = { } } } +var PKG = new Manifest(BASE) npmlog.level = process.env.LOGLEVEL || 'silent' var OPTS = { @@ -110,7 +119,7 @@ test('fetches manifest from registry by range', function (t) { manifest('foo@^1.2.0', OPTS, function (err, pkg) { if (err) { throw err } // Not 1.2.4 because 1.2.3 is `latest` - t.deepEqual(pkg, META.versions['1.2.3'], 'picked right manifest') + t.deepEqual(pkg, new Manifest(META.versions['1.2.3']), 'picked right manifest') t.end() }) }) @@ -121,7 +130,7 @@ test('fetches manifest from scoped registry by range', function (t) { srv.get('/@usr%2ffoo').reply(200, META) manifest('@usr/foo@^1.2.0', OPTS, function (err, pkg) { if (err) { throw err } - t.deepEqual(pkg, META.versions['1.2.3'], 'got scoped manifest from version') + t.deepEqual(pkg, new Manifest(META.versions['1.2.3']), 'got scoped manifest from version') t.end() }) }) @@ -241,13 +250,21 @@ test('package requests are case-sensitive', function (t) { t.plan(2) var srv = tnock(t, OPTS.registry) - var CASEDPKG = { + var CASEDBASE = { name: 'Foo', - version: '1.2.3' + version: '1.2.3', + _hasShrinkwrap: false, + _shasum: 'deadbeef', + _resolved: 'https://foo.bar/x.tgz', + dist: { + shasum: 'deadbeef', + tarball: 'https://foo.bar/x.tgz' + } } + var CASEDPKG = new Manifest(CASEDBASE) srv.get('/Foo').reply(200, { versions: { - '1.2.3': CASEDPKG + '1.2.3': CASEDBASE } }) manifest('Foo@1.2.3', OPTS, function (err, pkg) { diff --git a/test/registry.manifest.shrinkwrap.js b/test/registry.manifest.shrinkwrap.js index c7a03b7..57a23b7 100644 --- a/test/registry.manifest.shrinkwrap.js +++ b/test/registry.manifest.shrinkwrap.js @@ -21,10 +21,7 @@ var OPTS = { var PKG = { name: 'foo', - version: '1.2.3', - dist: { - tarball: OPTS.registry + '/foo/-/foo-1.2.3.tgz' - } + version: '1.2.3' } var SHRINKWRAP = { @@ -63,7 +60,6 @@ test('fetches shrinkwrap data if missing + required', function (t) { manifest('foo@1.2.3', OPTS, function (err, pkg) { if (err) { throw err } t.ok(pkg, 'got a package manifest') - t.equal(pkg._hasShrinkwrap, true, '_hasShrinkwrap set') t.deepEqual(pkg._shrinkwrap, SHRINKWRAP, 'got a shrinkwrap') t.end() }) From ee9cf3714d890b27065bff521f4a0f0cc2da44f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Thu, 16 Feb 2017 15:10:01 -0800 Subject: [PATCH 06/10] fix(manifest): registry-fetched manifests should prioritize the shasum in dist --- lib/registry/manifest.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/registry/manifest.js b/lib/registry/manifest.js index d83b523..94eb484 100644 --- a/lib/registry/manifest.js +++ b/lib/registry/manifest.js @@ -28,9 +28,9 @@ function manifest (spec, opts, cb) { if (err) { return cb(err) } // Done here instead of ./finalize-manifest because these fields // have to be filled in differently depending on type. - if (!manifest._shasum) { - manifest._shasum = manifest.dist && manifest.dist.shasum - } + manifest._shasum = ( + manifest.dist && manifest.dist.shasum + ) || manifest._shasum manifest._resolved = ( manifest.dist && manifest.dist.tarball ) || url.resolve( From 1e75c306c958986ea0c5e3d79134956313d32f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Thu, 16 Feb 2017 15:11:31 -0800 Subject: [PATCH 07/10] test(manifest): make it a bit clearer what comes out of where --- test/registry.manifest.cache.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/registry.manifest.cache.js b/test/registry.manifest.cache.js index 7906557..f796eb9 100644 --- a/test/registry.manifest.cache.js +++ b/test/registry.manifest.cache.js @@ -10,17 +10,24 @@ var CACHE = testDir(__filename) var Manifest = require('../lib/finalize-manifest').Manifest var manifest = require('../manifest') +// This is what the server sends var BASE = { name: 'foo', version: '1.2.3', _hasShrinkwrap: false, - _shasum: 'deadbeef', - _resolved: 'https://foo.bar/x.tgz', dist: { shasum: 'deadbeef', tarball: 'https://foo.bar/x.tgz' } } +// This is what's returned by finalize-manifest +var PKG = new Manifest({ + name: 'foo', + version: '1.2.3', + _hasShrinkwrap: false, + _shasum: BASE.dist.shasum, + _resolved: BASE.dist.tarball +}) var META = { 'dist-tags': { latest: '1.2.3' @@ -29,7 +36,6 @@ var META = { '1.2.3': BASE } } -var PKG = new Manifest(BASE) npmlog.level = process.env.LOGLEVEL || 'silent' var OPTS = { From 486dc5c0a2a1c6903fb39450aab6f4b457e97be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Thu, 16 Feb 2017 15:13:53 -0800 Subject: [PATCH 08/10] fix(util): make checksum-stream use strict mode --- lib/util/checksum-stream.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/util/checksum-stream.js b/lib/util/checksum-stream.js index 6c6705b..94d0d6e 100644 --- a/lib/util/checksum-stream.js +++ b/lib/util/checksum-stream.js @@ -1,3 +1,5 @@ +'use strict' + var crypto = require('crypto') var through = require('mississippi').through From 1882d1852e067a64b728bce96ae72d7ad25a3008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Thu, 16 Feb 2017 16:44:55 -0800 Subject: [PATCH 09/10] test(manifest): removed extract-shrinkwrap test and stubbed replacements --- test/extract-stream.js | 23 ++++++++++ test/finalize-manifest.js | 14 ++++++ test/util.extract-shrinkwrap.js | 75 --------------------------------- 3 files changed, 37 insertions(+), 75 deletions(-) create mode 100644 test/extract-stream.js create mode 100644 test/finalize-manifest.js delete mode 100644 test/util.extract-shrinkwrap.js diff --git a/test/extract-stream.js b/test/extract-stream.js new file mode 100644 index 0000000..07183aa --- /dev/null +++ b/test/extract-stream.js @@ -0,0 +1,23 @@ +'use strict' + +var fs = require('fs') +var npmlog = require('npmlog') +var pipe = require('mississippi').pipe +var test = require('tap').test + +require('./util/test-dir')(__filename) + +var extractStream = require('../lib/extract-stream') + +npmlog.level = process.env.LOGLEVEL || 'silent' +var OPTS = { + log: npmlog +} + +test('basic extraction') +test('excludes symlinks') +test('renames .gitignore to .npmignore if not present') +test('accepts gid and uid opts') +test('accepts dmode/fmode/umask opts') +test('automatically handles gzipped tarballs') +test('strips first item in path, even if not `package/`') diff --git a/test/finalize-manifest.js b/test/finalize-manifest.js new file mode 100644 index 0000000..bd07551 --- /dev/null +++ b/test/finalize-manifest.js @@ -0,0 +1,14 @@ +'use strict' + +var test = require('tap').test + +require('./util/test-dir')(__filename) + +var finalizeManifest = require('../lib/finalize-manifest') + +test('returns a manifest with the right fields') +test('defaults all field to expected types + values') +test('manifest returned is immutable + inextensible') +test('fills in shrinkwrap if missing') +test('fills in shasum if missing') +test('fills in `bin` if `directories.bin` present') diff --git a/test/util.extract-shrinkwrap.js b/test/util.extract-shrinkwrap.js deleted file mode 100644 index 1a358ac..0000000 --- a/test/util.extract-shrinkwrap.js +++ /dev/null @@ -1,75 +0,0 @@ -'use strict' - -var fs = require('fs') -var npmlog = require('npmlog') -var pipe = require('mississippi').pipe -var test = require('tap').test - -require('./util/test-dir')(__filename) - -var extractShrinkwrap = require('../lib/util/extract-shrinkwrap') - -var SHRINKWRAP = { - 'name': 'test', - 'version': '1.0.0', - 'dependencies': { - 'eggplant': { - 'version': '1.0.2', - 'from': 'eggplant@latest', - 'resolved': 'https://registry.npmjs.org/eggplant/-/eggplant-1.0.2.tgz' - } - } -} - -var HAS_SHRINKWRAP = '../../fixtures/has-shrinkwrap.tgz' -var NO_SHRINKWRAP = '../../fixtures/no-shrinkwrap.tgz' -var DEST = './copy.tgz' - -test('basic shrinkwrap extraction', function (t) { - var input = fs.createReadStream(HAS_SHRINKWRAP) - var output = fs.createWriteStream(DEST) - - t.plan(3) - extractShrinkwrap(input, {log: npmlog}, function (err, sr) { - if (err) { throw err } - t.ok(sr, 'got a shrinkwrap back!') - t.deepEqual(sr, SHRINKWRAP, 'shrinkwrap data correct') - }) - pipe(input, output, function (err) { - if (err) { throw err } - fs.readFile(HAS_SHRINKWRAP, 'utf8', function (err, src) { - if (err) { throw err } - fs.readFile(DEST, 'utf8', function (err, dest) { - if (err) { throw err } - t.equal(src, dest, 'data fully copied') - }) - }) - }) -}) - -test('no shrinkwrap in tarball', function (t) { - var input = fs.createReadStream(NO_SHRINKWRAP) - var output = fs.createWriteStream(DEST) - - t.plan(2) - extractShrinkwrap(input, {log: npmlog}, function (err, sr) { - if (err) { throw err } - t.notOk(sr, 'no shrinkwrap returned') - }) - pipe(input, output, function (err) { - if (err) { throw err } - fs.readFile(NO_SHRINKWRAP, 'utf8', function (err, src) { - if (err) { throw err } - fs.readFile(DEST, 'utf8', function (err, dest) { - if (err) { throw err } - t.equal(src, dest, 'data fully copied') - }) - }) - }) -}) - -test('stops parsing tarball after shrinkwrap found') -test('source stream continues after shrinkwrap found') -test('source stream errors trigger extract error') -test('only calls cb once if stream error after shrinkwrap found') -test('works fine when teeing a `request` stream') From 53fc6a6b629bdf4809da77ba39231fba721bfc9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kat=20March=C3=A1n?= Date: Thu, 16 Feb 2017 16:46:07 -0800 Subject: [PATCH 10/10] fix(extract-stream): oops @ path lol --- lib/extract-stream.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/extract-stream.js b/lib/extract-stream.js index d9b569f..a7f0457 100644 --- a/lib/extract-stream.js +++ b/lib/extract-stream.js @@ -1,6 +1,6 @@ 'use strict' -var gunzip = require('./lib/gunzip-maybe') +var gunzip = require('./util/gunzip-maybe') var path = require('path') var pipeline = require('mississippi').pipeline var tar = require('tar-fs')