UNPKG

7.48 kBJavaScriptView Raw
1'use strict';
2
3function _child_process() {
4 const data = require('child_process');
5
6 _child_process = function () {
7 return data;
8 };
9
10 return data;
11}
12
13function path() {
14 const data = _interopRequireWildcard(require('path'));
15
16 path = function () {
17 return data;
18 };
19
20 return data;
21}
22
23function fs() {
24 const data = _interopRequireWildcard(require('graceful-fs'));
25
26 fs = function () {
27 return data;
28 };
29
30 return data;
31}
32
33var _constants = _interopRequireDefault(require('../constants'));
34
35var fastPath = _interopRequireWildcard(require('../lib/fast_path'));
36
37function _interopRequireDefault(obj) {
38 return obj && obj.__esModule ? obj : {default: obj};
39}
40
41function _getRequireWildcardCache(nodeInterop) {
42 if (typeof WeakMap !== 'function') return null;
43 var cacheBabelInterop = new WeakMap();
44 var cacheNodeInterop = new WeakMap();
45 return (_getRequireWildcardCache = function (nodeInterop) {
46 return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
47 })(nodeInterop);
48}
49
50function _interopRequireWildcard(obj, nodeInterop) {
51 if (!nodeInterop && obj && obj.__esModule) {
52 return obj;
53 }
54 if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
55 return {default: obj};
56 }
57 var cache = _getRequireWildcardCache(nodeInterop);
58 if (cache && cache.has(obj)) {
59 return cache.get(obj);
60 }
61 var newObj = {};
62 var hasPropertyDescriptor =
63 Object.defineProperty && Object.getOwnPropertyDescriptor;
64 for (var key in obj) {
65 if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
66 var desc = hasPropertyDescriptor
67 ? Object.getOwnPropertyDescriptor(obj, key)
68 : null;
69 if (desc && (desc.get || desc.set)) {
70 Object.defineProperty(newObj, key, desc);
71 } else {
72 newObj[key] = obj[key];
73 }
74 }
75 }
76 newObj.default = obj;
77 if (cache) {
78 cache.set(obj, newObj);
79 }
80 return newObj;
81}
82
83/**
84 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
85 *
86 * This source code is licensed under the MIT license found in the
87 * LICENSE file in the root directory of this source tree.
88 */
89async function hasNativeFindSupport(forceNodeFilesystemAPI) {
90 if (forceNodeFilesystemAPI) {
91 return false;
92 }
93
94 try {
95 return await new Promise(resolve => {
96 // Check the find binary supports the non-POSIX -iname parameter wrapped in parens.
97 const args = [
98 '.',
99 '-type',
100 'f',
101 '(',
102 '-iname',
103 '*.ts',
104 '-o',
105 '-iname',
106 '*.js',
107 ')'
108 ];
109 const child = (0, _child_process().spawn)('find', args, {
110 cwd: __dirname
111 });
112 child.on('error', () => {
113 resolve(false);
114 });
115 child.on('exit', code => {
116 resolve(code === 0);
117 });
118 });
119 } catch {
120 return false;
121 }
122}
123
124function find(roots, extensions, ignore, enableSymlinks, callback) {
125 const result = [];
126 let activeCalls = 0;
127
128 function search(directory) {
129 activeCalls++;
130 fs().readdir(
131 directory,
132 {
133 withFileTypes: true
134 },
135 (err, entries) => {
136 activeCalls--;
137
138 if (err) {
139 callback(result);
140 return;
141 } // node < v10.10 does not support the withFileTypes option, and
142 // entry will be a string.
143
144 entries.forEach(entry => {
145 const file = path().join(
146 directory,
147 typeof entry === 'string' ? entry : entry.name
148 );
149
150 if (ignore(file)) {
151 return;
152 }
153
154 if (typeof entry !== 'string') {
155 if (entry.isSymbolicLink()) {
156 return;
157 }
158
159 if (entry.isDirectory()) {
160 search(file);
161 return;
162 }
163 }
164
165 activeCalls++;
166 const stat = enableSymlinks ? fs().stat : fs().lstat;
167 stat(file, (err, stat) => {
168 activeCalls--; // This logic is unnecessary for node > v10.10, but leaving it in
169 // since we need it for backwards-compatibility still.
170
171 if (!err && stat && !stat.isSymbolicLink()) {
172 if (stat.isDirectory()) {
173 search(file);
174 } else {
175 const ext = path().extname(file).substr(1);
176
177 if (extensions.indexOf(ext) !== -1) {
178 result.push([file, stat.mtime.getTime(), stat.size]);
179 }
180 }
181 }
182
183 if (activeCalls === 0) {
184 callback(result);
185 }
186 });
187 });
188
189 if (activeCalls === 0) {
190 callback(result);
191 }
192 }
193 );
194 }
195
196 if (roots.length > 0) {
197 roots.forEach(search);
198 } else {
199 callback(result);
200 }
201}
202
203function findNative(roots, extensions, ignore, enableSymlinks, callback) {
204 const args = Array.from(roots);
205
206 if (enableSymlinks) {
207 args.push('(', '-type', 'f', '-o', '-type', 'l', ')');
208 } else {
209 args.push('-type', 'f');
210 }
211
212 if (extensions.length) {
213 args.push('(');
214 }
215
216 extensions.forEach((ext, index) => {
217 if (index) {
218 args.push('-o');
219 }
220
221 args.push('-iname');
222 args.push('*.' + ext);
223 });
224
225 if (extensions.length) {
226 args.push(')');
227 }
228
229 const child = (0, _child_process().spawn)('find', args);
230 let stdout = '';
231
232 if (child.stdout === null) {
233 throw new Error(
234 'stdout is null - this should never happen. Please open up an issue at https://github.com/facebook/jest'
235 );
236 }
237
238 child.stdout.setEncoding('utf-8');
239 child.stdout.on('data', data => (stdout += data));
240 child.stdout.on('close', () => {
241 const lines = stdout
242 .trim()
243 .split('\n')
244 .filter(x => !ignore(x));
245 const result = [];
246 let count = lines.length;
247
248 if (!count) {
249 callback([]);
250 } else {
251 lines.forEach(path => {
252 fs().stat(path, (err, stat) => {
253 // Filter out symlinks that describe directories
254 if (!err && stat && !stat.isDirectory()) {
255 result.push([path, stat.mtime.getTime(), stat.size]);
256 }
257
258 if (--count === 0) {
259 callback(result);
260 }
261 });
262 });
263 }
264 });
265}
266
267module.exports = async function nodeCrawl(options) {
268 const {
269 data,
270 extensions,
271 forceNodeFilesystemAPI,
272 ignore,
273 rootDir,
274 enableSymlinks,
275 roots
276 } = options;
277 const useNativeFind = await hasNativeFindSupport(forceNodeFilesystemAPI);
278 return new Promise(resolve => {
279 const callback = list => {
280 const files = new Map();
281 const removedFiles = new Map(data.files);
282 list.forEach(fileData => {
283 const [filePath, mtime, size] = fileData;
284 const relativeFilePath = fastPath.relative(rootDir, filePath);
285 const existingFile = data.files.get(relativeFilePath);
286
287 if (existingFile && existingFile[_constants.default.MTIME] === mtime) {
288 files.set(relativeFilePath, existingFile);
289 } else {
290 // See ../constants.js; SHA-1 will always be null and fulfilled later.
291 files.set(relativeFilePath, ['', mtime, size, 0, '', null]);
292 }
293
294 removedFiles.delete(relativeFilePath);
295 });
296 data.files = files;
297 resolve({
298 hasteMap: data,
299 removedFiles
300 });
301 };
302
303 if (useNativeFind) {
304 findNative(roots, extensions, ignore, enableSymlinks, callback);
305 } else {
306 find(roots, extensions, ignore, enableSymlinks, callback);
307 }
308 });
309};