@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.
Files changed (44) hide show
  1. package/lib/browser/file-service-client.js +4 -4
  2. package/lib/browser/file-service-client.js.map +1 -1
  3. package/lib/browser/file-service-provider-client.d.ts +2 -2
  4. package/lib/browser/file-service-provider-client.d.ts.map +1 -1
  5. package/lib/browser/file-service-provider-client.js +2 -2
  6. package/lib/browser/file-service-provider-client.js.map +1 -1
  7. package/lib/common/files.d.ts +2 -2
  8. package/lib/common/files.d.ts.map +1 -1
  9. package/lib/common/watcher.d.ts +2 -3
  10. package/lib/common/watcher.d.ts.map +1 -1
  11. package/lib/common/watcher.js.map +1 -1
  12. package/lib/node/disk-file-system.provider.d.ts +2 -3
  13. package/lib/node/disk-file-system.provider.d.ts.map +1 -1
  14. package/lib/node/disk-file-system.provider.js +2 -3
  15. package/lib/node/disk-file-system.provider.js.map +1 -1
  16. package/lib/node/hosted/recursive/file-service-watcher.d.ts +13 -13
  17. package/lib/node/hosted/recursive/file-service-watcher.d.ts.map +1 -1
  18. package/lib/node/hosted/recursive/file-service-watcher.js +95 -146
  19. package/lib/node/hosted/recursive/file-service-watcher.js.map +1 -1
  20. package/lib/node/hosted/un-recursive/file-service-watcher.d.ts +11 -5
  21. package/lib/node/hosted/un-recursive/file-service-watcher.d.ts.map +1 -1
  22. package/lib/node/hosted/un-recursive/file-service-watcher.js +40 -28
  23. package/lib/node/hosted/un-recursive/file-service-watcher.js.map +1 -1
  24. package/lib/node/hosted/watcher.host.service.d.ts +2 -7
  25. package/lib/node/hosted/watcher.host.service.d.ts.map +1 -1
  26. package/lib/node/hosted/watcher.host.service.js +28 -55
  27. package/lib/node/hosted/watcher.host.service.js.map +1 -1
  28. package/lib/node/hosted/watcher.process.js +1 -1
  29. package/lib/node/hosted/watcher.process.js.map +1 -1
  30. package/lib/node/watcher-process-manager.d.ts +2 -3
  31. package/lib/node/watcher-process-manager.d.ts.map +1 -1
  32. package/lib/node/watcher-process-manager.js +3 -4
  33. package/lib/node/watcher-process-manager.js.map +1 -1
  34. package/package.json +9 -9
  35. package/src/browser/file-service-client.ts +4 -4
  36. package/src/browser/file-service-provider-client.ts +2 -3
  37. package/src/common/files.ts +2 -2
  38. package/src/common/watcher.ts +3 -10
  39. package/src/node/disk-file-system.provider.ts +3 -8
  40. package/src/node/hosted/recursive/file-service-watcher.ts +106 -179
  41. package/src/node/hosted/un-recursive/file-service-watcher.ts +55 -36
  42. package/src/node/hosted/watcher.host.service.ts +33 -95
  43. package/src/node/hosted/watcher.process.ts +1 -1
  44. package/src/node/watcher-process-manager.ts +5 -13
@@ -2,15 +2,24 @@ import fs, { watch } from 'fs-extra';
2
2
  import debounce from 'lodash/debounce';
3
3
 
4
4
  import { ILogService } from '@opensumi/ide-core-common/lib/log';
5
- import { Disposable, DisposableCollection, FileUri, isMacintosh, path } from '@opensumi/ide-utils/lib';
5
+ import { Disposable, DisposableCollection, FileUri, IDisposable, isMacintosh, path } from '@opensumi/ide-utils/lib';
6
6
 
7
- import { FileChangeType, FileSystemWatcherClient, IWatcher } from '../../../common/index';
7
+ import { FileChangeType, FileSystemWatcherClient, IFileSystemWatcherServer } from '../../../common/index';
8
8
  import { FileChangeCollection } from '../../file-change-collection';
9
9
  import { shouldIgnorePath } from '../shared';
10
10
  const { join, basename, normalize } = path;
11
11
 
