From 113e1a3af2f487c753b8871d51924682283c89fc Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 1 May 2018 15:53:03 -0700 Subject: [PATCH] inflate-shrinkwrap: Infer versions from tarballs to self heal Credit: @iarna --- lib/install/inflate-shrinkwrap.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/install/inflate-shrinkwrap.js b/lib/install/inflate-shrinkwrap.js index ef1018faa21f1..06a41191ad7bf 100644 --- a/lib/install/inflate-shrinkwrap.js +++ b/lib/install/inflate-shrinkwrap.js @@ -69,6 +69,26 @@ 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) const usesIntegrity = ( @@ -76,6 +96,12 @@ function inflatableChild (onDiskChild, name, topPath, tree, sw, requested, opts) 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.