Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some comments. Nothing really bad jumps out at me. I'll take a closer look once I've gotten some sleep and/or can actually talk through this and test it out.
lib/install/inflate-shrinkwrap.js
Outdated
@@ -26,7 +26,8 @@ module.exports = function (tree, swdeps, opts, finishInflating) { | |||
if (!npm.config.get('shrinkwrap') || !npm.config.get('package-lock')) { | |||
return finishInflating() | |||
} | |||
tree.loaded = true | |||
tree.loaded = false | |||
tree.hasRequiresFromLock = Object.keys(swdeps).every((d) => swdeps[d].requires) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this be .some()
? You only need to know if there was one, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well... no, if any of them are missing then we can't assume we know anything about the relationships between the modules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At one point during the process of writing this it was possible to produce an install that only had partial resolved information. Buuut…
That doesn't seem to be the case any more. So this can become some
and we can stop including requires
on every node.
Relatedly, I'm finding that npm install xyz
or npm rm xyz
when you have a legacy package-lock but nothing installed fails to properly upgrade the package-lock, eg:
$ node ~/code/npm rm null
added 190 packages and removed 1 package in 6.671s
package-lock.json
Outdated
@@ -6,113 +6,163 @@ | |||
"abbrev": { | |||
"version": "1.1.0", | |||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", | |||
"integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=" | |||
"integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=", | |||
"requires": {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wait, was your solution to unconditionally add a requires:{}
? Mehhhh. I don't like this kinda noop crud :\
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I'm open to alternatives.
lib/shrinkwrap.js
Outdated
@@ -133,13 +127,28 @@ function shrinkwrapDeps (deps, top, tree, seen) { | |||
} | |||
if (childIsOnlyDev) pkginfo.dev = true | |||
if (isOptional(child)) pkginfo.optional = true | |||
pkginfo.requires = {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
meh @ always having requires
if (child.fakeChild) { | ||
dep.missing = true | ||
dep.optional = child.package._optional | ||
dep.requiredBy = child.package._spec |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get this line...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where we're producing read-installed
's output for ls
to consume. In it's format requiredBy
is the spec that required the missing dep.
_resolved: adaptResolved(requested, sw.resolved), | ||
_requested: requested, | ||
_optional: sw.optional, | ||
_integrity: sw.integrity, | ||
_from: from, | ||
_spec: requested.rawSpec, | ||
_where: topPath, | ||
_args: [[requested.toString(), topPath]] | ||
_args: [[requested.toString(), topPath]], | ||
dependencies: sw.requires |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this feels so mischievous 😈
508cc07
to
a4091fb
Compare
@iarna when I use
|
f7534bc
to
e511aa8
Compare
@zkat If it's showing you anything beyond the first level that's a bug. (It doesn't do that for me in my examples…) We can bikeshed the details of how this looks different showing the full tree later, imo. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📦
#### dependencies | ||
|
||
The dependencies of this dependency, exactly as at the top level. | ||
Exactly like `dependencies` at the top level, this is a list of modules to | ||
isntall in the `node_modules` of this module. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that supposed to say isntall
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope, ty
@@ -28,15 +28,6 @@ The version of the package this is a package-lock for. This must match what's in | |||
An integer version, starting at `1` with the version number of this document | |||
whose semantics were used when generating this `package-lock.json`. | |||
|
|||
### packageIntegrity *(new)* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this removed? I am confused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a hash of the package.json
which would result in churn and merge conflicts on the package-lock.json
. It was never implemented and the consensus of the discussion is that it was a bad idea.
@@ -85,7 +85,7 @@ 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( | |||
t.like( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this an update to tap
or a design choice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deepEqual
requires exact matching of the datastructures. like
let's you compare an incomplete datastructure against a complete one. Where they share keys they have to match.
So this change was made to allow changes to the package-lock
format that aren't related to this test to happen w/o breaking the test.
79c4628
to
85b6908
Compare
85b6908
to
fc2ce64
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 💯 🐑 🚀 💥 🔥 😱
Also prune before we save, as we skipped the earlier pruning and we don't want to save a bogus `package-lock`. Fixes: #16839
This removes a no longer appropriate check of `fromShrinkwrap` and a duplicated code path when using `_from`.
That is, if you have a package-lock but haven't installed anything yet then we're going to insist that all of the bits be there. This is necessary in order to be able to cleanly upgrade old package-lock files. This means if you type `npm install foo` or `npm rm foo` and don't have a `node_modules` but do have a `package-lock.json` it's gonna install everything from the `package-lock.json` in addition to making your change. The one thing we won't do is update your package-lock from your package.json. We only do that when you request a full install. This does not change the behavior if you don't have a lock file.
That is, if you have a package-lock but haven't installed anything yet then we're going to insist that all of the bits be there. This is necessary in order to be able to cleanly upgrade old package-lock files. This means if you type `npm install foo` or `npm rm foo` and don't have a `node_modules` but do have a `package-lock.json` it's gonna install everything from the `package-lock.json` in addition to making your change. The one thing we won't do is update your package-lock from your package.json. We only do that when you request a full install. This does not change the behavior if you don't have a lock file. PR-URL: #17508 Credit: @iarna Reviewed-By: @zkat
See npm/npm#17508 for details
This has a handful of fixes:
package-lock.json
field, calledrequires
, which tracks which modules a given module requires.npm install
a second time #16839 which was caused by not having this information available, particularly when git dependencies were involved.package.json
to trump thepackage-lock.json
.fetch-package-metadata.addBundled
on fake children (this was harmless, because bundleDependencies would never be set, but also pointless.)npm ls
now loads the shrinkwrap, which opens the door to showing a full tree of dependencies even when nothing is yet installed. (It doesn't do that yet though.)