metro-file-map 0.80.5 → 0.80.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/package.json +1 -1
  2. package/src/Watcher.js +0 -20
  3. package/src/Watcher.js.flow +2 -2
  4. package/src/cache/DiskCacheManager.js +0 -13
  5. package/src/constants.js +1 -29
  6. package/src/crawlers/__fixtures__/directory/bar.js +0 -10
  7. package/src/crawlers/__fixtures__/foo.js +0 -10
  8. package/src/crawlers/__fixtures__/ignored/hidden.js +0 -10
  9. package/src/crawlers/__fixtures__/link-to-directory/bar.js +0 -10
  10. package/src/crawlers/__fixtures__/link-to-foo.js +0 -10
  11. package/src/crawlers/node/hasNativeFindSupport.js +0 -12
  12. package/src/crawlers/node/index.js +9 -24
  13. package/src/crawlers/node/index.js.flow +6 -3
  14. package/src/crawlers/watchman/index.js +16 -52
  15. package/src/crawlers/watchman/index.js.flow +14 -8
  16. package/src/crawlers/watchman/planQuery.js +0 -64
  17. package/src/flow-types.d.ts +1 -1
  18. package/src/flow-types.js +0 -11
  19. package/src/flow-types.js.flow +29 -1
  20. package/src/getMockName.js +0 -10
  21. package/src/index.js +18 -216
  22. package/src/index.js.flow +16 -11
  23. package/src/lib/DuplicateError.js +0 -11
  24. package/src/lib/DuplicateHasteCandidatesError.js +0 -11
  25. package/src/lib/MockMap.js +4 -15
  26. package/src/lib/MockMap.js.flow +4 -2
  27. package/src/lib/MutableHasteMap.js +6 -79
  28. package/src/lib/MutableHasteMap.js.flow +6 -4
  29. package/src/lib/RootPathUtils.js +168 -0
  30. package/src/lib/RootPathUtils.js.flow +211 -0
  31. package/src/lib/TreeFS.js +96 -159
  32. package/src/lib/TreeFS.js.flow +118 -43
  33. package/src/lib/checkWatchmanCapabilities.js +4 -12
  34. package/src/lib/checkWatchmanCapabilities.js.flow +2 -1
  35. package/src/lib/dependencyExtractor.js +7 -25
  36. package/src/lib/fast_path.js +27 -34
  37. package/src/lib/fast_path.js.flow +31 -9
  38. package/src/lib/getPlatformExtension.js +0 -11
  39. package/src/lib/normalizePathSeparatorsToPosix.js +0 -10
  40. package/src/lib/normalizePathSeparatorsToSystem.js +0 -10
  41. package/src/lib/rootRelativeCacheKeys.js +3 -58
  42. package/src/lib/rootRelativeCacheKeys.js.flow +3 -2
  43. package/src/watchers/FSEventsWatcher.js +1 -41
  44. package/src/watchers/NodeWatcher.js +1 -104
  45. package/src/watchers/RecrawlWarning.js +0 -19
  46. package/src/watchers/WatchmanWatcher.js +3 -55
  47. package/src/watchers/common.js +1 -49
  48. package/src/worker.js +18 -45
  49. package/src/workerExclusionList.js +1 -26
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metro-file-map",
3
- "version": "0.80.5",
3
+ "version": "0.80.7",
4
4
  "description": "[Experimental] - 🚇 File crawling, watching and mapping for Metro",
5
5
  "main": "src/index.js",
