Skip to content

Commit d9dade2

Browse files
devoto13Jonathan Ginsburg
authored and
Jonathan Ginsburg
committedFeb 5, 2022
fix(helper): make mkdirIfNotExists helper resilient to concurrent calls
The main motivation for this change is karma-runner/karma-coverage#434 (comment) where concurrent calls to the helper fail because of the race between the check and directory creation. This is a temporary solution and should be replaced with the native [`mkdir`](https://nodejs.org/api/fs.html#fsmkdirpath-options-callback) with the `recursive` option once minimum supported Node is bumped to 12.
1 parent 653c762 commit d9dade2

File tree

4 files changed

+15
-41
lines changed

4 files changed

+15
-41
lines changed
 

‎lib/helper.js

+2-14
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
'use strict'
22

3-
const fs = require('graceful-fs')
4-
const path = require('path')
53
const _ = require('lodash')
4+
const mkdirp = require('mkdirp')
65
const useragent = require('ua-parser-js')
76
const mm = require('minimatch')
87

@@ -141,18 +140,7 @@ const replaceWinPath = (path) => {
141140
exports.normalizeWinPath = process.platform === 'win32' ? replaceWinPath : _.identity
142141

143142
exports.mkdirIfNotExists = (directory, done) => {
144-
// TODO(vojta): handle if it's a file
145-
/* eslint-disable handle-callback-err */
146-
fs.stat(directory, (err, stat) => {
147-
if (stat && stat.isDirectory()) {
148-
done()
149-
} else {
150-
exports.mkdirIfNotExists(path.dirname(directory), () => {
151-
fs.mkdir(directory, done)
152-
})
153-
}
154-
})
155-
/* eslint-enable handle-callback-err */
143+
mkdirp(directory, done)
156144
}
157145

158146
exports.defer = () => {

‎package-lock.json

+2-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@
441441
"log4js": "^6.4.1",
442442
"mime": "^2.5.2",
443443
"minimatch": "^3.0.4",
444+
"mkdirp": "^0.5.5",
444445
"qjobs": "^1.2.0",
445446
"range-parser": "^1.2.1",
446447
"rimraf": "^3.0.2",
@@ -479,7 +480,6 @@
479480
"karma-mocha": "^1.0.1",
480481
"karma-mocha-reporter": "^2.0.0",
481482
"karma-script-launcher": "^1.0.0",
482-
"mkdirp": "^0.5.0",
483483
"mocha": "^4.1.0",
484484
"mocks": "^0.0.15",
485485
"proxyquire": "^2.1.3",

‎test/unit/helper.spec.js

+10-23
Original file line numberDiff line numberDiff line change
@@ -229,36 +229,23 @@ describe('helper', () => {
229229
})
230230

231231
describe('mkdirIfNotExists', () => {
232-
const fsMock = require('mocks').fs
233232
const loadFile = require('mocks').loadFile
234233

235-
const fs = fsMock.create({
236-
home: { 'some.js': fsMock.file() }
237-
})
234+
const spy = sinon.spy()
238235

239236
// load file under test
240-
const m = loadFile(path.join(__dirname, '/../../lib/helper.js'), { 'graceful-fs': fs, lodash: require('lodash') })
241-
242-
const mkdirIfNotExists = m.exports.mkdirIfNotExists
243-
244-
it('should not do anything, if dir already exists', (done) => {
245-
mkdirIfNotExists('/home', done)
246-
})
247-
248-
it('should create directory if it does not exist', (done) => {
249-
mkdirIfNotExists('/home/new', () => {
250-
const stat = fs.statSync('/home/new')
251-
expect(stat).to.exist
252-
expect(stat.isDirectory()).to.equal(true)
237+
const m = loadFile(path.join(__dirname, '/../../lib/helper.js'), {
238+
mkdirp: (path, done) => {
239+
spy(path)
253240
done()
254-
})
241+
}
255242
})
256243

257-
it('should create even parent directories if it does not exist', (done) => {
258-
mkdirIfNotExists('/home/new/parent/child', () => {
259-
const stat = fs.statSync('/home/new/parent/child')
260-
expect(stat).to.exist
261-
expect(stat.isDirectory()).to.equal(true)
244+
const mkdirIfNotExists = m.exports.mkdirIfNotExists
245+
246+
it('should call mkdirp', (done) => {
247+
mkdirIfNotExists('/path/to/dir', () => {
248+
expect(spy).to.have.been.calledOnceWith('/path/to/dir')
262249
done()
263250
})
264251
})

0 commit comments

Comments
 (0)
Please sign in to comment.