Skip to content

Commit 2b83f75

Browse files
fix: crash on unix based systems without find (#9579)
1 parent 1ed46e7 commit 2b83f75

File tree

5 files changed

+57
-7
lines changed

5 files changed

+57
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- `[jest-cli]` Set `coverageProvider` correctly when provided in config ([#9562](https://github.com/facebook/jest/pull/9562))
1818
- `[jest-cli]` Allow specifying `.cjs` and `.mjs` config files by `--config` CLI option ([#9578](https://github.com/facebook/jest/pull/9578))
1919
- `[jest-config]` Ensure pattern of `replacePosixSep` is a string ([#9546]https://github.com/facebook/jest/pull/9546)
20+
- `[jest-haste-map]` Fix crash on unix based systems without find ([#9579](https://github.com/facebook/jest/pull/9579))
2021
- `[jest-matcher-utils]` Fix diff highlight of symbol-keyed object. ([#9499](https://github.com/facebook/jest/pull/9499))
2122
- `[@jest/reporters]` Notifications should be fire&forget rather than having a timeout ([#9567](https://github.com/facebook/jest/pull/9567))
2223
- `[jest-resolve]` Fix module identity preservation with symlinks and browser field resolution ([#9511](https://github.com/facebook/jest/pull/9511))

packages/jest-haste-map/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"jest-worker": "^25.1.0",
2020
"micromatch": "^4.0.2",
2121
"sane": "^4.0.3",
22-
"walker": "^1.0.7"
22+
"walker": "^1.0.7",
23+
"which": "^2.0.2"
2324
},
2425
"devDependencies": {
2526
"@jest/test-utils": "^25.1.0",
@@ -28,7 +29,8 @@
2829
"@types/graceful-fs": "^4.1.2",
2930
"@types/micromatch": "^4.0.0",
3031
"@types/node": "*",
31-
"@types/sane": "^2.0.0"
32+
"@types/sane": "^2.0.0",
33+
"@types/which": "^1.3.2"
3234
},
3335
"optionalDependencies": {
3436
"fsevents": "^2.1.2"

packages/jest-haste-map/src/crawlers/__tests__/node.test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ jest.mock('fs', () => {
124124
};
125125
});
126126

127+
jest.mock('which', () => jest.fn().mockResolvedValue());
128+
127129
const pearMatcher = path => /pear/.test(path);
128130
const createMap = obj => new Map(Object.keys(obj).map(key => [key, obj[key]]));
129131

@@ -291,6 +293,33 @@ describe('node crawler', () => {
291293
});
292294
});
293295

296+
it('uses node fs APIs on Unix based OS without find binary', () => {
297+
process.platform = 'linux';
298+
const which = require('which');
299+
which.mockReturnValueOnce(Promise.reject());
300+
301+
nodeCrawl = require('../node');
302+
303+
return nodeCrawl({
304+
data: {
305+
files: new Map(),
306+
},
307+
extensions: ['js'],
308+
ignore: pearMatcher,
309+
rootDir,
310+
roots: ['/project/fruits'],
311+
}).then(({hasteMap, removedFiles}) => {
312+
expect(hasteMap.files).toEqual(
313+
createMap({
314+
'fruits/directory/strawberry.js': ['', 33, 42, 0, '', null],
315+
'fruits/tomato.js': ['', 32, 42, 0, '', null],
316+
}),
317+
);
318+
expect(removedFiles).toEqual(new Map());
319+
expect(which).toBeCalledWith('find');
320+
});
321+
});
322+
294323
it('uses node fs APIs if "forceNodeFilesystemAPI" is set to true, regardless of platform', () => {
295324
process.platform = 'linux';
296325

packages/jest-haste-map/src/crawlers/node.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import * as fs from 'fs';
99
import * as path from 'path';
1010
import {spawn} from 'child_process';
11+
import which = require('which');
1112
import H from '../constants';
1213
import * as fastPath from '../lib/fast_path';
1314
import {
@@ -21,6 +22,21 @@ type Result = Array<[/* id */ string, /* mtime */ number, /* size */ number]>;
2122

2223
type Callback = (result: Result) => void;
2324

25+
async function hasNativeFindSupport(
26+
forceNodeFilesystemAPI: boolean,
27+
): Promise<boolean> {
28+
if (forceNodeFilesystemAPI || process.platform === 'win32') {
29+
return false;
30+
}
31+
32+
try {
33+
await which('find');
34+
return true;
35+
} catch {
36+
return false;
37+
}
38+
}
39+
2440
function find(
2541
roots: Array<string>,
2642
extensions: Array<string>,
@@ -154,7 +170,7 @@ function findNative(
154170
});
155171
}
156172

157-
export = function nodeCrawl(
173+
export = async function nodeCrawl(
158174
options: CrawlerOptions,
159175
): Promise<{
160176
removedFiles: FileData;
@@ -169,6 +185,8 @@ export = function nodeCrawl(
169185
roots,
170186
} = options;
171187

188+
const useNativeFind = await hasNativeFindSupport(forceNodeFilesystemAPI);
189+
172190
return new Promise(resolve => {
173191
const callback = (list: Result) => {
174192
const files = new Map();
@@ -193,10 +211,10 @@ export = function nodeCrawl(
193211
});
194212
};
195213

196-
if (forceNodeFilesystemAPI || process.platform === 'win32') {
197-
find(roots, extensions, ignore, callback);
198-
} else {
214+
if (useNativeFind) {
199215
findNative(roots, extensions, ignore, callback);
216+
} else {
217+
find(roots, extensions, ignore, callback);
200218
}
201219
});
202220
};

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14745,7 +14745,7 @@ [email protected], which@^1.2.1, which@^1.2.9, which@^1.3.0, which@^1.3.1:
1474514745
dependencies:
1474614746
isexe "^2.0.0"
1474714747

14748-
which@^2.0.1:
14748+
which@^2.0.1, which@^2.0.2:
1474914749
version "2.0.2"
1475014750
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
1475114751
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==

0 commit comments

Comments
 (0)