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
diff options
context:
space:
mode:
-rw-r--r--lib/install/read-shrinkwrap.js26
-rw-r--r--lib/shrinkwrap.js59
-rw-r--r--package-lock.json3
-rw-r--r--test/tap/dedupe.js1
-rw-r--r--test/tap/shrinkwrap-default-dev.js2
-rw-r--r--test/tap/shrinkwrap-dev-dependency.js2
-rw-r--r--test/tap/shrinkwrap-empty-deps.js34
-rw-r--r--test/tap/shrinkwrap-extra-metadata.js83
-rw-r--r--test/tap/shrinkwrap-local-dependency.js6
-rw-r--r--test/tap/shrinkwrap-optional-dependency.js2
-rw-r--r--test/tap/shrinkwrap-optional-property.js2
-rw-r--r--test/tap/shrinkwrap-prod-dependency-also.js6
-rw-r--r--test/tap/shrinkwrap-prod-dependency.js2
-rw-r--r--test/tap/shrinkwrap-shared-dev-dependency.js2
14 files changed, 194 insertions, 36 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'}, () => {})
}
diff --git a/package-lock.json b/package-lock.json
index b4365b614..f6764e305 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,9 @@
{
"name": "npm",
"version": "4.6.1",
+ "createdWith": "npm@4.6.1",
+ "lockfileVersion": 1,
+ "packageIntegrity": "sha512-DS0oU+EJLlcc0fmN5pb8OwuG8h/JYKIEIoJBIWdykZk/i0HjXW1dChjcMwUUEFAAIIWH5Ru27RDPnVqWTvApCQ==",
"dependencies": {
"abbrev": {
"version": "1.1.0",
diff --git a/test/tap/dedupe.js b/test/tap/dedupe.js
index bdda3474a..b6c601cba 100644
--- a/test/tap/dedupe.js
+++ b/test/tap/dedupe.js
@@ -60,6 +60,7 @@ test('setup', function (t) {
test('dedupe finds the common module and moves it up one level', function (t) {
common.npm([
'--registry', common.registry,
+ '--no-save',
'install', '.'
],
EXEC_OPTS,
diff --git a/test/tap/shrinkwrap-default-dev.js b/test/tap/shrinkwrap-default-dev.js
index 67266644c..5c8929a43 100644
--- a/test/tap/shrinkwrap-default-dev.js
+++ b/test/tap/shrinkwrap-default-dev.js
@@ -83,7 +83,7 @@ test('shrinkwrap-default-dev', function (t) {
t.comment(stdout.trim())
t.comment(stderr.trim())
var swrap = JSON.parse(fs.readFileSync(shrinkwrapPath))
- t.isDeeply(swrap, shrinkwrapWithDev, 'Shrinkwrap included dev deps by default')
+ t.isDeeply(swrap.dependencies, shrinkwrapWithDev.dependencies, 'Shrinkwrap included dev deps by default')
t.done()
})
})
diff --git a/test/tap/shrinkwrap-dev-dependency.js b/test/tap/shrinkwrap-dev-dependency.js
index 20e2de1d2..79d3b7cd0 100644
--- a/test/tap/shrinkwrap-dev-dependency.js
+++ b/test/tap/shrinkwrap-dev-dependency.js
@@ -79,7 +79,7 @@ test("shrinkwrap doesn't strip out the dependency", function (t) {
} catch (ex) {
t.comment(ex)
}
- t.deepEqual(results, desired)
+ t.deepEqual(results.dependencies, desired.dependencies)
s.close()
t.end()
})
diff --git a/test/tap/shrinkwrap-empty-deps.js b/test/tap/shrinkwrap-empty-deps.js
index cf7e9a6e8..37ce4d4f1 100644
--- a/test/tap/shrinkwrap-empty-deps.js
+++ b/test/tap/shrinkwrap-empty-deps.js
@@ -1,19 +1,22 @@
-var fs = require('fs')
-var path = require('path')
+'use strict'
-var mkdirp = require('mkdirp')
-var mr = require('npm-registry-mock')
-var osenv = require('osenv')
-var rimraf = require('rimraf')
-var test = require('tap').test
+const common = require('../common-tap.js')
+const fs = require('fs')
+const mkdirp = require('mkdirp')
+const mr = require('npm-registry-mock')
+const npm = require('../../lib/npm.js')
+const osenv = require('osenv')
+const path = require('path')
+const rimraf = require('rimraf')
+const shrinkwrap = require('../../lib/shrinkwrap.js')
+const ssri = require('ssri')
+const test = require('tap').test
-var common = require('../common-tap.js')
+const pkg = path.resolve(__dirname, 'shrinkwrap-empty-deps')
-var pkg = path.resolve(__dirname, 'shrinkwrap-empty-deps')
+const EXEC_OPTS = { cwd: pkg }
-var EXEC_OPTS = { cwd: pkg }
-
-var json = {
+const json = {
author: 'Rockbert',
name: 'shrinkwrap-empty-deps',
version: '0.0.0',
@@ -51,7 +54,12 @@ test('returns a list of removed items', function (t) {
t.same(
{
'name': 'shrinkwrap-empty-deps',
- 'version': '0.0.0'
+ 'version': '0.0.0',
+ 'createdWith': `npm@${npm.version}`,
+ 'lockfileVersion': shrinkwrap.PKGLOCK_VERSION,
+ 'packageIntegrity': ssri.fromData(JSON.stringify(json, null, 2), {
+ algorithms: ['sha512']
+ }).toString()
},
JSON.parse(desired),
'shrinkwrap handled empty deps without exploding'
diff --git a/test/tap/shrinkwrap-extra-metadata.js b/test/tap/shrinkwrap-extra-metadata.js
new file mode 100644
index 000000000..1947ee575
--- /dev/null
+++ b/test/tap/shrinkwrap-extra-metadata.js
@@ -0,0 +1,83 @@
+'use strict'
+
+const common = require('../common-tap.js')
+const fs = require('fs')
+const mkdirp = require('mkdirp')
+const mr = require('npm-registry-mock')
+const npm = require('../../lib/npm.js')
+const osenv = require('osenv')
+const path = require('path')
+const rimraf = require('rimraf')
+const shrinkwrap = require('../../lib/shrinkwrap.js')
+const ssri = require('ssri')
+const test = require('tap').test
+
+const pkg = path.join(__dirname, path.basename(__filename, '.js'))
+
+const EXEC_OPTS = { cwd: pkg }
+
+const json = {
+ author: 'Rockbert',
+ name: 'shrinkwrap-extra-metadata',
+ version: '0.0.0'
+}
+
+test('setup', function (t) {
+ cleanup()
+ mkdirp.sync(pkg)
+ fs.writeFileSync(
+ path.join(pkg, 'package.json'),
+ JSON.stringify(json, null, 2)
+ )
+
+ process.chdir(pkg)
+ t.end()
+})
+
+test('adds additional metadata fields from the pkglock spec', function (t) {
+ mr({ port: common.port }, function (er, s) {
+ common.npm(
+ [
+ '--registry', common.registry,
+ '--loglevel', 'silent',
+ 'shrinkwrap'
+ ],
+ EXEC_OPTS,
+ function (err, code, stdout, stderr) {
+ t.ifError(err, 'shrinkwrap ran without issue')
+ t.notOk(code, 'shrinkwrap ran without raising error code')
+
+ fs.readFile(path.resolve(pkg, 'npm-shrinkwrap.json'), function (err, desired) {
+ t.ifError(err, 'read npm-shrinkwrap.json without issue')
+ t.same(
+ {
+ 'name': 'shrinkwrap-extra-metadata',
+ 'version': '0.0.0',
+ 'createdWith': `npm@${npm.version}`,
+ 'lockfileVersion': shrinkwrap.PKGLOCK_VERSION,
+ 'packageIntegrity': ssri.fromData(JSON.stringify(json, null, 2), {
+ algorithms: ['sha512']
+ }).toString()
+ },
+ JSON.parse(desired),
+ 'shrinkwrap wrote the expected metadata fields'
+ )
+
+ s.close()
+ t.end()
+ })
+ }
+ )
+ })
+})
+
+test('cleanup', function (t) {
+ cleanup()
+
+ t.end()
+})
+
+function cleanup () {
+ process.chdir(osenv.tmpdir())
+ rimraf.sync(pkg)
+}
diff --git a/test/tap/shrinkwrap-local-dependency.js b/test/tap/shrinkwrap-local-dependency.js
index 56e044de0..992343ccf 100644
--- a/test/tap/shrinkwrap-local-dependency.js
+++ b/test/tap/shrinkwrap-local-dependency.js
@@ -85,7 +85,11 @@ test('shrinkwrap uses resolved with file: on local deps', function (t) {
t.comment(stderr.trim())
t.equal(code, 0, 'npm exited normally')
var data = fs.readFileSync(path.join(testdir, 'npm-shrinkwrap.json'), { encoding: 'utf8' })
- t.deepEqual(JSON.parse(data), shrinkwrap, 'shrinkwrap looks correct')
+ t.deepEqual(
+ JSON.parse(data).dependencies,
+ shrinkwrap.dependencies,
+ 'shrinkwrap looks correct'
+ )
t.end()
})
})
diff --git a/test/tap/shrinkwrap-optional-dependency.js b/test/tap/shrinkwrap-optional-dependency.js
index 0e9b3b202..0373e89e6 100644
--- a/test/tap/shrinkwrap-optional-dependency.js
+++ b/test/tap/shrinkwrap-optional-dependency.js
@@ -43,7 +43,7 @@ test('shrinkwrap does not fail on missing optional dependency', function (t) {
npm.commands.shrinkwrap([], true, function (err, results) {
if (err) return fail(err)
- t.deepEqual(results, desired)
+ t.deepEqual(results.dependencies, desired.dependencies)
s.close()
t.end()
})
diff --git a/test/tap/shrinkwrap-optional-property.js b/test/tap/shrinkwrap-optional-property.js
index 52deba863..19e55a45f 100644
--- a/test/tap/shrinkwrap-optional-property.js
+++ b/test/tap/shrinkwrap-optional-property.js
@@ -33,7 +33,7 @@ test('shrinkwrap adds optional property when optional dependency', function (t)
npm.commands.shrinkwrap([], true, function (err, results) {
if (err) return fail(err)
- t.deepEqual(results, desired)
+ t.deepEqual(results.dependencies, desired.dependencies)
s.close()
t.end()
})
diff --git a/test/tap/shrinkwrap-prod-dependency-also.js b/test/tap/shrinkwrap-prod-dependency-also.js
index 4d18aedca..6cc388946 100644
--- a/test/tap/shrinkwrap-prod-dependency-also.js
+++ b/test/tap/shrinkwrap-prod-dependency-also.js
@@ -46,7 +46,11 @@ test("shrinkwrap --also=development doesn't strip out prod dependencies", functi
t.ifError(ex, 'read shrinkwrap')
}
}
- t.deepEqual(results, desired, 'results have dev dep')
+ t.deepEqual(
+ results.dependencies,
+ desired.dependencies,
+ 'results have dev dep'
+ )
s.done()
t.end()
})
diff --git a/test/tap/shrinkwrap-prod-dependency.js b/test/tap/shrinkwrap-prod-dependency.js
index cdb6416cc..023a3bf0b 100644
--- a/test/tap/shrinkwrap-prod-dependency.js
+++ b/test/tap/shrinkwrap-prod-dependency.js
@@ -26,7 +26,7 @@ test("shrinkwrap --dev doesn't strip out prod dependencies", function (t) {
npm.commands.shrinkwrap([], true, function (err, results) {
if (err) return t.fail(err)
- t.deepEqual(results, desired)
+ t.deepEqual(results.dependencies, desired.dependencies)
s.close()
t.end()
})
diff --git a/test/tap/shrinkwrap-shared-dev-dependency.js b/test/tap/shrinkwrap-shared-dev-dependency.js
index 0414ac8c2..71e6371bc 100644
--- a/test/tap/shrinkwrap-shared-dev-dependency.js
+++ b/test/tap/shrinkwrap-shared-dev-dependency.js
@@ -67,7 +67,7 @@ test("shrinkwrap doesn't strip out the shared dependency", function (t) {
}).spread((code) => {
t.is(code, 0, 'shrinkwrap')
var results = JSON.parse(fs.readFileSync(`${pkg}/npm-shrinkwrap.json`))
- t.deepEqual(results, desired)
+ t.deepEqual(results.dependencies, desired.dependencies)
t.end()
})
})