Skip to content
This repository was archived by the owner on Aug 11, 2022. It is now read-only.

Commit d8471a2

Browse files
Andrew Schmadelzkat
authored andcommitted
deps: Consider devDependencies when deciding whether to hoist a package
Fixes: #10727 Fixes: #11062 Fixes: #12654 Fixes: #10277 Fixes: #11766 Fixes: #11043 PR-URL: #12811 Credit: @schmod Reviewed-By: @iarna
1 parent fc61c08 commit d8471a2

3 files changed

Lines changed: 121 additions & 0 deletions

File tree

lib/install/deps.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,14 @@ var earliestInstallable = exports.earliestInstallable = function (requiredBy, tr
639639
return null
640640
}
641641

642+
var devDeps = tree.package.devDependencies || {}
643+
if (tree.isTop && devDeps[pkg.name]) {
644+
var requested = npa(pkg.name + '@' + devDeps[pkg.name])
645+
if (!doesChildVersionMatch({package: pkg}, requested, tree)) {
646+
return null
647+
}
648+
}
649+
642650
if (tree.phantomChildren && tree.phantomChildren[pkg.name]) return null
643651

644652
if (tree.isTop) return tree

test/tap/shrinkwrap-shared-dev-dependency.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ test("shrinkwrap doesn't strip out the shared dependency", function (t) {
2121

2222
npm.install('.', function (err) {
2323
if (err) return t.fail(err)
24+
npm.config.set('dev', true) // npm install unsets this
2425

2526
npm.commands.shrinkwrap([], true, function (err, results) {
2627
if (err) return t.fail(err)
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
'use strict'
2+
var test = require('tap').test
3+
var requireInject = require('require-inject')
4+
5+
// we're just mocking to avoid having to call `npm.load`
6+
var deps = requireInject('../../lib/install/deps.js', {
7+
'../../lib/npm.js': {
8+
config: {
9+
get: function (val) { return (val === 'global-style' || val === 'legacy-bundling') ? false : 'mock' }
10+
}
11+
}
12+
})
13+
14+
var earliestInstallable = deps.earliestInstallable
15+
16+
test('earliestInstallable should consider devDependencies', function (t) {
17+
var dep1 = {
18+
children: [],
19+
package: {
20+
name: 'dep1',
21+
dependencies: { dep2: '2.0.0' }
22+
}
23+
}
24+
25+
// a library required by the base package
26+
var dep2 = {
27+
package: {
28+
name: 'dep2',
29+
version: '1.0.0'
30+
}
31+
}
32+
33+
// an incompatible verson of dep2. required by dep1
34+
var dep2a = {
35+
package: {
36+
name: 'dep2',
37+
version: '2.0.0',
38+
_from: {
39+
40+
scope: null,
41+
escapedName: 'dep2',
42+
name: 'dep2',
43+
rawSpec: '1.0.0',
44+
spec: '1.0.0',
45+
type: 'version'
46+
}
47+
},
48+
parent: dep1
49+
}
50+
51+
var pkg = {
52+
isTop: true,
53+
children: [dep1],
54+
package: {
55+
name: 'pkg',
56+
dependencies: { dep1: '1.0.0' },
57+
devDependencies: { dep2: '1.0.0' }
58+
}
59+
}
60+
61+
dep1.parent = pkg
62+
dep2a.parent = dep1
63+
dep2.parent = pkg
64+
65+
var earliest = earliestInstallable(dep1, dep1, dep2a.package)
66+
t.isDeeply(earliest, dep1, 'should hoist package when an incompatible devDependency is present')
67+
t.end()
68+
})
69+
70+
test('earliestInstallable should reuse shared prod/dev deps when they are identical', function (t) {
71+
var dep1 = {
72+
children: [],
73+
package: {
74+
name: 'dep1',
75+
dependencies: { dep2: '1.0.0' }
76+
}
77+
}
78+
79+
var dep2 = {
80+
package: {
81+
name: 'dep2',
82+
version: '1.0.0',
83+
_from: {
84+
raw: 'dep2@^1.0.0',
85+
scope: null,
86+
escapedName: 'dep2',
87+
name: 'dep2',
88+
rawSpec: '^1.0.0',
89+
spec: '>=1.0.0 <2.0.0',
90+
type: 'range'
91+
}
92+
}
93+
}
94+
95+
var pkg = {
96+
isTop: true,
97+
children: [dep1],
98+
package: {
99+
name: 'pkg',
100+
dependencies: { dep1: '1.0.0' },
101+
devDependencies: { dep2: '^1.0.0' }
102+
}
103+
}
104+
105+
dep1.parent = pkg
106+
dep2.parent = pkg
107+
108+
var earliest = earliestInstallable(dep1, dep1, dep2.package)
109+
t.isDeeply(earliest, pkg, 'should reuse identical shared dev/prod deps when installing both')
110+
t.end()
111+
})
112+

0 commit comments

Comments
 (0)