12
- export class UnRecursiveFileSystemWatcher implements IWatcher {
13
- private watcherCollections: Map<string, fs.FSWatcher> = new Map();
12
+ export class UnRecursiveFileSystemWatcher implements IFileSystemWatcherServer {
13
+ private WATCHER_HANDLERS = new Map<
14
+ number,
15
+ {
16
+ path: string;
17
+ handlers: any;
18
+ disposable: IDisposable;
19
+ }
20
+ >();
21
+
22
+ private static WATCHER_SEQUENCE = 1;
14
23
 
15
24
  private static readonly FILE_DELETE_HANDLER_DELAY = 500;
16
25
 
@@ -25,25 +34,34 @@ export class UnRecursiveFileSystemWatcher implements IWatcher {
25
34
 
26
35
  dispose(): void {
27
36
  this.toDispose.dispose();
37
+ this.WATCHER_HANDLERS.clear();
38
+ }
39
+
40
+ /**
41
+ * 查找某个路径是否已被监听
42
+ * @param watcherPath
43
+ */
44
+ checkIsAlreadyWatched(watcherPath: string): number | undefined {
45
+ for (const [watcherId, watcher] of this.WATCHER_HANDLERS) {
46
+ if (watcherPath.indexOf(watcher.path) === 0) {
47
+ return watcherId;
48
+ }
49
+ }
28
50
  }
29
51
 
30
52
  private async doWatch(basePath: string) {
31
53
  try {
32
54
  const watcher = watch(basePath);
33
- this.watcherCollections.set(basePath, watcher);
34
-
35
- this.logger.log('[Un-Recursive] start watching', basePath);
36
- const isDirectory = (await fs.lstat(basePath)).isDirectory();
55
+ this.logger.log('start watching', basePath);
56
+ const isDirectory = fs.lstatSync(basePath).isDirectory();
37
57
 
38
58
  const docChildren = new Set<string>();
39
59
  let signalDoc = '';
40
60
  if (isDirectory) {
41
61
  try {
42
- const children = await fs.readdir(basePath);
43
- for (const child of children) {
62
+ for (const child of fs.readdirSync(basePath)) {
44
63
  const base = join(basePath, String(child));
45
- const childStat = await fs.lstat(base);
46
- if (!childStat.isDirectory()) {
64
+ if (!fs.lstatSync(base).isDirectory()) {
47
65
  docChildren.add(child);
48
66
  }
49
67
  }
@@ -56,13 +74,11 @@ export class UnRecursiveFileSystemWatcher implements IWatcher {
56
74
 
57
75
  // 开始走监听流程
58
76
  watcher.on('error', (code: number, signal: string) => {
59
- this.logger.error(
60
- `[Un-Recursive] Failed to watch ${basePath} for changes using fs.watch() (${code}, ${signal})`,
61
- );
77
+ this.logger.error(`Failed to watch ${basePath} for changes using fs.watch() (${code}, ${signal})`);
62
78
  watcher.close();
63
79
  });
64
80
 
65
- watcher.on('change', async (type: string, filename: string | Buffer) => {
81
+ watcher.on('change', (type: string, filename: string | Buffer) => {
66
82
  if (shouldIgnorePath(filename as string)) {
67
83
  return;
68
84
  }
@@ -80,22 +96,21 @@ export class UnRecursiveFileSystemWatcher implements IWatcher {
80
96
  }
81
97
 
82
98
  const changePath = join(basePath, changeFileName);
83
- const pathExist = await fs.pathExists(changePath);
84
99
  if (isDirectory) {
85
100
  setTimeout(async () => {
86
101
  // 监听的目录如果是文件夹,那么只对其下面的文件改动做出响应
87
102
  if (docChildren.has(changeFileName)) {
88
103
  if ((type === 'rename' || type === 'change') && changeFileName === filename) {
89
- if (pathExist) {
104
+ const fileExists = fs.existsSync(changePath);
105
+ if (fileExists) {
90
106
  this.pushUpdated(changePath);
91
107
  } else {
92
108
  docChildren.delete(changeFileName);
93
109
  this.pushDeleted(changePath);
94
110
  }
95
111
  }
96
- } else if (pathExist) {
97
- const fileStat = await fs.lstat(changePath);
98
- if (!fileStat.isDirectory()) {
112
+ } else if (fs.pathExistsSync(changePath)) {
113
+ if (!fs.lstatSync(changePath).isDirectory()) {
99
114
  this.pushAdded(changePath);
100
115
  docChildren.add(changeFileName);
101
116
  }
@@ -104,7 +119,7 @@ export class UnRecursiveFileSystemWatcher implements IWatcher {
104
119
  } else {
105
120
  setTimeout(async () => {
106
121
  if (changeFileName === signalDoc) {
107
- if (pathExist) {
122
+ if (fs.pathExistsSync(basePath)) {
108
123
  this.pushUpdated(basePath);
109
124
  } else {
110
125
  this.pushDeleted(basePath);
@@ -115,7 +130,7 @@ export class UnRecursiveFileSystemWatcher implements IWatcher {
115
130
  }
116
131
  });
117
132
  } catch (error) {
118
- this.logger.error(`[Un-Recursive] Failed to watch ${basePath} for change using fs.watch() (${error.toString()})`);
133
+ this.logger.error(`Failed to watch ${basePath} for change using fs.watch() (${error.toString()})`);
119
134
  }
120
135
  }
121
136
 
@@ -123,20 +138,29 @@ export class UnRecursiveFileSystemWatcher implements IWatcher {
123
138
  const basePath = FileUri.fsPath(uri);
124
139
  const exist = await fs.pathExists(basePath);
125
140
 
141
+ let watcherId = this.checkIsAlreadyWatched(basePath);
142
+
143
+ if (watcherId) {
144
+ return watcherId;
145
+ }
146
+
147
+ watcherId = UnRecursiveFileSystemWatcher.WATCHER_SEQUENCE++;
148
+
126
149
  const disposables = new DisposableCollection(); // 管理可释放的资源
127
150
 
128
151
  let watchPath = '';
129
152
 
130
153
  if (exist) {
131
- const stat = await fs.lstat(basePath);
154
+ const stat = await fs.lstatSync(basePath);
132
155
  if (stat) {
133
156
  watchPath = basePath;
134
157
  }
135
158
  } else {
136
- this.logger.warn('[Un-Recursive] This path does not exist. Please try again');
159
+ this.logger.warn('This path does not exist. Please try again');
137
160
  }
138
161
  disposables.push(await this.start(watchPath));
139
162
  this.toDispose.push(disposables);
163
+ return watcherId;
140
164
  }
141
165
 
142
166
  protected async start(basePath: string): Promise<DisposableCollection> {
@@ -146,10 +170,6 @@ export class UnRecursiveFileSystemWatcher implements IWatcher {
146
170
  }
147
171
 
148
172
  const realPath = await fs.realpath(basePath);
149
- if (this.watcherCollections.has(realPath)) {
150
- return disposables;
151
- }
152
-
153
173
  const tryWatchDir = async (retryDelay = 1000) => {
154
174
  try {
155
175
  this.doWatch(realPath);
@@ -163,14 +183,13 @@ export class UnRecursiveFileSystemWatcher implements IWatcher {
163
183
  await tryWatchDir();
164
184
  return disposables;
165
185
  }
166
-
167
- async unwatchFileChanges(uri: string): Promise<void> {
168
- const basePath = FileUri.fsPath(uri);
169
- if (this.watcherCollections.has(basePath)) {
170
- const watcher = this.watcherCollections.get(basePath);
171
- watcher?.close();
172
- this.watcherCollections.delete(basePath);
186
+ unwatchFileChanges(watcherId: number): Promise<void> {
187
+ const watcher = this.WATCHER_HANDLERS.get(watcherId);
188
+ if (watcher) {
189
+ this.WATCHER_HANDLERS.delete(watcherId);
190
+ watcher.disposable.dispose();
173
191
  }
192
+ return Promise.resolve();
174
193
  }
175
194
 
176
195
  protected pushAdded(path: string): void {
@@ -1,45 +1,20 @@
1
1
  import { SumiConnectionMultiplexer } from '@opensumi/ide-connection';
2
- import {
3
- DidFilesChangedParams,
4
- Disposable,
5
- DisposableCollection,
6
- FileUri,
7
- IDisposable,
8
- RecursiveWatcherBackend,
9
- } from '@opensumi/ide-core-common';
2
+ import { DidFilesChangedParams } from '@opensumi/ide-core-common';
10
3
  import { defaultFilesWatcherExcludes, flattenExcludes } from '@opensumi/ide-core-common/lib/preferences/file-watch';
11
4
  import { URI, Uri, UriComponents } from '@opensumi/ide-utils/lib/uri';
12
5
 
13
6
  import { IWatcherHostService, WatcherProcessManagerProxy, WatcherServiceProxy } from '../../common/watcher';
14
7
  import { IWatcher } from '../disk-file-system.provider';
15
8
 
16
- import { RecursiveFileSystemWatcher } from './recursive/file-service-watcher';
9
+ import { FileSystemWatcherServer } from './recursive/file-service-watcher';
17
10
  import { UnRecursiveFileSystemWatcher } from './un-recursive/file-service-watcher';
18
11
  import { WatcherProcessLogger } from './watch-process-log';
19
12
 
20
- const watcherPlaceHolder = {
21
- disposable: {
22
- dispose: () => { },
23
- },
24
- handlers: [],
25
- };
26
-
27
13
  export class WatcherHostServiceImpl implements IWatcherHostService {
28
- private static WATCHER_SEQUENCE = 1;
29
-
30
- private WATCHER_HANDLERS = new Map<
31
- number,
32
- {
33
- path: string;
34
- handlers: any;
35
- disposable: IDisposable;
36
- }
37
- >();
38
-
39
14
  /**
40
15
  * recursive file system watcher
41
16
  */
42
- private recursiveFileSystemWatcher?: RecursiveFileSystemWatcher;
17
+ private recursiveFileSystemWatcher?: FileSystemWatcherServer;
43
18
 
44
19
  /**
45
20
  * unrecursive file system watcher
@@ -52,11 +27,7 @@ export class WatcherHostServiceImpl implements IWatcherHostService {
52
27
 
53
28
  private watchedDirs: Set<string> = new Set();
54
29
 
55
- constructor(
56
- private rpcProtocol: SumiConnectionMultiplexer,
57
- private logger: WatcherProcessLogger,
58
- private backend: RecursiveWatcherBackend,
59
- ) {
30
+ constructor(private rpcProtocol: SumiConnectionMultiplexer, private logger: WatcherProcessLogger) {
60
31
  this.rpcProtocol.set(WatcherServiceProxy, this);
61
32
  this.defaultExcludes = flattenExcludes(defaultFilesWatcherExcludes);
62
33
  this.initWatcherServer(this.defaultExcludes);
@@ -77,18 +48,18 @@ export class WatcherHostServiceImpl implements IWatcherHostService {
77
48
 
78
49
  // rewatch
79
50
  for (const [_uri, { options, disposable }] of this.watcherCollection) {
51
+ this.doWatch(Uri.parse(_uri), options);
80
52
  this.logger.log('rewatch file changes: ', _uri, ' recursive: ', options?.recursive);
81
53
  disposable.dispose();
82
- this.doWatch(Uri.parse(_uri), options);
83
54
  }
84
55
  }
85
56
 
86
- this.recursiveFileSystemWatcher = new RecursiveFileSystemWatcher(excludes, this.logger, this.backend);
57
+ this.recursiveFileSystemWatcher = new FileSystemWatcherServer(excludes, this.logger);
87
58
  this.unrecursiveFileSystemWatcher = new UnRecursiveFileSystemWatcher(this.logger);
88
59
 
89
60
  const watcherClient = {
90
61
  onDidFilesChanged: (events: DidFilesChangedParams) => {
91
- this.logger.log('onDidFilesChanged: ', events);
62
+ this.logger.log('watcher server onDidFilesChanged: ', events);
92
63
  const proxy = this.rpcProtocol.getProxy(WatcherProcessManagerProxy);
93
64
  proxy.$onDidFilesChanged(events);
94
65
  },
@@ -98,80 +69,47 @@ export class WatcherHostServiceImpl implements IWatcherHostService {
98
69
  this.unrecursiveFileSystemWatcher.setClient(watcherClient);
99
70
  }
100
71
 
101
- checkIsAlreadyWatched(watcherPath: string): number | undefined {
102
- for (const [watcherId, watcher] of this.WATCHER_HANDLERS) {
103
- if (watcherPath === watcher.path) {
104
- return watcherId;
105
- }
106
- }
107
- }
108
-
109
- private async doWatch(
110
- uri: Uri,
111
- options?: { excludes?: string[]; recursive?: boolean; pollingWatch?: boolean },
112
- ): Promise<number> {
72
+ private getWatcherServer(recursive?: boolean) {
73
+ const useRecursiveServer = recursive;
74
+ let watcherServer: FileSystemWatcherServer | UnRecursiveFileSystemWatcher;
113
75
  this.initWatcherServer();
114
- const basePath = FileUri.fsPath(uri.toString());
115
- let watcherId = this.checkIsAlreadyWatched(basePath);
116
76
 
117
- if (watcherId) {
118
- this.logger.log(uri.toString(), 'is already watched');
119
- return watcherId;
77
+ if (useRecursiveServer) {
78
+ watcherServer = this.recursiveFileSystemWatcher!;
79
+ } else {
80
+ watcherServer = this.unrecursiveFileSystemWatcher!;
120
81
  }
121
82
 
122
- watcherId = WatcherHostServiceImpl.WATCHER_SEQUENCE++;
83
+ return watcherServer;
84
+ }
123
85
 
124
- this.WATCHER_HANDLERS.set(watcherId, {
125
- ...watcherPlaceHolder,
126
- path: basePath,
127
- });
86
+ private async doWatch(uri: Uri, options?: { excludes?: string[]; recursive?: boolean }): Promise<number> {
87
+ const watcherServer = this.getWatcherServer(options?.recursive);
88
+ if (!watcherServer) {
89
+ return -1;
90
+ }
128
91
 
129
92
  this.logger.log('watch file changes: ', uri.toString(), ' recursive: ', options?.recursive);
130
93
 
131
94
  const mergedExcludes = new Set([...(options?.excludes ?? []), ...this.defaultExcludes]);
95
+ const id = await watcherServer.watchFileChanges(uri.toString(), {
96
+ excludes: Array.from(mergedExcludes),
97
+ });
132
98
 
133
- const disposables = new DisposableCollection();
134
-
135
- await this.unrecursiveFileSystemWatcher!.watchFileChanges(uri.toString());
99
+ this.watchedDirs.add(uri.toString());
136
100
 
137
- disposables.push(
138
- Disposable.create(() => {
139
- this.unrecursiveFileSystemWatcher!.unwatchFileChanges(uri.toString());
101
+ const disposable = {
102
+ dispose: () => {
103
+ watcherServer.unwatchFileChanges(id);
140
104
  this.watchedDirs.delete(uri.toString());
141
- }),
142
- );
143
-
144
- if (options?.recursive) {
145
- this.logger.log('use recursive watcher for: ', uri.toString());
146
- try {
147
- await this.recursiveFileSystemWatcher!.watchFileChanges(uri.toString(), {
148
- excludes: Array.from(mergedExcludes),
149
- pollingWatch: options?.pollingWatch,
150
- });
151
-
152
- disposables.push(
153
- Disposable.create(() => {
154
- this.recursiveFileSystemWatcher!.unwatchFileChanges(uri.toString());
155
- this.watchedDirs.delete(uri.toString());
156
- }),
157
- );
158
- } catch (error) {
159
- // watch error or timeout
160
- this.logger.error('watch error: ', error);
161
- }
162
- }
163
-
164
- this.watcherCollection.set(uri.toString(), { id: watcherId, options, disposable: disposables });
165
-
166
- this.watchedDirs.add(uri.toString());
105
+ },
106
+ };
167
107
 
168
- return watcherId;
108
+ this.watcherCollection.set(uri.toString(), { id, options, disposable });
109
+ return id;
169
110
  }
170
111
 
171
- async $watch(
172
- uri: UriComponents,
173
- options?: { excludes?: string[]; recursive?: boolean; pollingWatch?: boolean },
174
- ): Promise<number> {
112
+ async $watch(uri: UriComponents, options?: { excludes?: string[]; recursive?: boolean }): Promise<number> {
175
113
  const _uri = URI.revive(uri);
176
114
  return this.doWatch(_uri, options);
177
115
  }
@@ -37,7 +37,7 @@ async function initWatcherProcess() {
37
37
  });
38
38
 
39
39
  const logger = new WatcherProcessLogger(watcherInjector, initData.logDir, initData.logLevel);
40
- const watcherHostService = new WatcherHostServiceImpl(watcherProtocol, logger, initData.backend);
40
+ const watcherHostService = new WatcherHostServiceImpl(watcherProtocol, logger);
41
41
  watcherHostService.initWatcherServer();
42
42
  }
43
43
 
@@ -7,11 +7,7 @@ import { IRPCProtocol } from '@opensumi/ide-connection';
7
7
  import { NetSocketConnection } from '@opensumi/ide-connection/lib/common/connection/drivers/socket';
8
8
  import { SumiConnectionMultiplexer } from '@opensumi/ide-connection/lib/common/rpc/multiplexer';
9
9
  import { ILogServiceManager, SupportLogNamespace } from '@opensumi/ide-core-common/lib/log';
10
- import {
11
- DidFilesChangedParams,
12
- FileSystemWatcherClient,
13
- RecursiveWatcherBackend,
14
- } from '@opensumi/ide-core-common/lib/types/file-watch';
10
+ import { DidFilesChangedParams, FileSystemWatcherClient } from '@opensumi/ide-core-common/lib/types/file-watch';
15
11
  import { normalizedIpcHandlerPathAsync } from '@opensumi/ide-core-common/lib/utils/ipc';
16
12
  import { AppConfig, Deferred, ILogService, UriComponents } from '@opensumi/ide-core-node';
17
13
  import { process as processUtil } from '@opensumi/ide-utils';
@@ -114,7 +110,7 @@ export class WatcherProcessManagerImpl implements IWatcherProcessManager {
114
110
  );
115
111
  }
116
112
 
117
- private async createWatcherProcess(clientId: string, ipcHandlerPath: string, backend?: RecursiveWatcherBackend) {
113
+ private async createWatcherProcess(clientId: string, ipcHandlerPath: string) {
118
114
  const forkArgs = [
119
115
  `--${SUMI_WATCHER_PROCESS_SOCK_KEY}=${JSON.stringify({
120
116
  path: ipcHandlerPath,
@@ -122,7 +118,6 @@ export class WatcherProcessManagerImpl implements IWatcherProcessManager {
122
118
  `--${WATCHER_INIT_DATA_KEY}=${JSON.stringify({
123
119
  logDir: this.appConfig.logDir,
124
120
  logLevel: this.appConfig.logLevel,
125
- backend,
126
121
  clientId,
127
122
  })}`,
128
123
  ];
@@ -141,14 +136,14 @@ export class WatcherProcessManagerImpl implements IWatcherProcessManager {
141
136
  return this.watcherProcess.pid;
142
137
  }
143
138
 
144
- async createProcess(clientId: string, backend?: RecursiveWatcherBackend) {
139
+ async createProcess(clientId: string) {
145
140
  this.logger.log('create watcher process for client: ', clientId);
146
141
  this.logger.log('appconfig watcherHost: ', this.watcherHost);
147
142
 
148
143
  const ipcHandlerPath = await this.getIPCHandlerPath('watcher_process');
149
144
  await this.createWatcherServer(clientId, ipcHandlerPath);
150
145
 
151
- const pid = await this.createWatcherProcess(clientId, ipcHandlerPath, backend);
146
+ const pid = await this.createWatcherProcess(clientId, ipcHandlerPath);
152
147
 
153
148
  return pid;
154
149
  }
@@ -163,10 +158,7 @@ export class WatcherProcessManagerImpl implements IWatcherProcessManager {
163
158
  }
164
159
  }
165
160
 
166
- async watch(
167
- uri: UriComponents,
168
- options?: { excludes?: string[]; recursive?: boolean; pollingWatch: boolean },
169
- ): Promise<number> {
161
+ async watch(uri: UriComponents, options?: { excludes?: string[]; recursive?: boolean }): Promise<number> {
170
162
  this.logger.log('Wait for watcher process ready...');
171
163
  await this._whenReadyDeferred.promise;
172
164
  this.logger.log('start watch: ', uri);