Skip to content

Commit a8e77f2

Browse files
committed
wrap a timer around the rimraf call in npm-ci
Fix: npm/arborist#207 PR-URL: #2573 Credit: @isaacs Close: #2573 Reviewed-by: @nlf
1 parent 0ea134e commit a8e77f2

File tree

2 files changed

+58
-8
lines changed

2 files changed

+58
-8
lines changed

lib/ci.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ const Arborist = require('@npmcli/arborist')
33
const rimraf = util.promisify(require('rimraf'))
44
const reifyFinish = require('./utils/reify-finish.js')
55
const runScript = require('@npmcli/run-script')
6+
const fs = require('fs')
7+
const readdir = util.promisify(fs.readdir)
68

79
const log = require('npmlog')
810
const npm = require('./npm.js')
@@ -13,6 +15,16 @@ const completion = require('./utils/completion/none.js')
1315

1416
const cmd = (args, cb) => ci().then(() => cb()).catch(cb)
1517

18+
const removeNodeModules = async where => {
19+
const rimrafOpts = { glob: false }
20+
process.emit('time', 'npm-ci:rm')
21+
const path = `${where}/node_modules`
22+
// get the list of entries so we can skip the glob for performance
23+
const entries = await readdir(path, null).catch(er => [])
24+
await Promise.all(entries.map(f => rimraf(`${path}/${f}`, rimrafOpts)))
25+
process.emit('timeEnd', 'npm-ci:rm')
26+
}
27+
1628
const ci = async () => {
1729
if (npm.flatOptions.global) {
1830
const err = new Error('`npm ci` does not work for global packages')
@@ -33,7 +45,7 @@ const ci = async () => {
3345
'later to generate a package-lock.json file, then try again.'
3446
throw new Error(msg)
3547
}),
36-
rimraf(`${where}/node_modules/*`, { glob: { dot: true, nosort: true, silent: true } }),
48+
removeNodeModules(where),
3749
])
3850
// npm ci should never modify the lockfile or package.json
3951
await arb.reify({ ...npm.flatOptions, save: false })

test/lib/ci.js

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,45 @@ test('should use Arborist and run-script', (t) => {
5151
'prepare',
5252
'postprepare',
5353
]
54+
55+
// set to true when timer starts, false when it ends
56+
// when the test is done, we assert that all timers ended
57+
const timers = {}
58+
const onTime = msg => {
59+
if (timers[msg])
60+
throw new Error(`saw duplicate timer: ${msg}`)
61+
timers[msg] = true
62+
}
63+
const onTimeEnd = msg => {
64+
if (!timers[msg])
65+
throw new Error(`ended timer that was not started: ${msg}`)
66+
timers[msg] = false
67+
}
68+
process.on('time', onTime)
69+
process.on('timeEnd', onTimeEnd)
70+
t.teardown(() => {
71+
process.removeListener('time', onTime)
72+
process.removeListener('timeEnd', onTimeEnd)
73+
})
74+
75+
const path = t.testdir({
76+
node_modules: {
77+
foo: {
78+
'package.json': JSON.stringify({
79+
name: 'foo',
80+
version: '1.2.3',
81+
}),
82+
},
83+
'.dotdir': {},
84+
'.dotfile': 'a file with a dot',
85+
},
86+
})
87+
const expectRimrafs = 3
88+
let actualRimrafs = 0
89+
5490
const ci = requireInject('../../lib/ci.js', {
5591
'../../lib/npm.js': {
56-
prefix: 'foo',
92+
prefix: path,
5793
flatOptions: {
5894
global: false,
5995
},
@@ -72,13 +108,11 @@ test('should use Arborist and run-script', (t) => {
72108
t.ok(true, 'reify is called')
73109
}
74110
},
75-
util: {
76-
inherits: () => {},
77-
promisify: (fn) => fn,
78-
},
79-
rimraf: (path) => {
111+
rimraf: (path, ...args) => {
112+
actualRimrafs++
80113
t.ok(path, 'rimraf called with path')
81-
return Promise.resolve(true)
114+
// callback is always last arg
115+
args.pop()()
82116
},
83117
'../../lib/utils/reify-output.js': function (arb) {
84118
t.ok(arb, 'gets arborist tree')
@@ -87,6 +121,10 @@ test('should use Arborist and run-script', (t) => {
87121
ci(null, er => {
88122
if (er)
89123
throw er
124+
for (const [msg, result] of Object.entries(timers))
125+
t.notOk(result, `properly resolved ${msg} timer`)
126+
t.match(timers, { 'npm-ci:rm': false }, 'saw the rimraf timer')
127+
t.equal(actualRimrafs, expectRimrafs, 'removed the right number of things')
90128
t.strictSame(scripts, [], 'called all scripts')
91129
t.end()
92130
})

0 commit comments

Comments
 (0)