Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[0.73.x] Hotfix release 0.73.9 - sync watcher backends with 0.76.0 #949

Merged
merged 8 commits into from
Mar 21, 2023
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"lerna": "2.4.0",
"version": "0.73.8",
"version": "0.73.9",
"npmClient": "yarn",
"useWorkspaces": true
}
4 changes: 2 additions & 2 deletions packages/buck-worker-tool/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "buck-worker-tool",
"version": "0.73.8",
"version": "0.73.9",
"description": "Implementation of the Buck worker protocol for Node.js.",
"license": "MIT",
"main": "src/worker-tool.js",
Expand All @@ -13,7 +13,7 @@
"through": ">=2.2.7 <3"
},
"devDependencies": {
"metro-memory-fs": "0.73.8"
"metro-memory-fs": "0.73.9"
},
"scripts": {
"prepare-release": "test -d build && rm -rf src.real && mv src src.real && mv build src",
Expand Down
2 changes: 1 addition & 1 deletion packages/metro-babel-register/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "metro-babel-register",
"version": "0.73.8",
"version": "0.73.9",
"description": "🚇 babel/register configuration for Metro.",
"main": "src/babel-register.js",
"repository": {
Expand Down
4 changes: 2 additions & 2 deletions packages/metro-babel-transformer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "metro-babel-transformer",
"version": "0.73.8",
"version": "0.73.9",
"description": "🚇 Base Babel transformer for Metro.",
"main": "src/index.js",
"repository": {
Expand All @@ -19,7 +19,7 @@
"dependencies": {
"@babel/core": "^7.20.0",
"hermes-parser": "0.8.0",
"metro-source-map": "0.73.8",
"metro-source-map": "0.73.9",
"nullthrows": "^1.1.1"
}
}
4 changes: 2 additions & 2 deletions packages/metro-cache-key/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "metro-cache-key",
"version": "0.73.8",
"version": "0.73.9",
"description": "🚇 Cache key utility.",
"main": "src/index.js",
"repository": {
Expand All @@ -13,6 +13,6 @@
},
"license": "MIT",
"devDependencies": {
"metro-memory-fs": "0.73.8"
"metro-memory-fs": "0.73.9"
}
}
6 changes: 3 additions & 3 deletions packages/metro-cache/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "metro-cache",
"version": "0.73.8",
"version": "0.73.9",
"description": "🚇 Cache layers for Metro.",
"main": "src/index.js",
"repository": {
Expand All @@ -12,11 +12,11 @@
"cleanup-release": "test ! -e build && mv src build && mv src.real src"
},
"dependencies": {
"metro-core": "0.73.8",
"metro-core": "0.73.9",
"rimraf": "^3.0.2"
},
"devDependencies": {
"metro-memory-fs": "0.73.8"
"metro-memory-fs": "0.73.9"
},
"license": "MIT"
}
10 changes: 5 additions & 5 deletions packages/metro-config/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "metro-config",
"version": "0.73.8",
"version": "0.73.9",
"description": "🚇 Config parser for Metro.",
"main": "src/index.js",
"repository": {
Expand All @@ -15,10 +15,10 @@
"dependencies": {
"cosmiconfig": "^5.0.5",
"jest-validate": "^26.5.2",
"metro": "0.73.8",
"metro-cache": "0.73.8",
"metro-core": "0.73.8",
"metro-runtime": "0.73.8"
"metro": "0.73.9",
"metro-cache": "0.73.9",
"metro-core": "0.73.9",
"metro-runtime": "0.73.9"
},
"devDependencies": {
"pretty-format": "^26.5.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/metro-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "metro-core",
"version": "0.73.8",
"version": "0.73.9",
"description": "🚇 Metro's core package.",
"main": "src/index.js",
"repository": {
Expand All @@ -13,7 +13,7 @@
},
"dependencies": {
"lodash.throttle": "^4.1.1",
"metro-resolver": "0.73.8"
"metro-resolver": "0.73.9"
},
"license": "MIT"
}
2 changes: 1 addition & 1 deletion packages/metro-file-map/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "metro-file-map",
"version": "0.73.8",
"version": "0.73.9",
"description": "[Experimental] - 🚇 File crawling, watching and mapping for Metro",
"main": "src/index.js",
"repository": {
Expand Down
93 changes: 42 additions & 51 deletions packages/metro-file-map/src/watchers/FSEventsWatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,18 @@
*/

import type {ChangeEventMetadata} from '../flow-types';
import type {Stats} from 'fs';
// $FlowFixMe[cannot-resolve-module] - Optional, Darwin only
import type {FSEvents} from 'fsevents';

// $FlowFixMe[untyped-import] - anymatch
import anymatch from 'anymatch';
import EventEmitter from 'events';
import * as fs from 'graceful-fs';
import {promises as fsPromises} from 'fs';
import * as path from 'path';
// $FlowFixMe[untyped-import] - walker
import walker from 'walker';
import {typeFromStat} from './common';

// $FlowFixMe[untyped-import] - micromatch
const micromatch = require('micromatch');
import {isIncluded, typeFromStat} from './common';

const debug = require('debug')('Metro:FSEventsWatcher');

Expand Down Expand Up @@ -56,7 +54,6 @@ export default class FSEventsWatcher extends EventEmitter {
+ignored: ?Matcher;
+glob: $ReadOnlyArray<string>;
+dot: boolean;
+hasIgnore: boolean;
+doIgnore: (path: string) => boolean;
+fsEventsWatchStopper: () => Promise<void>;
_tracked: Set<string>;
Expand All @@ -66,17 +63,18 @@ export default class FSEventsWatcher extends EventEmitter {
}

static _normalizeProxy(
callback: (normalizedPath: string, stats: fs.Stats) => void,
callback: (normalizedPath: string, stats: Stats) => void,
// $FlowFixMe[cannot-resolve-name]
): (filepath: string, stats: Stats) => void {
return (filepath: string, stats: fs.Stats): void =>
return (filepath: string, stats: Stats): void =>
callback(path.normalize(filepath), stats);
}

static _recReaddir(
dir: string,
dirCallback: (normalizedPath: string, stats: fs.Stats) => void,
fileCallback: (normalizedPath: string, stats: fs.Stats) => void,
dirCallback: (normalizedPath: string, stats: Stats) => void,
fileCallback: (normalizedPath: string, stats: Stats) => void,
symlinkCallback: (normalizedPath: string, stats: Stats) => void,
// $FlowFixMe[unclear-type] Add types for callback
endCallback: Function,
// $FlowFixMe[unclear-type] Add types for callback
Expand All @@ -89,6 +87,7 @@ export default class FSEventsWatcher extends EventEmitter {
)
.on('dir', FSEventsWatcher._normalizeProxy(dirCallback))
.on('file', FSEventsWatcher._normalizeProxy(fileCallback))
.on('symlink', FSEventsWatcher._normalizeProxy(symlinkCallback))
.on('error', errorCallback)
.on('end', () => {
endCallback();
Expand Down Expand Up @@ -116,28 +115,27 @@ export default class FSEventsWatcher extends EventEmitter {
this.dot = opts.dot || false;
this.ignored = opts.ignored;
this.glob = Array.isArray(opts.glob) ? opts.glob : [opts.glob];

this.hasIgnore =
Boolean(opts.ignored) && !(Array.isArray(opts) && opts.length > 0);
this.doIgnore = opts.ignored ? anymatch(opts.ignored) : () => false;

this.root = path.resolve(dir);

this.fsEventsWatchStopper = fsevents.watch(this.root, path =>
this._handleEvent(path),
);
this.fsEventsWatchStopper = fsevents.watch(this.root, path => {
this._handleEvent(path).catch(error => {
this.emit('error', error);
});
});

debug(`Watching ${this.root}`);

this._tracked = new Set();
const trackPath = (filePath: string) => {
this._tracked.add(filePath);
};
FSEventsWatcher._recReaddir(
this.root,
(filepath: string) => {
this._tracked.add(filepath);
},
(filepath: string) => {
this._tracked.add(filepath);
},
trackPath,
trackPath,
trackPath,
// $FlowFixMe[method-unbinding] - Refactor
this.emit.bind(this, 'ready'),
// $FlowFixMe[method-unbinding] - Refactor
Expand All @@ -158,42 +156,22 @@ export default class FSEventsWatcher extends EventEmitter {
}
}

_isFileIncluded(relativePath: string): boolean {
if (this.doIgnore(relativePath)) {
return false;
}
return this.glob.length
? micromatch([relativePath], this.glob, {dot: this.dot}).length > 0
: this.dot || micromatch([relativePath], '**/*').length > 0;
}

_handleEvent(filepath: string) {
async _handleEvent(filepath: string) {
const relativePath = path.relative(this.root, filepath);
if (!this._isFileIncluded(relativePath)) {
return;
}

fs.lstat(filepath, (error, stat) => {
if (error && error.code !== 'ENOENT') {
this.emit('error', error);
return;
}

if (error) {
// Ignore files that aren't tracked and don't exist.
if (!this._tracked.has(filepath)) {
return;
}
try {
const stat = await fsPromises.lstat(filepath);
const type = typeFromStat(stat);

this._emit(DELETE_EVENT, relativePath);
this._tracked.delete(filepath);
// Ignore files of an unrecognized type
if (!type) {
return;
}

const type = typeFromStat(stat);
if (!type) {
if (!isIncluded(type, this.glob, this.dot, this.doIgnore, relativePath)) {
return;
}

const metadata: ChangeEventMetadata = {
type,
modifiedTime: stat.mtime.getTime(),
Expand All @@ -206,7 +184,20 @@ export default class FSEventsWatcher extends EventEmitter {
this._tracked.add(filepath);
this._emit(ADD_EVENT, relativePath, metadata);
}
});
} catch (error) {
if (error?.code !== 'ENOENT') {
this.emit('error', error);
return;
}

// Ignore files that aren't tracked and don't exist.
if (!this._tracked.has(filepath)) {
return;
}

this._emit(DELETE_EVENT, relativePath);
this._tracked.delete(filepath);
}
}

/**
Expand Down
Loading