Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorKat Marchán <kzm@sykosomatic.org>2017-05-16 06:44:53 +0300
committerRebecca Turner <me@re-becca.org>2017-05-26 04:55:23 +0300
commit180e2981a5a2a7c43a2b35fda73b641abfde704c (patch)
treeba1f352aaaf683feabb23a18ceea9120eb5b8f07 /lib
parent2d346e9ba9e64cffffd2bdd0d19a2be2413ebb61 (diff)
feat(shrinkwrap): support extra metadata fields
Diffstat (limited to 'lib')
-rw-r--r--lib/install/read-shrinkwrap.js26
-rw-r--r--lib/shrinkwrap.js59
2 files changed, 70 insertions, 15 deletions
diff --git a/lib/install/read-shrinkwrap.js b/lib/install/read-shrinkwrap.js
index bf941a49c..b18265bd4 100644
--- a/lib/install/read-shrinkwrap.js
+++ b/lib/install/read-shrinkwrap.js
@@ -8,6 +8,7 @@ const inflateShrinkwrap = require('./inflate-shrinkwrap.js')
const log = require('npmlog')
const parseJSON = require('../utils/parse-json.js')
const path = require('path')
+const ssri = require('ssri')
const readFileAsync = BB.promisify(fs.readFile)
@@ -15,28 +16,37 @@ module.exports = readShrinkwrap
function readShrinkwrap (child, next) {
if (child.package._shrinkwrap) return process.nextTick(next)
BB.join(
- readLockfile('npm-shrinkwrap.json', child),
+ maybeReadFile('npm-shrinkwrap.json', child),
// Don't read non-root lockfiles
- child.isTop && readLockfile('package-lock.json', child),
- (shrinkwrap, lockfile) => {
+ child.isTop && maybeReadFile('package-lock.json', child),
+ child.isTop && maybeReadFile('package.json', child),
+ (shrinkwrap, lockfile, pkgJson) => {
if (shrinkwrap && lockfile) {
log.warn('read-shrinkwrap', 'Ignoring package-lock.json because there is already an npm-shrinkwrap.json. Please use only one of the two.')
}
+ let parsed = null
if (shrinkwrap || lockfile) {
try {
- child.package._shrinkwrap = parseJSON(shrinkwrap || lockfile)
+ parsed = parseJSON(shrinkwrap || lockfile)
} catch (ex) {
- child.package._shrinkwrap = null
throw ex
}
- } else {
- child.package._shrinkwrap = null
}
+ if (
+ pkgJson &&
+ parsed &&
+ parsed.packageIntegrity &&
+ !ssri.checkData(pkgJson, parsed.packageIntegrity)
+ ) {
+ let name = shrinkwrap ? 'npm-shrinkwrap.json' : 'package-lock.json'
+ log.info('read-shrinkwrap', `${name} will be updated because package.json does not match what it was generated against.`)
+ }
+ child.package._shrinkwrap = parsed
}
).then(() => next(), next)
}
-function readLockfile (name, child) {
+function maybeReadFile (name, child) {
return readFileAsync(
path.join(child.path, name)
).catch({code: 'ENOENT'}, () => null)
diff --git a/lib/shrinkwrap.js b/lib/shrinkwrap.js
index 832479e73..c764d3837 100644
--- a/lib/shrinkwrap.js
+++ b/lib/shrinkwrap.js
@@ -26,12 +26,14 @@ const writeFileAtomic = require('write-file-atomic')
const PKGLOCK = 'package-lock.json'
const SHRINKWRAP = 'npm-shrinkwrap.json'
+const PKGLOCK_VERSION = 1
// emit JSON describing versions of all packages currently installed (for later
// use with shrinkwrap install)
shrinkwrap.usage = 'npm shrinkwrap'
module.exports = exports = shrinkwrap
+module.exports.PKGLOCK_VERSION = PKGLOCK_VERSION
function shrinkwrap (args, silent, cb) {
if (typeof cb !== 'function') {
cb = silent
@@ -74,8 +76,7 @@ module.exports.createShrinkwrap = createShrinkwrap
function createShrinkwrap (tree, opts, cb) {
opts = opts || {}
lifecycle(tree.package, 'preshrinkwrap', tree.path, function () {
- var pkginfo = treeToShrinkwrap(tree)
-
+ const pkginfo = treeToShrinkwrap(tree)
chain([
[lifecycle, tree.package, 'shrinkwrap', tree.path],
[shrinkwrap_, tree.path, pkginfo, opts],
@@ -182,14 +183,19 @@ function save (dir, pkginfo, opts, cb) {
const info = (
shrinkwrap ||
lockfile ||
- [path.resolve(dir, opts.defaultFile || PKGLOCK), (pkg && pkg[1]) || 2]
+ {
+ path: path.resolve(dir, opts.defaultFile || PKGLOCK),
+ data: '{}',
+ indent: (pkg && pkg.indent) || 2
+ }
)
- const swdata = JSON.stringify(pkginfo, null, info[1]) + '\n'
- writeFileAtomic(info[0], swdata, (err) => {
+ const updated = updateLockfileMetadata(pkginfo, pkg && pkg.data)
+ const swdata = JSON.stringify(updated, null, info.indent) + '\n'
+ writeFileAtomic(info.path, swdata, (err) => {
if (err) return cb(err)
if (opts.silent) return cb(null, pkginfo)
if (!shrinkwrap && !lockfile) {
- log.notice('', `created a lockfile as ${path.basename(info[0])}. You should commit this file.`)
+ log.notice('', `created a lockfile as ${path.basename(info.path)}. You should commit this file.`)
}
cb(null, pkginfo)
})
@@ -198,12 +204,51 @@ function save (dir, pkginfo, opts, cb) {
}, cb)
}
+function updateLockfileMetadata (pkginfo, pkgJson) {
+ // This is a lot of work just to make sure the extra metadata fields are
+ // between version and dependencies fields, without affecting any other stuff
+ const newPkg = {}
+ let metainfoWritten = false
+ const metainfo = new Set([
+ 'createdWith',
+ 'lockfileVersion',
+ 'packageIntegrity'
+ ])
+ Object.keys(pkginfo).forEach((k) => {
+ if (k === 'dependencies') {
+ writeMetainfo(newPkg)
+ }
+ if (!metainfo.has(k)) {
+ newPkg[k] = pkginfo[k]
+ }
+ if (k === 'version') {
+ writeMetainfo(newPkg)
+ }
+ })
+ if (!metainfoWritten) {
+ writeMetainfo(newPkg)
+ }
+ function writeMetainfo (pkginfo) {
+ pkginfo.createdWith = `npm@${npm.version}`
+ pkginfo.lockfileVersion = PKGLOCK_VERSION
+ pkginfo.packageIntegrity = pkgJson && ssri.fromData(pkgJson, {
+ algorithms: ['sha512']
+ }).toString()
+ metainfoWritten = true
+ }
+ return newPkg
+}
+
function checkPackageFile (dir, name) {
const file = path.resolve(dir, name)
return fs.readFileAsync(
file, 'utf8'
).then((data) => {
- return [file, detectIndent(data).indent || ' ']
+ return {
+ path: file,
+ data,
+ indent: detectIndent(data).indent || 2
+ }
}).catch({code: 'ENOENT'}, () => {})
}