@opensumi/ide-file-service 3.7.1-next-1736763672.0 → 3.7.1-next-1736771329.0
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.
- package/lib/browser/file-service-client.js +4 -4
- package/lib/browser/file-service-client.js.map +1 -1
- package/lib/browser/file-service-provider-client.d.ts +2 -2
- package/lib/browser/file-service-provider-client.d.ts.map +1 -1
- package/lib/browser/file-service-provider-client.js +2 -2
- package/lib/browser/file-service-provider-client.js.map +1 -1
- package/lib/common/files.d.ts +2 -2
- package/lib/common/files.d.ts.map +1 -1
- package/lib/common/watcher.d.ts +2 -3
- package/lib/common/watcher.d.ts.map +1 -1
- package/lib/common/watcher.js.map +1 -1
- package/lib/node/disk-file-system.provider.d.ts +2 -3
- package/lib/node/disk-file-system.provider.d.ts.map +1 -1
- package/lib/node/disk-file-system.provider.js +2 -3
- package/lib/node/disk-file-system.provider.js.map +1 -1
- package/lib/node/hosted/recursive/file-service-watcher.d.ts +13 -13
- package/lib/node/hosted/recursive/file-service-watcher.d.ts.map +1 -1
- package/lib/node/hosted/recursive/file-service-watcher.js +95 -146
- package/lib/node/hosted/recursive/file-service-watcher.js.map +1 -1
- package/lib/node/hosted/un-recursive/file-service-watcher.d.ts +11 -5
- package/lib/node/hosted/un-recursive/file-service-watcher.d.ts.map +1 -1
- package/lib/node/hosted/un-recursive/file-service-watcher.js +40 -28
- package/lib/node/hosted/un-recursive/file-service-watcher.js.map +1 -1
- package/lib/node/hosted/watcher.host.service.d.ts +2 -7
- package/lib/node/hosted/watcher.host.service.d.ts.map +1 -1
- package/lib/node/hosted/watcher.host.service.js +28 -55
- package/lib/node/hosted/watcher.host.service.js.map +1 -1
- package/lib/node/hosted/watcher.process.js +1 -1
- package/lib/node/hosted/watcher.process.js.map +1 -1
- package/lib/node/watcher-process-manager.d.ts +2 -3
- package/lib/node/watcher-process-manager.d.ts.map +1 -1
- package/lib/node/watcher-process-manager.js +3 -4
- package/lib/node/watcher-process-manager.js.map +1 -1
- package/package.json +9 -9
- package/src/browser/file-service-client.ts +4 -4
- package/src/browser/file-service-provider-client.ts +2 -3
- package/src/common/files.ts +2 -2
- package/src/common/watcher.ts +3 -10
- package/src/node/disk-file-system.provider.ts +3 -8
- package/src/node/hosted/recursive/file-service-watcher.ts +106 -179
- package/src/node/hosted/un-recursive/file-service-watcher.ts +55 -36
- package/src/node/hosted/watcher.host.service.ts +33 -95
- package/src/node/hosted/watcher.process.ts +1 -1
- package/src/node/watcher-process-manager.ts +5 -13
package/src/common/watcher.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { ProxyIdentifier } from '@opensumi/ide-connection/lib/common/rpc/multiplexer';
|
|
2
2
|
import { Event, FileChange, IRelativePattern, URI, UriComponents } from '@opensumi/ide-core-common';
|
|
3
|
-
import {
|
|
4
|
-
DidFilesChangedParams,
|
|
5
|
-
FileSystemWatcherClient,
|
|
6
|
-
RecursiveWatcherBackend,
|
|
7
|
-
} from '@opensumi/ide-core-common/lib/types/file-watch';
|
|
3
|
+
import { DidFilesChangedParams, FileSystemWatcherClient } from '@opensumi/ide-core-common/lib/types/file-watch';
|
|
8
4
|
|
|
9
5
|
import { IFileServiceClient } from './file-service-client';
|
|
10
6
|
|
|
@@ -79,14 +75,11 @@ export const WatcherProcessManagerProxy = new ProxyIdentifier('WatcherProcessMan
|
|
|
79
75
|
export interface IWatcherProcessManager {
|
|
80
76
|
whenReady: Promise<void>;
|
|
81
77
|
|
|
82
|
-
createProcess(clientId: string
|
|
78
|
+
createProcess(clientId: string): Promise<number | undefined>;
|
|
83
79
|
setClient(client: FileSystemWatcherClient): void;
|
|
84
80
|
dispose(): Promise<void>;
|
|
85
81
|
|
|
86
|
-
watch(
|
|
87
|
-
uri: UriComponents,
|
|
88
|
-
options?: { excludes?: string[]; recursive?: boolean; pollingWatch?: boolean },
|
|
89
|
-
): Promise<number>;
|
|
82
|
+
watch(uri: UriComponents, options?: { excludes?: string[]; recursive?: boolean }): Promise<number>;
|
|
90
83
|
unWatch(watcherId: number): Promise<void>;
|
|
91
84
|
setWatcherFileExcludes(excludes: string[]): Promise<void>;
|
|
92
85
|
|
|
@@ -38,7 +38,6 @@ import {
|
|
|
38
38
|
FileType,
|
|
39
39
|
IDiskFileProvider,
|
|
40
40
|
IWatcherProcessManager,
|
|
41
|
-
RecursiveWatcherBackend,
|
|
42
41
|
handleError,
|
|
43
42
|
isErrnoException,
|
|
44
43
|
notEmpty,
|
|
@@ -106,8 +105,8 @@ export class DiskFileSystemProvider extends RPCService<IRPCDiskFileSystemProvide
|
|
|
106
105
|
});
|
|
107
106
|
}
|
|
108
107
|
|
|
109
|
-
async initialize(clientId: string
|
|
110
|
-
await this.watcherProcessManager.createProcess(clientId
|
|
108
|
+
async initialize(clientId: string) {
|
|
109
|
+
await this.watcherProcessManager.createProcess(clientId);
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
get whenReady() {
|
|
@@ -144,17 +143,13 @@ export class DiskFileSystemProvider extends RPCService<IRPCDiskFileSystemProvide
|
|
|
144
143
|
* @param {{ excludes: string[] }}
|
|
145
144
|
* @memberof DiskFileSystemProvider
|
|
146
145
|
*/
|
|
147
|
-
async watch(
|
|
148
|
-
uri: UriComponents,
|
|
149
|
-
options?: { excludes?: string[]; recursive?: boolean; pollingWatch?: boolean },
|
|
150
|
-
): Promise<number> {
|
|
146
|
+
async watch(uri: UriComponents, options?: { excludes?: string[]; recursive?: boolean }): Promise<number> {
|
|
151
147
|
await this.whenReady;
|
|
152
148
|
const _uri = Uri.revive(uri);
|
|
153
149
|
|
|
154
150
|
const id = await this.watcherProcessManager.watch(_uri, {
|
|
155
151
|
excludes: options?.excludes ?? [],
|
|
156
152
|
recursive: options?.recursive ?? this.recursive,
|
|
157
|
-
pollingWatch: options?.pollingWatch,
|
|
158
153
|
});
|
|
159
154
|
|
|
160
155
|
return id;
|
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import paths, { join } from 'path';
|
|
1
|
+
import paths from 'path';
|
|
3
2
|
|
|
4
3
|
import ParcelWatcher from '@parcel/watcher';
|
|
5
4
|
import fs from 'fs-extra';
|
|
6
5
|
import debounce from 'lodash/debounce';
|
|
7
6
|
import uniqBy from 'lodash/uniqBy';
|
|
8
7
|
|
|
9
|
-
import {
|
|
10
|
-
FileChangeType,
|
|
11
|
-
FileSystemWatcherClient,
|
|
12
|
-
IWatcher,
|
|
13
|
-
RecursiveWatcherBackend,
|
|
14
|
-
WatchOptions,
|
|
15
|
-
} from '@opensumi/ide-core-common';
|
|
16
8
|
import { ILogService } from '@opensumi/ide-core-common/lib/log';
|
|
17
9
|
import {
|
|
18
10
|
Disposable,
|
|
@@ -20,13 +12,18 @@ import {
|
|
|
20
12
|
FileUri,
|
|
21
13
|
IDisposable,
|
|
22
14
|
ParsedPattern,
|
|
23
|
-
RunOnceScheduler,
|
|
24
15
|
isLinux,
|
|
25
16
|
isWindows,
|
|
26
17
|
parseGlob,
|
|
27
18
|
} from '@opensumi/ide-core-common/lib/utils';
|
|
28
19
|
|
|
29
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
FileChangeType,
|
|
22
|
+
FileSystemWatcherClient,
|
|
23
|
+
IFileSystemWatcherServer,
|
|
24
|
+
INsfw,
|
|
25
|
+
WatchOptions,
|
|
26
|
+
} from '../../../common';
|
|
30
27
|
import { FileChangeCollection } from '../../file-change-collection';
|
|
31
28
|
import { shouldIgnorePath } from '../shared';
|
|
32
29
|
|
|
@@ -35,6 +32,13 @@ export interface WatcherOptions {
|
|
|
35
32
|
excludes: string[];
|
|
36
33
|
}
|
|
37
34
|
|
|
35
|
+
const watcherPlaceHolder = {
|
|
36
|
+
disposable: {
|
|
37
|
+
dispose: () => {},
|
|
38
|
+
},
|
|
39
|
+
handlers: [],
|
|
40
|
+
};
|
|
41
|
+
|
|
38
42
|
/**
|
|
39
43
|
* @deprecated
|
|
40
44
|
*/
|
|
@@ -44,27 +48,21 @@ export interface NsfwFileSystemWatcherOption {
|
|
|
44
48
|
error?: (message: string, ...args: any[]) => void;
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
export class
|
|
51
|
+
export class FileSystemWatcherServer extends Disposable implements IFileSystemWatcherServer {
|
|
48
52
|
private static readonly PARCEL_WATCHER_BACKEND = isWindows ? 'windows' : isLinux ? 'inotify' : 'fs-events';
|
|
49
53
|
|
|
50
|
-
private static DEFAULT_POLLING_INTERVAL = 100;
|
|
51
|
-
|
|
52
54
|
private WATCHER_HANDLERS = new Map<
|
|
53
|
-
|
|
55
|
+
number,
|
|
54
56
|
{ path: string; handlers: ParcelWatcher.SubscribeCallback[]; disposable: IDisposable }
|
|
55
57
|
>();
|
|
56
|
-
|
|
57
|
-
protected watcherOptions = new Map<
|
|
58
|
+
private static WATCHER_SEQUENCE = 1;
|
|
59
|
+
protected watcherOptions = new Map<number, WatcherOptions>();
|
|
58
60
|
|
|
59
61
|
protected client: FileSystemWatcherClient | undefined;
|
|
60
62
|
|
|
61
63
|
protected changes = new FileChangeCollection();
|
|
62
64
|
|
|
63
|
-
constructor(
|
|
64
|
-
private excludes: string[] = [],
|
|
65
|
-
private readonly logger: ILogService,
|
|
66
|
-
private backend: RecursiveWatcherBackend = RecursiveWatcherBackend.NSFW,
|
|
67
|
-
) {
|
|
65
|
+
constructor(private excludes: string[] = [], private readonly logger: ILogService) {
|
|
68
66
|
super();
|
|
69
67
|
this.addDispose(
|
|
70
68
|
Disposable.create(() => {
|
|
@@ -73,41 +71,37 @@ export class RecursiveFileSystemWatcher extends Disposable implements IWatcher {
|
|
|
73
71
|
);
|
|
74
72
|
}
|
|
75
73
|
|
|
74
|
+
/**
|
|
75
|
+
* 查找某个路径是否已被监听
|
|
76
|
+
* @param watcherPath
|
|
77
|
+
*/
|
|
78
|
+
checkIsAlreadyWatched(watcherPath: string): number | undefined {
|
|
79
|
+
for (const [watcherId, watcher] of this.WATCHER_HANDLERS) {
|
|
80
|
+
if (watcherPath.indexOf(watcher.path) === 0) {
|
|
81
|
+
return watcherId;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
76
86
|
/**
|
|
77
87
|
* 如果监听路径不存在,则会监听父目录
|
|
78
88
|
* @param uri 要监听的路径
|
|
79
89
|
* @param options
|
|
80
90
|
* @returns
|
|
81
91
|
*/
|
|
82
|
-
async watchFileChanges(uri: string, options?: WatchOptions) {
|
|
83
|
-
|
|
84
|
-
const timer = setTimeout(() => {
|
|
85
|
-
rej(`Watch ${uri} Timeout`);
|
|
86
|
-
// FIXME:暂时写死3秒
|
|
87
|
-
}, 3000);
|
|
88
|
-
|
|
89
|
-
if (options?.excludes) {
|
|
90
|
-
this.updateWatcherFileExcludes(options.excludes);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
this.doWatchFileChange(uri, options).then(() => {
|
|
94
|
-
resolve(void 0);
|
|
95
|
-
if (timer) {
|
|
96
|
-
clearTimeout(timer);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
}
|
|
92
|
+
async watchFileChanges(uri: string, options?: WatchOptions): Promise<number> {
|
|
93
|
+
const basePath = FileUri.fsPath(uri);
|
|
101
94
|
|
|
102
|
-
|
|
103
|
-
if (
|
|
104
|
-
|
|
105
|
-
handler?.disposable.dispose();
|
|
106
|
-
this.WATCHER_HANDLERS.delete(uri);
|
|
95
|
+
let watcherId = this.checkIsAlreadyWatched(basePath);
|
|
96
|
+
if (watcherId) {
|
|
97
|
+
return watcherId;
|
|
107
98
|
}
|
|
108
99
|
|
|
109
|
-
|
|
110
|
-
this.
|
|
100
|
+
watcherId = FileSystemWatcherServer.WATCHER_SEQUENCE++;
|
|
101
|
+
this.WATCHER_HANDLERS.set(watcherId, {
|
|
102
|
+
...watcherPlaceHolder,
|
|
103
|
+
path: basePath,
|
|
104
|
+
});
|
|
111
105
|
|
|
112
106
|
const toDisposeWatcher = new DisposableCollection();
|
|
113
107
|
let watchPath: string;
|
|
@@ -123,10 +117,10 @@ export class RecursiveFileSystemWatcher extends Disposable implements IWatcher {
|
|
|
123
117
|
} else {
|
|
124
118
|
watchPath = await this.lookup(basePath);
|
|
125
119
|
}
|
|
126
|
-
|
|
120
|
+
this.logger.log('Starting watching:', watchPath, options);
|
|
127
121
|
const handler = (err, events: ParcelWatcher.Event[]) => {
|
|
128
122
|
if (err) {
|
|
129
|
-
this.logger.error(`
|
|
123
|
+
this.logger.error(`Watching ${watchPath} error: `, err);
|
|
130
124
|
return;
|
|
131
125
|
}
|
|
132
126
|
events = this.trimChangeEvent(events);
|
|
@@ -145,15 +139,15 @@ export class RecursiveFileSystemWatcher extends Disposable implements IWatcher {
|
|
|
145
139
|
}
|
|
146
140
|
};
|
|
147
141
|
|
|
148
|
-
this.WATCHER_HANDLERS.set(
|
|
142
|
+
this.WATCHER_HANDLERS.set(watcherId, {
|
|
149
143
|
path: watchPath,
|
|
150
144
|
disposable: toDisposeWatcher,
|
|
151
145
|
handlers: [handler],
|
|
152
146
|
});
|
|
153
|
-
|
|
154
|
-
toDisposeWatcher.push(
|
|
155
|
-
toDisposeWatcher.push(await this.start(watchPath, options));
|
|
147
|
+
toDisposeWatcher.push(Disposable.create(() => this.WATCHER_HANDLERS.delete(watcherId as number)));
|
|
148
|
+
toDisposeWatcher.push(await this.start(watcherId, watchPath, options));
|
|
156
149
|
this.addDispose(toDisposeWatcher);
|
|
150
|
+
return watcherId;
|
|
157
151
|
}
|
|
158
152
|
|
|
159
153
|
/**
|
|
@@ -190,63 +184,16 @@ export class RecursiveFileSystemWatcher extends Disposable implements IWatcher {
|
|
|
190
184
|
this.excludes = excludes;
|
|
191
185
|
}
|
|
192
186
|
|
|
193
|
-
protected async start(
|
|
194
|
-
|
|
195
|
-
|
|
187
|
+
protected async start(
|
|
188
|
+
watcherId: number,
|
|
189
|
+
basePath: string,
|
|
190
|
+
rawOptions: WatchOptions | undefined,
|
|
191
|
+
): Promise<DisposableCollection> {
|
|
192
|
+
const disposables = new DisposableCollection();
|
|
196
193
|
if (!(await fs.pathExists(basePath))) {
|
|
197
|
-
return
|
|
194
|
+
return disposables;
|
|
198
195
|
}
|
|
199
|
-
|
|
200
196
|
const realPath = await fs.realpath(basePath);
|
|
201
|
-
|
|
202
|
-
if (this.isEnableNSFW()) {
|
|
203
|
-
return this.watchWithNsfw(realPath, rawOptions);
|
|
204
|
-
} else {
|
|
205
|
-
// polling
|
|
206
|
-
if (rawOptions?.pollingWatch) {
|
|
207
|
-
this.logger.log('[Recursive] Start polling watch:', realPath);
|
|
208
|
-
return this.pollingWatch(realPath, rawOptions);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return this.watchWithParcel(realPath, rawOptions);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
private async watchWithNsfw(realPath: string, rawOptions?: WatchOptions | undefined) {
|
|
216
|
-
const disposables = new DisposableCollection();
|
|
217
|
-
const nsfw = await this.withNSFWModule();
|
|
218
|
-
const watcher: INsfw.NSFW = await nsfw(
|
|
219
|
-
realPath,
|
|
220
|
-
(events: INsfw.ChangeEvent[]) => this.handleNSFWEvents(events, realPath),
|
|
221
|
-
{
|
|
222
|
-
errorCallback: (err) => {
|
|
223
|
-
this.logger.error('[Recursive] NSFW watcher encountered an error and will stop watching.', err);
|
|
224
|
-
// see https://github.com/atom/github/issues/342
|
|
225
|
-
this.unwatchFileChanges(realPath);
|
|
226
|
-
},
|
|
227
|
-
},
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
await watcher.start();
|
|
231
|
-
|
|
232
|
-
disposables.push(
|
|
233
|
-
Disposable.create(async () => {
|
|
234
|
-
this.watcherOptions.delete(realPath);
|
|
235
|
-
await watcher.stop();
|
|
236
|
-
}),
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
const excludes = this.excludes.concat(rawOptions?.excludes || []);
|
|
240
|
-
|
|
241
|
-
this.watcherOptions.set(realPath, {
|
|
242
|
-
excludesPattern: excludes.map((pattern) => parseGlob(pattern)),
|
|
243
|
-
excludes,
|
|
244
|
-
});
|
|
245
|
-
return disposables;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
private async watchWithParcel(realPath: string, rawOptions?: WatchOptions | undefined) {
|
|
249
|
-
const disposables = new DisposableCollection();
|
|
250
197
|
const tryWatchDir = async (maxRetries = 3, retryDelay = 1000) => {
|
|
251
198
|
for (let times = 0; times < maxRetries; times++) {
|
|
252
199
|
try {
|
|
@@ -258,30 +205,23 @@ export class RecursiveFileSystemWatcher extends Disposable implements IWatcher {
|
|
|
258
205
|
// FIXME: 研究此处屏蔽的影响,考虑下阈值应该设置多少,或者更加优雅的方式
|
|
259
206
|
return;
|
|
260
207
|
}
|
|
261
|
-
const handlers = this.WATCHER_HANDLERS.get(
|
|
208
|
+
const handlers = this.WATCHER_HANDLERS.get(watcherId)?.handlers;
|
|
262
209
|
|
|
263
210
|
if (!handlers) {
|
|
264
|
-
this.logger.log('[Recursive] No handler found for watcher', realPath);
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
this.logger.log('[Recursive] Received events:', events);
|
|
269
|
-
if (events.length === 0) {
|
|
270
211
|
return;
|
|
271
212
|
}
|
|
272
|
-
|
|
273
213
|
for (const handler of handlers) {
|
|
274
214
|
(handler as ParcelWatcher.SubscribeCallback)(err, events);
|
|
275
215
|
}
|
|
276
216
|
},
|
|
277
217
|
{
|
|
278
|
-
backend:
|
|
218
|
+
backend: FileSystemWatcherServer.PARCEL_WATCHER_BACKEND,
|
|
279
219
|
ignore: this.excludes.concat(rawOptions?.excludes ?? []),
|
|
280
220
|
},
|
|
281
221
|
);
|
|
282
222
|
} catch (e) {
|
|
283
223
|
// Watcher 启动失败,尝试重试
|
|
284
|
-
this.logger.error('
|
|
224
|
+
this.logger.error('watcher subscribe failed ', e, ' try times ', times);
|
|
285
225
|
await new Promise((resolve) => {
|
|
286
226
|
setTimeout(resolve, retryDelay);
|
|
287
227
|
});
|
|
@@ -289,72 +229,61 @@ export class RecursiveFileSystemWatcher extends Disposable implements IWatcher {
|
|
|
289
229
|
}
|
|
290
230
|
|
|
291
231
|
// 经过若干次的尝试后,Parcel Watcher 依然启动失败,此时就不再尝试重试
|
|
292
|
-
this.logger.error(`
|
|
232
|
+
this.logger.error(`watcher subscribe finally failed after ${maxRetries} times`);
|
|
293
233
|
return undefined; // watch 失败则返回 undefined
|
|
294
234
|
};
|
|
295
235
|
|
|
296
|
-
|
|
236
|
+
if (this.isEnableNSFW()) {
|
|
237
|
+
const nsfw = await this.withNSFWModule();
|
|
238
|
+
const watcher: INsfw.NSFW = await nsfw(
|
|
239
|
+
realPath,
|
|
240
|
+
(events: INsfw.ChangeEvent[]) => this.handleNSFWEvents(events, watcherId),
|
|
241
|
+
{
|
|
242
|
+
errorCallback: (err) => {
|
|
243
|
+
this.logger.error('NSFW watcher encountered an error and will stop watching.', err);
|
|
244
|
+
// see https://github.com/atom/github/issues/342
|
|
245
|
+
this.unwatchFileChanges(watcherId);
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
await watcher.start();
|
|
297
251
|
|
|
298
|
-
if (hanlder) {
|
|
299
|
-
// watch 成功才加入 disposables,否则也就无需 dispose
|
|
300
252
|
disposables.push(
|
|
301
253
|
Disposable.create(async () => {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
254
|
+
this.watcherOptions.delete(watcherId);
|
|
255
|
+
await watcher.stop();
|
|
305
256
|
}),
|
|
306
257
|
);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return disposables;
|
|
310
|
-
}
|
|
311
258
|
|
|
312
|
-
|
|
313
|
-
const disposables = new DisposableCollection();
|
|
314
|
-
const snapshotFile = join(tmpdir(), `watcher-snapshot-${realPath}`);
|
|
315
|
-
let counter = 0;
|
|
316
|
-
|
|
317
|
-
const pollingWatcher = new RunOnceScheduler(async () => {
|
|
318
|
-
counter++;
|
|
319
|
-
if (counter > 1) {
|
|
320
|
-
const parcelEvents = await ParcelWatcher.getEventsSince(realPath, snapshotFile, {
|
|
321
|
-
ignore: rawOptions?.excludes,
|
|
322
|
-
backend: RecursiveFileSystemWatcher.PARCEL_WATCHER_BACKEND,
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
const handlers = this.WATCHER_HANDLERS.get(realPath)?.handlers;
|
|
326
|
-
|
|
327
|
-
if (!handlers) {
|
|
328
|
-
this.logger.log('[Recursive] No handler found for watcher', realPath);
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
259
|
+
const excludes = this.excludes.concat(rawOptions?.excludes || []);
|
|
331
260
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
await ParcelWatcher.writeSnapshot(realPath, snapshotFile, {
|
|
339
|
-
ignore: rawOptions?.excludes,
|
|
340
|
-
backend: RecursiveFileSystemWatcher.PARCEL_WATCHER_BACKEND,
|
|
261
|
+
this.watcherOptions.set(watcherId, {
|
|
262
|
+
excludesPattern: excludes.map((pattern) => parseGlob(pattern)),
|
|
263
|
+
excludes,
|
|
341
264
|
});
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
265
|
+
} else {
|
|
266
|
+
const hanlder: ParcelWatcher.AsyncSubscription | undefined = await tryWatchDir();
|
|
267
|
+
|
|
268
|
+
if (hanlder) {
|
|
269
|
+
// watch 成功才加入 disposables,否则也就无需 dispose
|
|
270
|
+
disposables.push(
|
|
271
|
+
Disposable.create(async () => {
|
|
272
|
+
if (hanlder) {
|
|
273
|
+
await hanlder.unsubscribe();
|
|
274
|
+
}
|
|
275
|
+
}),
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
349
279
|
|
|
350
280
|
return disposables;
|
|
351
281
|
}
|
|
352
282
|
|
|
353
|
-
unwatchFileChanges(
|
|
354
|
-
this.
|
|
355
|
-
const watcher = this.WATCHER_HANDLERS.get(uri);
|
|
283
|
+
unwatchFileChanges(watcherId: number): Promise<void> {
|
|
284
|
+
const watcher = this.WATCHER_HANDLERS.get(watcherId);
|
|
356
285
|
if (watcher) {
|
|
357
|
-
this.WATCHER_HANDLERS.delete(
|
|
286
|
+
this.WATCHER_HANDLERS.delete(watcherId);
|
|
358
287
|
watcher.disposable.dispose();
|
|
359
288
|
}
|
|
360
289
|
return Promise.resolve();
|
|
@@ -372,22 +301,20 @@ export class RecursiveFileSystemWatcher extends Disposable implements IWatcher {
|
|
|
372
301
|
* 社区相关 issue: https://github.com/parcel-bundler/watcher/issues/49
|
|
373
302
|
*/
|
|
374
303
|
private isEnableNSFW(): boolean {
|
|
375
|
-
return
|
|
304
|
+
return isLinux;
|
|
376
305
|
}
|
|
377
306
|
|
|
378
|
-
private async handleNSFWEvents(events: INsfw.ChangeEvent[],
|
|
307
|
+
private async handleNSFWEvents(events: INsfw.ChangeEvent[], watcherId: number): Promise<void> {
|
|
379
308
|
if (events.length > 5000) {
|
|
380
309
|
return;
|
|
381
310
|
}
|
|
382
311
|
|
|
383
|
-
const isIgnored = (
|
|
384
|
-
const options = this.watcherOptions.get(
|
|
312
|
+
const isIgnored = (watcherId: number, path: string): boolean => {
|
|
313
|
+
const options = this.watcherOptions.get(watcherId);
|
|
385
314
|
if (!options || !options.excludes || options.excludes.length < 1) {
|
|
386
315
|
return false;
|
|
387
316
|
}
|
|
388
|
-
|
|
389
|
-
const excludesPattern = [...this.excludes.map((pattern) => parseGlob(pattern)), ...options.excludesPattern];
|
|
390
|
-
return excludesPattern.some((match) => match(path));
|
|
317
|
+
return options.excludesPattern.some((match) => match(path));
|
|
391
318
|
};
|
|
392
319
|
|
|
393
320
|
const filterEvents = events.filter((event) => {
|
|
@@ -415,7 +342,7 @@ export class RecursiveFileSystemWatcher extends Disposable implements IWatcher {
|
|
|
415
342
|
case INsfw.actions.RENAMED:
|
|
416
343
|
{
|
|
417
344
|
const deletedPath = await this.resolvePath(event.directory, event.oldFile!);
|
|
418
|
-
if (isIgnored(
|
|
345
|
+
if (isIgnored(watcherId, deletedPath)) {
|
|
419
346
|
return;
|
|
420
347
|
}
|
|
421
348
|
|
|
@@ -423,14 +350,14 @@ export class RecursiveFileSystemWatcher extends Disposable implements IWatcher {
|
|
|
423
350
|
|
|
424
351
|
if (event.newDirectory) {
|
|
425
352
|
const path = await this.resolvePath(event.newDirectory, event.newFile!);
|
|
426
|
-
if (isIgnored(
|
|
353
|
+
if (isIgnored(watcherId, path)) {
|
|
427
354
|
return;
|
|
428
355
|
}
|
|
429
356
|
|
|
430
357
|
this.pushAdded(path);
|
|
431
358
|
} else {
|
|
432
359
|
const path = await this.resolvePath(event.directory, event.newFile!);
|
|
433
|
-
if (isIgnored(
|
|
360
|
+
if (isIgnored(watcherId, path)) {
|
|
434
361
|
return;
|
|
435
362
|
}
|
|
436
363
|
|
|
@@ -441,7 +368,7 @@ export class RecursiveFileSystemWatcher extends Disposable implements IWatcher {
|
|
|
441
368
|
default:
|
|
442
369
|
{
|
|
443
370
|
const path = await this.resolvePath(event.directory, event.file!);
|
|
444
|
-
if (isIgnored(
|
|
371
|
+
if (isIgnored(watcherId, path)) {
|
|
445
372
|
return;
|
|
446
373
|
}
|
|
447
374
|
|