Skip to content

Commit 2fb0509

Browse files
jfirebaughisaacs
authored andcommitted
Fix npm ci with file: dependencies
Partially reverts #40/#86, keeping the "Don't record linked deps as bundled" part but reverting the "Don't iterate into linked deps" part. It seems that we need to record dependencies of linked deps in order for `npm ci` to work. Fix: https://npm.community/t/6-8-0-npm-ci-fails-with-local-dependency/5385 Fix: https://npm.community/t/npm-ci-fail-to-local-packages/6076 PR-URL: #216 Credit: @jfirebaugh Close: #216 Reviewed-by: @isaacs EDIT: Updated test to not rely on network and follow latest and greatest test patterns.
1 parent 3dcf86f commit 2fb0509

File tree

3 files changed

+86
-3
lines changed

3 files changed

+86
-3
lines changed

lib/shrinkwrap.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ function shrinkwrapDeps (deps, top, tree, seen) {
111111
var pkginfo = deps[moduleName(child)] = {}
112112
var requested = getRequested(child) || child.package._requested || {}
113113
var linked = child.isLink || child.isInLink
114-
var linkedFromHere = linked && path.relative(top.realpath, child.realpath)[0] !== '.'
115114
pkginfo.version = childVersion(top, child, requested)
116115
if (requested.type === 'git' && child.package._from) {
117116
pkginfo.from = child.package._from
@@ -142,7 +141,7 @@ function shrinkwrapDeps (deps, top, tree, seen) {
142141
})
143142
}
144143
// iterate into children on non-links and links contained within the top level package
145-
if (child.children.length && (!child.isLink || linkedFromHere)) {
144+
if (child.children.length) {
146145
pkginfo.dependencies = {}
147146
shrinkwrapDeps(pkginfo.dependencies, top, child, seen)
148147
}

test/tap/ci-with-local-dependency.js

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
const fs = require('graceful-fs')
2+
const path = require('path')
3+
4+
const mkdirp = require('mkdirp')
5+
const t = require('tap')
6+
7+
const common = require('../common-tap.js')
8+
9+
const pkg = common.pkg + '/package'
10+
11+
const EXEC_OPTS = {
12+
cwd: pkg,
13+
stdio: [0, 1, 2],
14+
env: common.newEnv().extend({
15+
npm_config_registry: common.registry
16+
})
17+
}
18+
19+
const localDependencyJson = {
20+
name: 'local-dependency',
21+
version: '0.0.0',
22+
dependencies: {
23+
'test-package': '0.0.0'
24+
}
25+
}
26+
27+
const dependentJson = {
28+
name: 'dependent',
29+
version: '0.0.0',
30+
dependencies: {
31+
'local-dependency': '../local-dependency'
32+
}
33+
}
34+
35+
const target = path.resolve(pkg, '../local-dependency')
36+
const mr = require('npm-registry-mock')
37+
let server
38+
t.teardown(() => {
39+
if (server) {
40+
server.close()
41+
}
42+
})
43+
44+
t.test('setup', function (t) {
45+
mkdirp.sync(target)
46+
fs.writeFileSync(
47+
path.join(target, 'package.json'),
48+
JSON.stringify(localDependencyJson, null, 2)
49+
)
50+
mkdirp.sync(pkg)
51+
fs.writeFileSync(
52+
path.join(pkg, 'package.json'),
53+
JSON.stringify(dependentJson, null, 2)
54+
)
55+
mr({ port: common.port }, (er, s) => {
56+
if (er) {
57+
throw er
58+
}
59+
server = s
60+
t.end()
61+
})
62+
})
63+
64+
t.test('\'npm install\' should install local pkg from sub path', function (t) {
65+
common.npm(['install', '--loglevel=silent'], EXEC_OPTS, function (err, code) {
66+
if (err) throw err
67+
t.equal(code, 0, 'npm install exited with code')
68+
t.ok(fs.statSync(path.resolve(pkg, 'node_modules/local-dependency/package.json')).isFile(), 'local dependency package.json exists')
69+
t.ok(fs.statSync(path.resolve(pkg, 'node_modules/local-dependency/node_modules/test-package')).isDirectory(), 'transitive dependency installed')
70+
t.end()
71+
})
72+
})
73+
74+
t.test('\'npm ci\' should work', function (t) {
75+
common.npm(['ci', '--loglevel=silent'], EXEC_OPTS, function (err, code) {
76+
if (err) throw err
77+
t.equal(code, 0, 'npm install exited with code')
78+
t.ok(fs.statSync(path.resolve(pkg, 'node_modules/local-dependency/package.json')).isFile(), 'local dependency package.json exists')
79+
t.ok(fs.statSync(path.resolve(pkg, 'node_modules/local-dependency/node_modules/test-package')).isDirectory(), 'transitive dependency installed')
80+
t.end()
81+
})
82+
})

test/tap/spec-local-specifiers.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,9 @@ test('save behavior', function (t) {
585585
var deps = pjson.dependencies || {}
586586
t.is(deps['sb-transitive'], 'file:../sb-transitive', 'package.json')
587587
var sdep = shrinkwrap.dependencies['sb-transitive'] || {}
588-
t.like(sdep, {bundled: null, dependencies: null, version: 'file:../sb-transitive'}, 'npm-shrinkwrap.json direct dep')
588+
var tdep = sdep.dependencies.sbta
589+
t.like(tdep, {bundled: null, version: 'file:../sb-transitive/sbta'}, 'npm-shrinkwrap.json transitive dep')
590+
t.like(sdep, {bundled: null, version: 'file:../sb-transitive'}, 'npm-shrinkwrap.json direct dep')
589591
t.done()
590592
})
591593
})

0 commit comments

Comments
 (0)