6
6
  "repository": {
package/src/Watcher.js CHANGED
@@ -62,16 +62,6 @@ function _interopRequireWildcard(obj, nodeInterop) {
62
62
  function _interopRequireDefault(obj) {
63
63
  return obj && obj.__esModule ? obj : { default: obj };
64
64
  }
65
- /**
66
- * Copyright (c) Meta Platforms, Inc. and affiliates.
67
- *
68
- * This source code is licensed under the MIT license found in the
69
- * LICENSE file in the root directory of this source tree.
70
- *
71
- * @format
72
- *
73
- */
74
-
75
65
  const debug = require("debug")("Metro:Watcher");
76
66
  const MAX_WAIT_TIME = 240000;
77
67
  let nextInstanceId = 0;
@@ -120,7 +110,6 @@ class Watcher extends _events.default {
120
110
  " " +
121
111
  error.toString()
122
112
  );
123
- // $FlowFixMe[prop-missing] Found when updating Promise type definition
124
113
  return (0, _node.default)(crawlerOptions).catch((e) => {
125
114
  throw new Error(
126
115
  "Crawler retry failed:\n" +
@@ -144,7 +133,6 @@ class Watcher extends _events.default {
144
133
  };
145
134
  debug('Beginning crawl with "%s".', crawler);
146
135
  try {
147
- // $FlowFixMe[incompatible-call] Found when updating Promise type definition
148
136
  return crawl(crawlerOptions).catch(retry).then(logEnd);
149
137
  } catch (error) {
150
138
  return retry(error).then(logEnd);
@@ -152,8 +140,6 @@ class Watcher extends _events.default {
152
140
  }
153
141
  async watch(onChange) {
154
142
  const { extensions, ignorePattern, useWatchman } = this._options;
155
-
156
- // WatchmanWatcher > FSEventsWatcher > sane.NodeWatcher
157
143
  const WatcherImpl = useWatchman
158
144
  ? _WatchmanWatcher.default
159
145
  : _FSEventsWatcher.default.isSupported()
@@ -176,10 +162,7 @@ class Watcher extends _events.default {
176
162
  const watcherOptions = {
177
163
  dot: true,
178
164
  glob: [
179
- // Ensure we always include package.json files, which are crucial for
180
- /// module resolution.
181
165
  "**/package.json",
182
- // Ensure we always watch any health check files
183
166
  "**/" + this._options.healthCheckFilePrefix + "*",
184
167
  ...extensions.map((extension) => "**/*." + extension),
185
168
  ],
@@ -287,9 +270,6 @@ class Watcher extends _events.default {
287
270
  creationPromise.then(() => observationPromise),
288
271
  ]);
289
272
  this._pendingHealthChecks.delete(basename);
290
- // Chain a deletion to the creation promise (which may not have even settled yet!),
291
- // don't await it, and swallow errors. This is just best-effort cleanup.
292
- // $FlowFixMe[unused-promise]
293
273
  creationPromise.then(() =>
294
274
  fs.promises.unlink(healthCheckPath).catch(() => {})
295
275
  );
@@ -176,8 +176,8 @@ export class Watcher extends EventEmitter {
176
176
  const WatcherImpl = useWatchman
177
177
  ? WatchmanWatcher
178
178
  : FSEventsWatcher.isSupported()
179
- ? FSEventsWatcher
180
- : NodeWatcher;
179
+ ? FSEventsWatcher
180
+ : NodeWatcher;
181
181
 
182
182
  let watcher = 'node';
183
183
  if (WatcherImpl === WatchmanWatcher) {
@@ -14,17 +14,6 @@ var _v = require("v8");
14
14
  function _interopRequireDefault(obj) {
15
15
  return obj && obj.__esModule ? obj : { default: obj };
16
16
  }
17
- /**
18
- * Copyright (c) Meta Platforms, Inc. and affiliates.
19
- *
20
- * This source code is licensed under the MIT license found in the
21
- * LICENSE file in the root directory of this source tree.
22
- *
23
- *
24
- * @format
25
- * @oncall react_native
26
- */
27
-
28
17
  const DEFAULT_PREFIX = "metro-file-map";
29
18
  const DEFAULT_DIRECTORY = (0, _os.tmpdir)();
30
19
  class DiskCacheManager {
@@ -55,10 +44,8 @@ class DiskCacheManager {
55
44
  );
56
45
  } catch (e) {
57
46
  if (e?.code === "ENOENT") {
58
- // Cache file not found - not considered an error.
59
47
  return null;
60
48
  }
61
- // Rethrow anything else.
62
49
  throw e;
63
50
  }
64
51
  }
package/src/constants.js CHANGED
@@ -1,32 +1,7 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- *
8
- * @noformat - Flow comment syntax
9
- */
10
-
11
- /*
12
- * This file exports a set of constants that are used for Jest's haste map
13
- * serialization. On very large repositories, the haste map cache becomes very
14
- * large to the point where it is the largest overhead in starting up Jest.
15
- *
16
- * This constant key map allows to keep the map smaller without having to build
17
- * a custom serialization library.
18
- */
19
-
20
- /*::
21
- import type {HType} from './flow-types';
22
- */
23
-
24
1
  "use strict";
25
2
 
26
- const constants /*: HType */ = {
27
- /* dependency serialization */
3
+ const constants = {
28
4
  DEPENDENCY_DELIM: "\0",
29
- /* file map attributes */
30
5
  ID: 0,
31
6
  MTIME: 1,
32
7
  SIZE: 2,
@@ -34,13 +9,10 @@ const constants /*: HType */ = {
34
9
  DEPENDENCIES: 4,
35
10
  SHA1: 5,
36
11
  SYMLINK: 6,
37
- /* module map attributes */
38
12
  PATH: 0,
39
13
  TYPE: 1,
40
- /* module types */
41
14
  MODULE: 0,
42
15
  PACKAGE: 1,
43
- /* platforms */
44
16
  GENERIC_PLATFORM: "g",
45
17
  NATIVE_PLATFORM: "native",
46
18
  };
@@ -1,11 +1 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- *
8
- * @format
9
- * @oncall react_native
10
- */
11
1
  "use strict";
@@ -1,11 +1 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- *
8
- * @format
9
- * @oncall react_native
10
- */
11
1
  "use strict";
@@ -1,11 +1 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- *
8
- * @format
9
- * @oncall react_native
10
- */
11
1
  "use strict";
@@ -1,11 +1 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- *
8
- * @format
9
- * @oncall react_native
10
- */
11
1
  "use strict";
@@ -1,11 +1 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- *
8
- * @format
9
- * @oncall react_native
10
- */
11
1
  "use strict";
@@ -5,21 +5,9 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = hasNativeFindSupport;
7
7
  var _child_process = require("child_process");
8
- /**
9
- * Copyright (c) Meta Platforms, Inc. and affiliates.
10
- *
11
- * This source code is licensed under the MIT license found in the
12
- * LICENSE file in the root directory of this source tree.
13
- *
14
- *
15
- * @format
16
- * @oncall react_native
17
- */
18
-
19
8
  async function hasNativeFindSupport() {
20
9
  try {
21
10
  return await new Promise((resolve) => {
22
- // Check the find binary supports the non-POSIX -iname parameter wrapped in parens.
23
11
  const args = [
24
12
  ".",
25
13
  "-type",
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- var fastPath = _interopRequireWildcard(require("../../lib/fast_path"));
3
+ var _RootPathUtils = require("../../lib/RootPathUtils");
4
4
  var _hasNativeFindSupport = _interopRequireDefault(
5
5
  require("./hasNativeFindSupport")
6
6
  );
@@ -8,9 +8,6 @@ var _child_process = require("child_process");
8
8
  var fs = _interopRequireWildcard(require("graceful-fs"));
9
9
  var _os = require("os");
10
10
  var path = _interopRequireWildcard(require("path"));
11
- function _interopRequireDefault(obj) {
12
- return obj && obj.__esModule ? obj : { default: obj };
13
- }
14
11
  function _getRequireWildcardCache(nodeInterop) {
15
12
  if (typeof WeakMap !== "function") return null;
16
13
  var cacheBabelInterop = new WeakMap();
@@ -51,21 +48,14 @@ function _interopRequireWildcard(obj, nodeInterop) {
51
48
  }
52
49
  return newObj;
53
50
  }
54
- /**
55
- * Copyright (c) Meta Platforms, Inc. and affiliates.
56
- *
57
- * This source code is licensed under the MIT license found in the
58
- * LICENSE file in the root directory of this source tree.
59
- *
60
- *
61
- * @format
62
- * @oncall react_native
63
- */
64
-
51
+ function _interopRequireDefault(obj) {
52
+ return obj && obj.__esModule ? obj : { default: obj };
53
+ }
65
54
  const debug = require("debug")("Metro:NodeCrawler");
66
55
  function find(roots, extensions, ignore, includeSymlinks, rootDir, callback) {
67
56
  const result = new Map();
68
57
  let activeCalls = 0;
58
+ const pathUtils = new _RootPathUtils.RootPathUtils(rootDir);
69
59
  function search(directory) {
70
60
  activeCalls++;
71
61
  fs.readdir(
@@ -97,7 +87,7 @@ function find(roots, extensions, ignore, includeSymlinks, rootDir, callback) {
97
87
  if (!err && stat) {
98
88
  const ext = path.extname(file).substr(1);
99
89
  if (stat.isSymbolicLink() || extensions.includes(ext)) {
100
- result.set(fastPath.relative(rootDir, file), [
90
+ result.set(pathUtils.absoluteToNormal(file), [
101
91
  "",
102
92
  stat.mtime.getTime(),
103
93
  stat.size,
@@ -133,17 +123,13 @@ function findNative(
133
123
  rootDir,
134
124
  callback
135
125
  ) {
136
- // Examples:
137
- // ( ( -type f ( -iname *.js ) ) )
138
- // ( ( -type f ( -iname *.js -o -iname *.ts ) ) )
139
- // ( ( -type f ( -iname *.js ) ) -o -type l )
140
- // ( ( -type f ) -o -type l )
141
126
  const extensionClause = extensions.length
142
127
  ? `( ${extensions.map((ext) => `-iname *.${ext}`).join(" -o ")} )`
143
- : ""; // Empty inner expressions eg "( )" are not allowed
128
+ : "";
144
129
  const expression = `( ( -type f ${extensionClause} ) ${
145
130
  includeSymlinks ? "-o -type l " : ""
146
131
  })`;
132
+ const pathUtils = new _RootPathUtils.RootPathUtils(rootDir);
147
133
  const child = (0, _child_process.spawn)(
148
134
  "find",
149
135
  roots.concat(expression.split(" "))
@@ -169,7 +155,7 @@ function findNative(
169
155
  lines.forEach((path) => {
170
156
  fs.lstat(path, (err, stat) => {
171
157
  if (!err && stat) {
172
- result.set(fastPath.relative(rootDir, path), [
158
+ result.set(pathUtils.absoluteToNormal(path), [
173
159
  "",
174
160
  stat.mtime.getTime(),
175
161
  stat.size,
@@ -211,7 +197,6 @@ module.exports = async function nodeCrawl(options) {
211
197
  const difference = previousState.fileSystem.getDifference(fileData);
212
198
  perfLogger?.point("nodeCrawl_end");
213
199
  try {
214
- // TODO: Use AbortSignal.reason directly when Flow supports it
215
200
  abortSignal?.throwIfAborted();
216
201
  } catch (e) {
217
202
  reject(e);
@@ -16,7 +16,7 @@ import type {
16
16
  IgnoreMatcher,
17
17
  } from '../../flow-types';
18
18
 
19
- import * as fastPath from '../../lib/fast_path';
19
+ import {RootPathUtils} from '../../lib/RootPathUtils';
20
20
  import hasNativeFindSupport from './hasNativeFindSupport';
21
21
  import {spawn} from 'child_process';
22
22
  import * as fs from 'graceful-fs';
@@ -37,6 +37,7 @@ function find(
37
37
  ): void {
38
38
  const result: FileData = new Map();
39
39
  let activeCalls = 0;
40
+ const pathUtils = new RootPathUtils(rootDir);
40
41
 
41
42
  function search(directory: string): void {
42
43
  activeCalls++;
@@ -71,7 +72,7 @@ function find(
71
72
  if (!err && stat) {
72
73
  const ext = path.extname(file).substr(1);
73
74
  if (stat.isSymbolicLink() || extensions.includes(ext)) {
74
- result.set(fastPath.relative(rootDir, file), [
75
+ result.set(pathUtils.absoluteToNormal(file), [
75
76
  '',
76
77
  stat.mtime.getTime(),
77
78
  stat.size,
@@ -122,6 +123,8 @@ function findNative(
122
123
  includeSymlinks ? '-o -type l ' : ''
123
124
  })`;
124
125
 
126
+ const pathUtils = new RootPathUtils(rootDir);
127
+
125
128
  const child = spawn('find', roots.concat(expression.split(' ')));
126
129
  let stdout = '';
127
130
  if (child.stdout == null) {
@@ -145,7 +148,7 @@ function findNative(
145
148
  lines.forEach(path => {
146
149
  fs.lstat(path, (err, stat) => {
147
150
  if (!err && stat) {
148
- result.set(fastPath.relative(rootDir, path), [
151
+ result.set(pathUtils.absoluteToNormal(path), [
149
152
  '',
150
153
  stat.mtime.getTime(),
151
154
  stat.size,
@@ -1,19 +1,16 @@
1
1
  "use strict";
2
2
 
3
- var fastPath = _interopRequireWildcard(require("../../lib/fast_path"));
4
3
  var _normalizePathSeparatorsToPosix = _interopRequireDefault(
5
4
  require("../../lib/normalizePathSeparatorsToPosix")
6
5
  );
7
6
  var _normalizePathSeparatorsToSystem = _interopRequireDefault(
8
7
  require("../../lib/normalizePathSeparatorsToSystem")
9
8
  );
9
+ var _RootPathUtils = require("../../lib/RootPathUtils");
10
10
  var _planQuery = require("./planQuery");
11
11
  var _invariant = _interopRequireDefault(require("invariant"));
12
12
  var path = _interopRequireWildcard(require("path"));
13
13
  var _perf_hooks = require("perf_hooks");
14
- function _interopRequireDefault(obj) {
15
- return obj && obj.__esModule ? obj : { default: obj };
16
- }
17
14
  function _getRequireWildcardCache(nodeInterop) {
18
15
  if (typeof WeakMap !== "function") return null;
19
16
  var cacheBabelInterop = new WeakMap();
@@ -54,17 +51,9 @@ function _interopRequireWildcard(obj, nodeInterop) {
54
51
  }
55
52
  return newObj;
56
53
  }
57
- /**
58
- * Copyright (c) Meta Platforms, Inc. and affiliates.
59
- *
60
- * This source code is licensed under the MIT license found in the
61
- * LICENSE file in the root directory of this source tree.
62
- *
63
- *
64
- * @format
65
- * @oncall react_native
66
- */
67
-
54
+ function _interopRequireDefault(obj) {
55
+ return obj && obj.__esModule ? obj : { default: obj };
56
+ }
68
57
  const watchman = require("fb-watchman");
69
58
  const WATCHMAN_WARNING_INITIAL_DELAY_MILLISECONDS = 10000;
70
59
  const WATCHMAN_WARNING_INTERVAL_MILLISECONDS = 20000;
@@ -89,6 +78,7 @@ module.exports = async function watchmanCrawl({
89
78
  }) {
90
79
  abortSignal?.throwIfAborted();
91
80
  const client = new watchman.Client();
81
+ const pathUtils = new _RootPathUtils.RootPathUtils(rootDir);
92
82
  abortSignal?.addEventListener("abort", () => client.end());
93
83
  perfLogger?.point("watchmanCrawl_start");
94
84
  const newClocks = new Map();
@@ -96,11 +86,7 @@ module.exports = async function watchmanCrawl({
96
86
  client.on("error", (error) => {
97
87
  clientError = makeWatchmanError(error);
98
88
  });
99
- const cmd = async (
100
- command,
101
- // $FlowFixMe[unclear-type] - Fix to use fb-watchman types
102
- ...args
103
- ) => {
89
+ const cmd = async (command, ...args) => {
104
90
  let didLogWatchmanWaitMessage = false;
105
91
  const startTime = _perf_hooks.performance.now();
106
92
  const logWatchmanWaitMessage = () => {
@@ -120,7 +106,6 @@ module.exports = async function watchmanCrawl({
120
106
  }, WATCHMAN_WARNING_INITIAL_DELAY_MILLISECONDS);
121
107
  try {
122
108
  const response = await new Promise((resolve, reject) =>
123
- // $FlowFixMe[incompatible-call] - dynamic call of command
124
109
  client.command([command, ...args], (error, result) =>
125
110
  error ? reject(makeWatchmanError(error)) : resolve(result)
126
111
  )
@@ -132,10 +117,8 @@ module.exports = async function watchmanCrawl({
132
117
  command,
133
118
  });
134
119
  }
135
- // $FlowFixMe[incompatible-return]
136
120
  return response;
137
121
  } finally {
138
- // $FlowFixMe[incompatible-call] clearInterval / clearTimeout are interchangeable
139
122
  clearInterval(intervalOrTimeoutId);
140
123
  if (didLogWatchmanWaitMessage) {
141
124
  onStatus({
@@ -155,8 +138,6 @@ module.exports = async function watchmanCrawl({
155
138
  const response = await cmd("watch-project", root);
156
139
  perfLogger?.point(`watchmanCrawl/watchProject_${index}_end`);
157
140
  const existing = watchmanRoots.get(response.watch);
158
- // A root can only be filtered if it was never seen with a
159
- // relative_path before.
160
141
  const canBeFiltered = !existing || existing.directoryFilters.length > 0;
161
142
  if (canBeFiltered) {
162
143
  if (response.relative_path) {
@@ -167,9 +148,6 @@ module.exports = async function watchmanCrawl({
167
148
  ),
168
149
  });
169
150
  } else {
170
- // Make the filter directories an empty array to signal that this
171
- // root was already seen and needs to be watched for all files or
172
- // directories.
173
151
  watchmanRoots.set(response.watch, {
174
152
  watcher: response.watcher,
175
153
  directoryFilters: [],
@@ -187,18 +165,14 @@ module.exports = async function watchmanCrawl({
187
165
  let isFresh = false;
188
166
  await Promise.all(
189
167
  Array.from(rootProjectDirMappings).map(
190
- async ([root, { directoryFilters, watcher }], index) => {
191
- // Jest is only going to store one type of clock; a string that
192
- // represents a local clock. However, the Watchman crawler supports
193
- // a second type of clock that can be written by automation outside of
194
- // Jest, called an "scm query", which fetches changed files based on
195
- // source control mergebases. The reason this is necessary is because
196
- // local clocks are not portable across systems, but scm queries are.
197
- // By using scm queries, we can create the haste map on a different
198
- // system and import it, transforming the clock into a local clock.
168
+ async ([posixSeparatedRoot, { directoryFilters, watcher }], index) => {
199
169
  const since = previousState.clocks.get(
200
170
  (0, _normalizePathSeparatorsToPosix.default)(
201
- fastPath.relative(rootDir, root)
171
+ pathUtils.absoluteToNormal(
172
+ (0, _normalizePathSeparatorsToSystem.default)(
173
+ posixSeparatedRoot
174
+ )
175
+ )
202
176
  )
203
177
  );
204
178
  perfLogger?.annotate({
@@ -220,18 +194,14 @@ module.exports = async function watchmanCrawl({
220
194
  },
221
195
  });
222
196
  perfLogger?.point(`watchmanCrawl/query_${index}_start`);
223
- const response = await cmd("query", root, query);
197
+ const response = await cmd("query", posixSeparatedRoot, query);
224
198
  perfLogger?.point(`watchmanCrawl/query_${index}_end`);
225
-
226
- // When a source-control query is used, we ignore the "is fresh"
227
- // response from Watchman because it will be true despite the query
228
- // being incremental.
229
199
  const isSourceControlQuery =
230
200
  typeof since !== "string" && since?.scm?.["mergebase-with"] != null;
231
201
  if (!isSourceControlQuery) {
232
202
  isFresh = isFresh || response.is_fresh_instance;
233
203
  }
234
- results.set(root, response);
204
+ results.set(posixSeparatedRoot, response);
235
205
  }
236
206
  )
237
207
  );
@@ -282,10 +252,9 @@ module.exports = async function watchmanCrawl({
282
252
  const freshFileData = new Map();
283
253
  for (const [watchRoot, response] of results) {
284
254
  const fsRoot = (0, _normalizePathSeparatorsToSystem.default)(watchRoot);
285
- const relativeFsRoot = fastPath.relative(rootDir, fsRoot);
255
+ const relativeFsRoot = pathUtils.absoluteToNormal(fsRoot);
286
256
  newClocks.set(
287
257
  (0, _normalizePathSeparatorsToPosix.default)(relativeFsRoot),
288
- // Ensure we persist only the local clock.
289
258
  typeof response.clock === "string" ? response.clock : response.clock.clock
290
259
  );
291
260
  for (const fileData of response.files) {
@@ -293,13 +262,11 @@ module.exports = async function watchmanCrawl({
293
262
  fsRoot +
294
263
  path.sep +
295
264
  (0, _normalizePathSeparatorsToSystem.default)(fileData.name);
296
- const relativeFilePath = fastPath.relative(rootDir, filePath);
265
+ const relativeFilePath = pathUtils.absoluteToNormal(filePath);
297
266
  if (!fileData.exists) {
298
267
  if (!isFresh) {
299
268
  removedFiles.add(relativeFilePath);
300
269
  }
301
- // Whether watchman can return exists: false in a fresh instance
302
- // response is unknown, but there's nothing we need to do in that case.
303
270
  } else if (!ignore(filePath)) {
304
271
  const { mtime_ms, size } = fileData;
305
272
  (0, _invariant.default)(
@@ -317,9 +284,6 @@ module.exports = async function watchmanCrawl({
317
284
  symlinkInfo = fileData["symlink_target"] ?? 1;
318
285
  }
319
286
  const nextData = ["", mtime, size, 0, "", sha1hex ?? null, symlinkInfo];
320
-
321
- // If watchman is fresh, the removed files map starts with all files
322
- // and we remove them as we verify they still exist.
323
287
  if (isFresh) {
324
288
  freshFileData.set(relativeFilePath, nextData);
325
289
  } else {
@@ -20,9 +20,9 @@ import type {
20
20
  } from '../../flow-types';
21
21
  import type {WatchmanQueryResponse, WatchmanWatchResponse} from 'fb-watchman';
22
22
 
23
- import * as fastPath from '../../lib/fast_path';
24
23
  import normalizePathSeparatorsToPosix from '../../lib/normalizePathSeparatorsToPosix';
25
24
  import normalizePathSeparatorsToSystem from '../../lib/normalizePathSeparatorsToSystem';
25
+ import {RootPathUtils} from '../../lib/RootPathUtils';
26
26
  import {planQuery} from './planQuery';
27
27
  import invariant from 'invariant';
28
28
  import * as path from 'path';
@@ -31,7 +31,7 @@ import {performance} from 'perf_hooks';
31
31
  const watchman = require('fb-watchman');
32
32
 
33
33
  type WatchmanRoots = Map<
34
- string,
34
+ string, // Posix-separated absolute path
35
35
  $ReadOnly<{directoryFilters: Array<string>, watcher: string}>,
36
36
  >;
37
37
 
@@ -66,6 +66,7 @@ module.exports = async function watchmanCrawl({
66
66
  abortSignal?.throwIfAborted();
67
67
 
68
68
  const client = new watchman.Client();
69
+ const pathUtils = new RootPathUtils(rootDir);
69
70
  abortSignal?.addEventListener('abort', () => client.end());
70
71
 
71
72
  perfLogger?.point('watchmanCrawl_start');
@@ -177,9 +178,10 @@ module.exports = async function watchmanCrawl({
177
178
  perfLogger?.point('watchmanCrawl/queryWatchmanForDirs_start');
178
179
  const results = new Map<string, WatchmanQueryResponse>();
179
180
  let isFresh = false;
181
+
180
182
  await Promise.all(
181
183
  Array.from(rootProjectDirMappings).map(
182
- async ([root, {directoryFilters, watcher}], index) => {
184
+ async ([posixSeparatedRoot, {directoryFilters, watcher}], index) => {
183
185
  // Jest is only going to store one type of clock; a string that
184
186
  // represents a local clock. However, the Watchman crawler supports
185
187
  // a second type of clock that can be written by automation outside of
@@ -189,7 +191,11 @@ module.exports = async function watchmanCrawl({
189
191
  // By using scm queries, we can create the haste map on a different
190
192
  // system and import it, transforming the clock into a local clock.
191
193
  const since = previousState.clocks.get(
192
- normalizePathSeparatorsToPosix(fastPath.relative(rootDir, root)),
194
+ normalizePathSeparatorsToPosix(
195
+ pathUtils.absoluteToNormal(
196
+ normalizePathSeparatorsToSystem(posixSeparatedRoot),
197
+ ),
198
+ ),
193
199
  );
194
200
 
195
201
  perfLogger?.annotate({
@@ -216,7 +222,7 @@ module.exports = async function watchmanCrawl({
216
222
  perfLogger?.point(`watchmanCrawl/query_${index}_start`);
217
223
  const response = await cmd<WatchmanQueryResponse>(
218
224
  'query',
219
- root,
225
+ posixSeparatedRoot,
220
226
  query,
221
227
  );
222
228
  perfLogger?.point(`watchmanCrawl/query_${index}_end`);
@@ -230,7 +236,7 @@ module.exports = async function watchmanCrawl({
230
236
  isFresh = isFresh || response.is_fresh_instance;
231
237
  }
232
238
 
233
- results.set(root, response);
239
+ results.set(posixSeparatedRoot, response);
234
240
  },
235
241
  ),
236
242
  );
@@ -288,7 +294,7 @@ module.exports = async function watchmanCrawl({
288
294
 
289
295
  for (const [watchRoot, response] of results) {
290
296
  const fsRoot = normalizePathSeparatorsToSystem(watchRoot);
291
- const relativeFsRoot = fastPath.relative(rootDir, fsRoot);
297
+ const relativeFsRoot = pathUtils.absoluteToNormal(fsRoot);
292
298
  newClocks.set(
293
299
  normalizePathSeparatorsToPosix(relativeFsRoot),
294
300
  // Ensure we persist only the local clock.
@@ -300,7 +306,7 @@ module.exports = async function watchmanCrawl({
300
306
  for (const fileData of response.files) {
301
307
  const filePath =
302
308
  fsRoot + path.sep + normalizePathSeparatorsToSystem(fileData.name);
303
- const relativeFilePath = fastPath.relative(rootDir, filePath);
309
+ const relativeFilePath = pathUtils.absoluteToNormal(filePath);
304
310
 
305
311
  if (!fileData.exists) {
306
312
  if (!isFresh) {