Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/services/files/electron-browser/diskFileSystemProvider.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { localize } from '../../../../nls.js';
7
import { Event } from '../../../../base/common/event.js';
8
import { isLinux } from '../../../../base/common/platform.js';
9
import { FileSystemProviderCapabilities, IFileDeleteOptions, IStat, FileType, IFileReadStreamOptions, IFileWriteOptions, IFileOpenOptions, IFileOverwriteOptions, IFileSystemProviderWithFileReadWriteCapability, IFileSystemProviderWithOpenReadWriteCloseCapability, IFileSystemProviderWithFileReadStreamCapability, IFileSystemProviderWithFileFolderCopyCapability, IFileSystemProviderWithFileAtomicReadCapability, IFileAtomicReadOptions, IFileSystemProviderWithFileCloneCapability, IFileChange } from '../../../../platform/files/common/files.js';
10
import { AbstractDiskFileSystemProvider } from '../../../../platform/files/common/diskFileSystemProvider.js';
11
import { IMainProcessService } from '../../../../platform/ipc/common/mainProcessService.js';
12
import { CancellationToken } from '../../../../base/common/cancellation.js';
13
import { ReadableStreamEvents } from '../../../../base/common/stream.js';
14
import { URI } from '../../../../base/common/uri.js';
15
import { DiskFileSystemProviderClient, LOCAL_FILE_SYSTEM_CHANNEL_NAME } from '../../../../platform/files/common/diskFileSystemProviderClient.js';
16
import { ILogMessage, AbstractUniversalWatcherClient } from '../../../../platform/files/common/watcher.js';
17
import { UniversalWatcherClient } from './watcherClient.js';
18
import { ILoggerService, ILogService } from '../../../../platform/log/common/log.js';
19
import { IUtilityProcessWorkerWorkbenchService } from '../../utilityProcess/electron-browser/utilityProcessWorkerWorkbenchService.js';
20
import { LogService } from '../../../../platform/log/common/logService.js';
21
22
/**
23
* A sandbox ready disk file system provider that delegates almost all calls
24
* to the main process via `DiskFileSystemProviderServer` except for recursive
25
* file watching that is done via shared process workers due to CPU intensity.
26
*/
27
export class DiskFileSystemProvider extends AbstractDiskFileSystemProvider implements
28
IFileSystemProviderWithFileReadWriteCapability,
29
IFileSystemProviderWithOpenReadWriteCloseCapability,
30
IFileSystemProviderWithFileReadStreamCapability,
31
IFileSystemProviderWithFileFolderCopyCapability,
32
IFileSystemProviderWithFileAtomicReadCapability,
33
IFileSystemProviderWithFileCloneCapability {
34
35
private readonly provider: DiskFileSystemProviderClient;
36
37
constructor(
38
mainProcessService: IMainProcessService,
39
private readonly utilityProcessWorkerWorkbenchService: IUtilityProcessWorkerWorkbenchService,
40
logService: ILogService,
41
private readonly loggerService: ILoggerService
42
) {
43
super(logService, { watcher: { forceUniversal: true /* send all requests to universal watcher process */ } });
44
45
this.provider = this._register(new DiskFileSystemProviderClient(mainProcessService.getChannel(LOCAL_FILE_SYSTEM_CHANNEL_NAME), { pathCaseSensitive: isLinux, trash: true }));
46
47
this.registerListeners();
48
}
49
50
private registerListeners(): void {
51
52
// Forward events from the embedded provider
53
this._register(this.provider.onDidChangeFile(changes => this._onDidChangeFile.fire(changes)));
54
this._register(this.provider.onDidWatchError(error => this._onDidWatchError.fire(error)));
55
}
56
57
//#region File Capabilities
58
59
get onDidChangeCapabilities(): Event<void> { return this.provider.onDidChangeCapabilities; }
60
61
get capabilities(): FileSystemProviderCapabilities { return this.provider.capabilities; }
62
63
//#endregion
64
65
//#region File Metadata Resolving
66
67
stat(resource: URI): Promise<IStat> {
68
return this.provider.stat(resource);
69
}
70
71
realpath(resource: URI): Promise<string> {
72
return this.provider.realpath(resource);
73
}
74
75
readdir(resource: URI): Promise<[string, FileType][]> {
76
return this.provider.readdir(resource);
77
}
78
79
//#endregion
80
81
//#region File Reading/Writing
82
83
readFile(resource: URI, opts?: IFileAtomicReadOptions): Promise<Uint8Array> {
84
return this.provider.readFile(resource, opts);
85
}
86
87
readFileStream(resource: URI, opts: IFileReadStreamOptions, token: CancellationToken): ReadableStreamEvents<Uint8Array> {
88
return this.provider.readFileStream(resource, opts, token);
89
}
90
91
writeFile(resource: URI, content: Uint8Array, opts: IFileWriteOptions): Promise<void> {
92
return this.provider.writeFile(resource, content, opts);
93
}
94
95
open(resource: URI, opts: IFileOpenOptions): Promise<number> {
96
return this.provider.open(resource, opts);
97
}
98
99
close(fd: number): Promise<void> {
100
return this.provider.close(fd);
101
}
102
103
read(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number> {
104
return this.provider.read(fd, pos, data, offset, length);
105
}
106
107
write(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number> {
108
return this.provider.write(fd, pos, data, offset, length);
109
}
110
111
//#endregion
112
113
//#region Move/Copy/Delete/Create Folder
114
115
mkdir(resource: URI): Promise<void> {
116
return this.provider.mkdir(resource);
117
}
118
119
delete(resource: URI, opts: IFileDeleteOptions): Promise<void> {
120
return this.provider.delete(resource, opts);
121
}
122
123
rename(from: URI, to: URI, opts: IFileOverwriteOptions): Promise<void> {
124
return this.provider.rename(from, to, opts);
125
}
126
127
copy(from: URI, to: URI, opts: IFileOverwriteOptions): Promise<void> {
128
return this.provider.copy(from, to, opts);
129
}
130
131
//#endregion
132
133
//#region Clone File
134
135
cloneFile(from: URI, to: URI): Promise<void> {
136
return this.provider.cloneFile(from, to);
137
}
138
139
//#endregion
140
141
//#region File Watching
142
143
protected createUniversalWatcher(
144
onChange: (changes: IFileChange[]) => void,
145
onLogMessage: (msg: ILogMessage) => void,
146
verboseLogging: boolean
147
): AbstractUniversalWatcherClient {
148
return new UniversalWatcherClient(changes => onChange(changes), msg => onLogMessage(msg), verboseLogging, this.utilityProcessWorkerWorkbenchService);
149
}
150
151
protected createNonRecursiveWatcher(): never {
152
throw new Error('Method not implemented in sandbox.'); // we never expect this to be called given we set `forceUniversal: true`
153
}
154
155
private _watcherLogService: ILogService | undefined = undefined;
156
private get watcherLogService(): ILogService {
157
if (!this._watcherLogService) {
158
this._watcherLogService = new LogService(this.loggerService.createLogger('fileWatcher', { name: localize('fileWatcher', "File Watcher") }));
159
}
160
161
return this._watcherLogService;
162
}
163
164
protected override logWatcherMessage(msg: ILogMessage): void {
165
this.watcherLogService[msg.type](msg.message);
166
167
if (msg.type !== 'trace' && msg.type !== 'debug') {
168
super.logWatcherMessage(msg); // allow non-verbose log messages in window log
169
}
170
}
171
172
//#endregion
173
}
174
175