summaryrefslogtreecommitdiff
path: root/deps/npm/lib/install/inflate-shrinkwrap.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/npm/lib/install/inflate-shrinkwrap.js')
-rw-r--r--deps/npm/lib/install/inflate-shrinkwrap.js81
1 files changed, 54 insertions, 27 deletions
diff --git a/deps/npm/lib/install/inflate-shrinkwrap.js b/deps/npm/lib/install/inflate-shrinkwrap.js
index 43ac9136f0..bf1ab70657 100644
--- a/deps/npm/lib/install/inflate-shrinkwrap.js
+++ b/deps/npm/lib/install/inflate-shrinkwrap.js
@@ -14,6 +14,9 @@ const realizeShrinkwrapSpecifier = require('./realize-shrinkwrap-specifier.js')
const validate = require('aproba')
const path = require('path')
const isRegistry = require('../utils/is-registry.js')
+const hasModernMeta = require('./has-modern-meta.js')
+const ssri = require('ssri')
+const npa = require('npm-package-arg')
module.exports = function (tree, sw, opts, finishInflating) {
if (!fetchPackageMetadata) {
@@ -66,11 +69,43 @@ function normalizePackageDataNoErrors (pkg) {
}
}
+function quotemeta (str) {
+ return str.replace(/([^A-Za-z_0-9/])/g, '\\$1')
+}
+
+function tarballToVersion (name, tb) {
+ const registry = quotemeta(npm.config.get('registry'))
+ .replace(/https?:/, 'https?:')
+ .replace(/([^/])$/, '$1/')
+ let matchRegTarball
+ if (name) {
+ const nameMatch = quotemeta(name)
+ matchRegTarball = new RegExp(`^${registry}${nameMatch}/-/${nameMatch}-(.*)[.]tgz$`)
+ } else {
+ matchRegTarball = new RegExp(`^${registry}(.*)?/-/\\1-(.*)[.]tgz$`)
+ }
+ const match = tb.match(matchRegTarball)
+ if (!match) return
+ return match[2] || match[1]
+}
+
function inflatableChild (onDiskChild, name, topPath, tree, sw, requested, opts) {
validate('OSSOOOO|ZSSOOOO', arguments)
- if (onDiskChild && childIsEquivalent(sw, requested, onDiskChild)) {
+ const usesIntegrity = (
+ requested.registry ||
+ requested.type === 'remote' ||
+ requested.type === 'file'
+ )
+ const regTarball = tarballToVersion(name, sw.version)
+ if (regTarball) {
+ sw.resolved = sw.version
+ sw.version = regTarball
+ }
+ if (sw.requires) Object.keys(sw.requires).map(_ => { sw.requires[_] = tarballToVersion(_, sw.requires[_]) || sw.requires[_] })
+ const modernLink = requested.type === 'directory' && !sw.from
+ if (hasModernMeta(onDiskChild) && childIsEquivalent(sw, requested, onDiskChild)) {
// The version on disk matches the shrinkwrap entry.
- if (!onDiskChild.fromShrinkwrap) onDiskChild.fromShrinkwrap = true
+ if (!onDiskChild.fromShrinkwrap) onDiskChild.fromShrinkwrap = requested
onDiskChild.package._requested = requested
onDiskChild.package._spec = requested.rawSpec
onDiskChild.package._where = topPath
@@ -88,7 +123,7 @@ function inflatableChild (onDiskChild, name, topPath, tree, sw, requested, opts)
onDiskChild.swRequires = sw.requires
tree.children.push(onDiskChild)
return BB.resolve(onDiskChild)
- } else if ((sw.version && sw.integrity) || sw.bundled) {
+ } else if ((sw.version && (sw.integrity || !usesIntegrity) && (requested.type !== 'directory' || modernLink)) || sw.bundled) {
// The shrinkwrap entry has an integrity field. We can fake a pkg to get
// the installer to do a content-address fetch from the cache, if possible.
return BB.resolve(makeFakeChild(name, topPath, tree, sw, requested))
@@ -100,13 +135,18 @@ function inflatableChild (onDiskChild, name, topPath, tree, sw, requested, opts)
}
}
+function isGit (sw) {
+ const version = npa.resolve(sw.name, sw.version)
+ return (version && version.type === 'git')
+}
+
function makeFakeChild (name, topPath, tree, sw, requested) {
const from = sw.from || requested.raw
const pkg = {
name: name,
version: sw.version,
_id: name + '@' + sw.version,
- _resolved: adaptResolved(requested, sw.resolved),
+ _resolved: sw.resolved || (isGit(sw) && sw.version),
_requested: requested,
_optional: sw.optional,
_development: sw.dev,
@@ -127,15 +167,15 @@ function makeFakeChild (name, topPath, tree, sw, requested) {
}
const child = createChild({
package: pkg,
- loaded: true,
+ loaded: false,
parent: tree,
children: [],
- fromShrinkwrap: true,
+ fromShrinkwrap: requested,
fakeChild: sw,
fromBundle: sw.bundled ? tree.fromBundle || tree : null,
path: childPath(tree.path, pkg),
- realpath: childPath(tree.realpath, pkg),
- location: tree.location + '/' + pkg.name,
+ realpath: requested.type === 'directory' ? requested.fetchSpec : childPath(tree.realpath, pkg),
+ location: (tree.location === '/' ? '' : tree.location + '/') + pkg.name,
isLink: requested.type === 'directory',
isInLink: tree.isLink,
swRequires: sw.requires
@@ -144,23 +184,6 @@ function makeFakeChild (name, topPath, tree, sw, requested) {
return child
}
-function adaptResolved (requested, resolved) {
- const registry = requested.scope
- ? npm.config.get(`${requested.scope}:registry`) || npm.config.get('registry')
- : npm.config.get('registry')
- if (!isRegistry(requested) || (resolved && resolved.indexOf(registry) === 0)) {
- // Nothing to worry about here. Pass it through.
- return resolved
- } else {
- // We could fast-path for registry.npmjs.org here, but if we do, it
- // would end up getting written back to the `resolved` field. By always
- // returning `null` for other registries, `pacote.extract()` will take
- // care of any required metadata fetches internally, without altering
- // the tree we're going to write out to shrinkwrap/lockfile.
- return null
- }
-}
-
function fetchChild (topPath, tree, sw, requested) {
return fetchPackageMetadata(requested, topPath).then((pkg) => {
pkg._from = sw.from || requested.raw
@@ -178,7 +201,7 @@ function fetchChild (topPath, tree, sw, requested) {
path: childPath(tree.path, pkg),
realpath: isLink ? requested.fetchSpec : childPath(tree.realpath, pkg),
children: pkg._bundled || [],
- location: tree.location + '/' + pkg.name,
+ location: (tree.location === '/' ? '' : tree.location + '/') + pkg.name,
fromBundle: null,
isLink: isLink,
isInLink: tree.isLink,
@@ -196,7 +219,11 @@ function fetchChild (topPath, tree, sw, requested) {
function childIsEquivalent (sw, requested, child) {
if (!child) return false
if (child.fromShrinkwrap) return true
- if (sw.integrity && child.package._integrity === sw.integrity) return true
+ if (
+ sw.integrity &&
+ child.package._integrity &&
+ ssri.parse(sw.integrity).match(child.package._integrity)
+ ) return true
if (child.isLink && requested.type === 'directory') return path.relative(child.realpath, requested.fetchSpec) === ''
if (sw.resolved) return child.package._resolved === sw.resolved