@codingame/monaco-vscode-files-service-override 4.0.0 → 4.1.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/files.js +5 -4
- package/index.js +1 -1
- package/package.json +2 -2
- package/override/vs/platform/dialogs/common/dialogs.js +0 -10
- package/vscode/src/vs/platform/files/browser/indexedDBFileSystemProvider.js +0 -406
- package/vscode/src/vs/platform/files/common/fileService.js +0 -988
- package/vscode/src/vs/platform/files/common/io.js +0 -77
- package/vscode/src/vs/workbench/services/textfile/browser/browserTextFileService.js +0 -59
- package/vscode/src/vs/workbench/services/textfile/browser/textFileService.js +0 -654
- package/vscode/src/vs/workbench/services/textfile/common/textFileEditorModelManager.js +0 -404
- package/vscode/src/vs/workbench/services/textfile/common/textFileSaveParticipant.js +0 -64
package/files.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __decorate, __param } from './external/tslib/tslib.es6.js';
|
|
2
2
|
import { SyncDescriptor } from 'vscode/vscode/vs/platform/instantiation/common/descriptors';
|
|
3
|
-
import { FileService } from '
|
|
3
|
+
import { FileService } from 'vscode/vscode/vs/platform/files/common/fileService';
|
|
4
4
|
import { ILogService } from 'vscode/vscode/vs/platform/log/common/log';
|
|
5
5
|
import { InMemoryFileSystemProvider } from 'vscode/vscode/vs/platform/files/common/inMemoryFilesystemProvider';
|
|
6
6
|
export { InMemoryFileSystemProvider } from 'vscode/vscode/vs/platform/files/common/inMemoryFilesystemProvider';
|
|
@@ -12,14 +12,15 @@ import { extUri, joinPath } from 'vscode/vscode/vs/base/common/resources';
|
|
|
12
12
|
import { Emitter, Event } from 'vscode/vscode/vs/base/common/event';
|
|
13
13
|
export { HTMLFileSystemProvider } from 'vscode/vscode/vs/platform/files/browser/htmlFileSystemProvider';
|
|
14
14
|
import { Schemas } from 'vscode/vscode/vs/base/common/network';
|
|
15
|
-
import { IndexedDBFileSystemProvider } from '
|
|
15
|
+
import { IndexedDBFileSystemProvider } from 'vscode/vscode/vs/platform/files/browser/indexedDBFileSystemProvider';
|
|
16
|
+
export { IndexedDBFileSystemProvider } from 'vscode/vscode/vs/platform/files/browser/indexedDBFileSystemProvider';
|
|
16
17
|
import { IndexedDB } from 'vscode/vscode/vs/base/browser/indexedDB';
|
|
17
18
|
export { IndexedDB } from 'vscode/vscode/vs/base/browser/indexedDB';
|
|
18
19
|
import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry';
|
|
19
20
|
import { BufferLogger } from 'vscode/vscode/vs/platform/log/common/bufferLog';
|
|
20
21
|
import { localizeWithPath } from 'vscode/vscode/vs/nls';
|
|
21
22
|
import { ITextFileService } from 'vscode/vscode/vs/workbench/services/textfile/common/textfiles';
|
|
22
|
-
import { BrowserTextFileService } from '
|
|
23
|
+
import { BrowserTextFileService } from 'vscode/vscode/vs/workbench/services/textfile/browser/browserTextFileService';
|
|
23
24
|
import { IFilesConfigurationService, FilesConfigurationService } from 'vscode/vscode/vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
|
24
25
|
import { BrowserElevatedFileService } from './vscode/src/vs/workbench/services/files/browser/elevatedFileService.js';
|
|
25
26
|
import { IElevatedFileService } from 'vscode/vscode/vs/workbench/services/files/common/elevatedFileService';
|
|
@@ -525,4 +526,4 @@ function registerFileSystemOverlay(priority, provider) {
|
|
|
525
526
|
return fileSystemProvider.register(priority, provider);
|
|
526
527
|
}
|
|
527
528
|
|
|
528
|
-
export { CustomSchemas, DelegateFileSystemProvider,
|
|
529
|
+
export { CustomSchemas, DelegateFileSystemProvider, RegisteredFile, RegisteredFileSystemProvider, RegisteredMemoryFile, RegisteredReadOnlyFile, createIndexedDBProviders, getServiceOverride as default, initFile, registerCustomProvider, registerExtensionFile, registerFileSystemOverlay };
|
package/index.js
CHANGED
|
@@ -3,4 +3,4 @@ export { FileChangeType, FilePermission, FileSystemProviderCapabilities, FileSys
|
|
|
3
3
|
export { HTMLFileSystemProvider } from 'vscode/vscode/vs/platform/files/browser/htmlFileSystemProvider';
|
|
4
4
|
export { InMemoryFileSystemProvider } from 'vscode/vscode/vs/platform/files/common/inMemoryFilesystemProvider';
|
|
5
5
|
export { IndexedDB } from 'vscode/vscode/vs/base/browser/indexedDB';
|
|
6
|
-
export { IndexedDBFileSystemProvider } from '
|
|
6
|
+
export { IndexedDBFileSystemProvider } from 'vscode/vscode/vs/platform/files/browser/indexedDBFileSystemProvider';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codingame/monaco-vscode-files-service-override",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"keywords": [],
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "CodinGame",
|
|
@@ -18,6 +18,6 @@
|
|
|
18
18
|
"module": "index.js",
|
|
19
19
|
"types": "index.d.ts",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"vscode": "npm:@codingame/monaco-vscode-api@4.
|
|
21
|
+
"vscode": "npm:@codingame/monaco-vscode-api@4.1.0"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export { AbstractDialogHandler, IDialogService, IFileDialogService, getFileNamesMessage } from 'vscode/vscode/vs/platform/dialogs/common/dialogs';
|
|
2
|
-
|
|
3
|
-
var ConfirmResult;
|
|
4
|
-
( (function(ConfirmResult) {
|
|
5
|
-
ConfirmResult[ConfirmResult["SAVE"] = 0] = "SAVE";
|
|
6
|
-
ConfirmResult[ConfirmResult["DONT_SAVE"] = 1] = "DONT_SAVE";
|
|
7
|
-
ConfirmResult[ConfirmResult["CANCEL"] = 2] = "CANCEL";
|
|
8
|
-
})(ConfirmResult || (ConfirmResult = {})));
|
|
9
|
-
|
|
10
|
-
export { ConfirmResult };
|
|
@@ -1,406 +0,0 @@
|
|
|
1
|
-
import { Throttler } from 'vscode/vscode/vs/base/common/async';
|
|
2
|
-
import { VSBuffer } from 'vscode/vscode/vs/base/common/buffer';
|
|
3
|
-
import { Event, Emitter } from 'vscode/vscode/vs/base/common/event';
|
|
4
|
-
import { Disposable } from 'vscode/vscode/vs/base/common/lifecycle';
|
|
5
|
-
import { ExtUri } from 'vscode/vscode/vs/base/common/resources';
|
|
6
|
-
import { isString } from 'vscode/vscode/vs/base/common/types';
|
|
7
|
-
import { URI } from 'vscode/vscode/vs/base/common/uri';
|
|
8
|
-
import { localizeWithPath } from 'vscode/vscode/vs/nls';
|
|
9
|
-
import { createFileSystemProviderError, FileSystemProviderErrorCode, FileType, FileSystemProviderError } from 'vscode/vscode/vs/platform/files/common/files';
|
|
10
|
-
import { DBClosedError } from 'vscode/vscode/vs/base/browser/indexedDB';
|
|
11
|
-
import { BroadcastDataChannel } from 'vscode/vscode/vs/base/browser/broadcast';
|
|
12
|
-
|
|
13
|
-
const ERR_FILE_NOT_FOUND = createFileSystemProviderError(( localizeWithPath(
|
|
14
|
-
'vs/platform/files/browser/indexedDBFileSystemProvider',
|
|
15
|
-
'fileNotExists',
|
|
16
|
-
"File does not exist"
|
|
17
|
-
)), FileSystemProviderErrorCode.FileNotFound);
|
|
18
|
-
const ERR_FILE_IS_DIR = createFileSystemProviderError(( localizeWithPath(
|
|
19
|
-
'vs/platform/files/browser/indexedDBFileSystemProvider',
|
|
20
|
-
'fileIsDirectory',
|
|
21
|
-
"File is Directory"
|
|
22
|
-
)), FileSystemProviderErrorCode.FileIsADirectory);
|
|
23
|
-
const ERR_FILE_NOT_DIR = createFileSystemProviderError(( localizeWithPath(
|
|
24
|
-
'vs/platform/files/browser/indexedDBFileSystemProvider',
|
|
25
|
-
'fileNotDirectory',
|
|
26
|
-
"File is not a directory"
|
|
27
|
-
)), FileSystemProviderErrorCode.FileNotADirectory);
|
|
28
|
-
const ERR_DIR_NOT_EMPTY = createFileSystemProviderError(( localizeWithPath(
|
|
29
|
-
'vs/platform/files/browser/indexedDBFileSystemProvider',
|
|
30
|
-
'dirIsNotEmpty',
|
|
31
|
-
"Directory is not empty"
|
|
32
|
-
)), FileSystemProviderErrorCode.Unknown);
|
|
33
|
-
const ERR_FILE_EXCEEDS_STORAGE_QUOTA = createFileSystemProviderError(( localizeWithPath(
|
|
34
|
-
'vs/platform/files/browser/indexedDBFileSystemProvider',
|
|
35
|
-
'fileExceedsStorageQuota',
|
|
36
|
-
"File exceeds available storage quota"
|
|
37
|
-
)), FileSystemProviderErrorCode.FileExceedsStorageQuota);
|
|
38
|
-
const ERR_UNKNOWN_INTERNAL = (message) => createFileSystemProviderError(( localizeWithPath(
|
|
39
|
-
'vs/platform/files/browser/indexedDBFileSystemProvider',
|
|
40
|
-
'internal',
|
|
41
|
-
"Internal error occurred in IndexedDB File System Provider. ({0})",
|
|
42
|
-
message
|
|
43
|
-
)), FileSystemProviderErrorCode.Unknown);
|
|
44
|
-
class IndexedDBFileSystemNode {
|
|
45
|
-
constructor(entry) {
|
|
46
|
-
this.entry = entry;
|
|
47
|
-
this.type = entry.type;
|
|
48
|
-
}
|
|
49
|
-
read(path) {
|
|
50
|
-
return this.doRead(path.split('/').filter(p => p.length));
|
|
51
|
-
}
|
|
52
|
-
doRead(pathParts) {
|
|
53
|
-
if (pathParts.length === 0) {
|
|
54
|
-
return this.entry;
|
|
55
|
-
}
|
|
56
|
-
if (this.entry.type !== FileType.Directory) {
|
|
57
|
-
throw ERR_UNKNOWN_INTERNAL('Internal error reading from IndexedDBFSNode -- expected directory at ' + this.entry.path);
|
|
58
|
-
}
|
|
59
|
-
const next = this.entry.children.get(pathParts[0]);
|
|
60
|
-
if (!next) {
|
|
61
|
-
return undefined;
|
|
62
|
-
}
|
|
63
|
-
return next.doRead(pathParts.slice(1));
|
|
64
|
-
}
|
|
65
|
-
delete(path) {
|
|
66
|
-
const toDelete = path.split('/').filter(p => p.length);
|
|
67
|
-
if (toDelete.length === 0) {
|
|
68
|
-
if (this.entry.type !== FileType.Directory) {
|
|
69
|
-
throw ERR_UNKNOWN_INTERNAL(`Internal error deleting from IndexedDBFSNode. Expected root entry to be directory`);
|
|
70
|
-
}
|
|
71
|
-
this.entry.children.clear();
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
return this.doDelete(toDelete, path);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
doDelete(pathParts, originalPath) {
|
|
78
|
-
if (pathParts.length === 0) {
|
|
79
|
-
throw ERR_UNKNOWN_INTERNAL(`Internal error deleting from IndexedDBFSNode -- got no deletion path parts (encountered while deleting ${originalPath})`);
|
|
80
|
-
}
|
|
81
|
-
else if (this.entry.type !== FileType.Directory) {
|
|
82
|
-
throw ERR_UNKNOWN_INTERNAL('Internal error deleting from IndexedDBFSNode -- expected directory at ' + this.entry.path);
|
|
83
|
-
}
|
|
84
|
-
else if (pathParts.length === 1) {
|
|
85
|
-
this.entry.children.delete(pathParts[0]);
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
const next = this.entry.children.get(pathParts[0]);
|
|
89
|
-
if (!next) {
|
|
90
|
-
throw ERR_UNKNOWN_INTERNAL('Internal error deleting from IndexedDBFSNode -- expected entry at ' + this.entry.path + '/' + next);
|
|
91
|
-
}
|
|
92
|
-
next.doDelete(pathParts.slice(1), originalPath);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
add(path, entry) {
|
|
96
|
-
this.doAdd(path.split('/').filter(p => p.length), entry, path);
|
|
97
|
-
}
|
|
98
|
-
doAdd(pathParts, entry, originalPath) {
|
|
99
|
-
if (pathParts.length === 0) {
|
|
100
|
-
throw ERR_UNKNOWN_INTERNAL(`Internal error creating IndexedDBFSNode -- adding empty path (encountered while adding ${originalPath})`);
|
|
101
|
-
}
|
|
102
|
-
else if (this.entry.type !== FileType.Directory) {
|
|
103
|
-
throw ERR_UNKNOWN_INTERNAL(`Internal error creating IndexedDBFSNode -- parent is not a directory (encountered while adding ${originalPath})`);
|
|
104
|
-
}
|
|
105
|
-
else if (pathParts.length === 1) {
|
|
106
|
-
const next = pathParts[0];
|
|
107
|
-
const existing = this.entry.children.get(next);
|
|
108
|
-
if (entry.type === 'dir') {
|
|
109
|
-
if (existing?.entry.type === FileType.File) {
|
|
110
|
-
throw ERR_UNKNOWN_INTERNAL(`Internal error creating IndexedDBFSNode -- overwriting file with directory: ${this.entry.path}/${next} (encountered while adding ${originalPath})`);
|
|
111
|
-
}
|
|
112
|
-
this.entry.children.set(next, existing ?? ( new IndexedDBFileSystemNode({
|
|
113
|
-
type: FileType.Directory,
|
|
114
|
-
path: this.entry.path + '/' + next,
|
|
115
|
-
children: ( new Map()),
|
|
116
|
-
})));
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
if (existing?.entry.type === FileType.Directory) {
|
|
120
|
-
throw ERR_UNKNOWN_INTERNAL(`Internal error creating IndexedDBFSNode -- overwriting directory with file: ${this.entry.path}/${next} (encountered while adding ${originalPath})`);
|
|
121
|
-
}
|
|
122
|
-
this.entry.children.set(next, ( new IndexedDBFileSystemNode({
|
|
123
|
-
type: FileType.File,
|
|
124
|
-
path: this.entry.path + '/' + next,
|
|
125
|
-
size: entry.size,
|
|
126
|
-
})));
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
else if (pathParts.length > 1) {
|
|
130
|
-
const next = pathParts[0];
|
|
131
|
-
let childNode = this.entry.children.get(next);
|
|
132
|
-
if (!childNode) {
|
|
133
|
-
childNode = ( new IndexedDBFileSystemNode({
|
|
134
|
-
children: ( new Map()),
|
|
135
|
-
path: this.entry.path + '/' + next,
|
|
136
|
-
type: FileType.Directory
|
|
137
|
-
}));
|
|
138
|
-
this.entry.children.set(next, childNode);
|
|
139
|
-
}
|
|
140
|
-
else if (childNode.type === FileType.File) {
|
|
141
|
-
throw ERR_UNKNOWN_INTERNAL(`Internal error creating IndexedDBFSNode -- overwriting file entry with directory: ${this.entry.path}/${next} (encountered while adding ${originalPath})`);
|
|
142
|
-
}
|
|
143
|
-
childNode.doAdd(pathParts.slice(1), entry, originalPath);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
print(indentation = '') {
|
|
147
|
-
console.log(indentation + this.entry.path);
|
|
148
|
-
if (this.entry.type === FileType.Directory) {
|
|
149
|
-
this.entry.children.forEach(child => child.print(indentation + ' '));
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
class IndexedDBFileSystemProvider extends Disposable {
|
|
154
|
-
constructor(scheme, indexedDB, store, watchCrossWindowChanges) {
|
|
155
|
-
super();
|
|
156
|
-
this.scheme = scheme;
|
|
157
|
-
this.indexedDB = indexedDB;
|
|
158
|
-
this.store = store;
|
|
159
|
-
this.capabilities = 2
|
|
160
|
-
| 1024 ;
|
|
161
|
-
this.onDidChangeCapabilities = Event.None;
|
|
162
|
-
this.extUri = ( new ExtUri(() => false)) ;
|
|
163
|
-
this._onDidChangeFile = this._register(( new Emitter()));
|
|
164
|
-
this.onDidChangeFile = this._onDidChangeFile.event;
|
|
165
|
-
this._onReportError = this._register(( new Emitter()));
|
|
166
|
-
this.onReportError = this._onReportError.event;
|
|
167
|
-
this.mtimes = ( new Map());
|
|
168
|
-
this.fileWriteBatch = [];
|
|
169
|
-
this.writeManyThrottler = ( new Throttler());
|
|
170
|
-
if (watchCrossWindowChanges) {
|
|
171
|
-
this.changesBroadcastChannel = this._register(( new BroadcastDataChannel(`vscode.indexedDB.${scheme}.changes`)));
|
|
172
|
-
this._register(this.changesBroadcastChannel.onDidReceiveData(changes => {
|
|
173
|
-
this._onDidChangeFile.fire(( changes.map(c => ({ type: c.type, resource: URI.revive(c.resource) }))));
|
|
174
|
-
}));
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
watch(resource, opts) {
|
|
178
|
-
return Disposable.None;
|
|
179
|
-
}
|
|
180
|
-
async mkdir(resource) {
|
|
181
|
-
try {
|
|
182
|
-
const resourceStat = await this.stat(resource);
|
|
183
|
-
if (resourceStat.type === FileType.File) {
|
|
184
|
-
throw ERR_FILE_NOT_DIR;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
catch (error) { }
|
|
188
|
-
(await this.getFiletree()).add(resource.path, { type: 'dir' });
|
|
189
|
-
}
|
|
190
|
-
async stat(resource) {
|
|
191
|
-
const entry = (await this.getFiletree()).read(resource.path);
|
|
192
|
-
if (entry?.type === FileType.File) {
|
|
193
|
-
return {
|
|
194
|
-
type: FileType.File,
|
|
195
|
-
ctime: 0,
|
|
196
|
-
mtime: this.mtimes.get(( resource.toString())) || 0,
|
|
197
|
-
size: entry.size ?? (await this.readFile(resource)).byteLength
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
if (entry?.type === FileType.Directory) {
|
|
201
|
-
return {
|
|
202
|
-
type: FileType.Directory,
|
|
203
|
-
ctime: 0,
|
|
204
|
-
mtime: 0,
|
|
205
|
-
size: 0
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
throw ERR_FILE_NOT_FOUND;
|
|
209
|
-
}
|
|
210
|
-
async readdir(resource) {
|
|
211
|
-
try {
|
|
212
|
-
const entry = (await this.getFiletree()).read(resource.path);
|
|
213
|
-
if (!entry) {
|
|
214
|
-
return [];
|
|
215
|
-
}
|
|
216
|
-
if (entry.type !== FileType.Directory) {
|
|
217
|
-
throw ERR_FILE_NOT_DIR;
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
return ( [...entry.children.entries()].map(([name, node]) => [name, node.type]));
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
catch (error) {
|
|
224
|
-
this.reportError('readDir', error);
|
|
225
|
-
throw error;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
async readFile(resource) {
|
|
229
|
-
try {
|
|
230
|
-
const result = await this.indexedDB.runInTransaction(this.store, 'readonly', objectStore => objectStore.get(resource.path));
|
|
231
|
-
if (result === undefined) {
|
|
232
|
-
throw ERR_FILE_NOT_FOUND;
|
|
233
|
-
}
|
|
234
|
-
const buffer = result instanceof Uint8Array ? result : isString(result) ? VSBuffer.fromString(result).buffer : undefined;
|
|
235
|
-
if (buffer === undefined) {
|
|
236
|
-
throw ERR_UNKNOWN_INTERNAL(`IndexedDB entry at "${resource.path}" in unexpected format`);
|
|
237
|
-
}
|
|
238
|
-
const fileTree = await this.getFiletree();
|
|
239
|
-
fileTree.add(resource.path, { type: 'file', size: buffer.byteLength });
|
|
240
|
-
return buffer;
|
|
241
|
-
}
|
|
242
|
-
catch (error) {
|
|
243
|
-
this.reportError('readFile', error);
|
|
244
|
-
throw error;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
async writeFile(resource, content, opts) {
|
|
248
|
-
try {
|
|
249
|
-
const existing = await this.stat(resource).catch(() => undefined);
|
|
250
|
-
if (existing?.type === FileType.Directory) {
|
|
251
|
-
throw ERR_FILE_IS_DIR;
|
|
252
|
-
}
|
|
253
|
-
await this.bulkWrite([[resource, content]]);
|
|
254
|
-
}
|
|
255
|
-
catch (error) {
|
|
256
|
-
this.reportError('writeFile', error);
|
|
257
|
-
throw error;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
async rename(from, to, opts) {
|
|
261
|
-
const fileTree = await this.getFiletree();
|
|
262
|
-
const fromEntry = fileTree.read(from.path);
|
|
263
|
-
if (!fromEntry) {
|
|
264
|
-
throw ERR_FILE_NOT_FOUND;
|
|
265
|
-
}
|
|
266
|
-
const toEntry = fileTree.read(to.path);
|
|
267
|
-
if (toEntry) {
|
|
268
|
-
if (!opts.overwrite) {
|
|
269
|
-
throw createFileSystemProviderError('file exists already', FileSystemProviderErrorCode.FileExists);
|
|
270
|
-
}
|
|
271
|
-
if (toEntry.type !== fromEntry.type) {
|
|
272
|
-
throw createFileSystemProviderError('Cannot rename files with different types', FileSystemProviderErrorCode.Unknown);
|
|
273
|
-
}
|
|
274
|
-
await this.delete(to, { recursive: true, useTrash: false, atomic: false });
|
|
275
|
-
}
|
|
276
|
-
const toTargetResource = (path) => this.extUri.joinPath(to, this.extUri.relativePath(from, from.with({ path })) || '');
|
|
277
|
-
const sourceEntries = await this.tree(from);
|
|
278
|
-
const sourceFiles = [];
|
|
279
|
-
for (const sourceEntry of sourceEntries) {
|
|
280
|
-
if (sourceEntry[1] === FileType.File) {
|
|
281
|
-
sourceFiles.push(sourceEntry);
|
|
282
|
-
}
|
|
283
|
-
else if (sourceEntry[1] === FileType.Directory) {
|
|
284
|
-
fileTree.add(toTargetResource(sourceEntry[0]).path, { type: 'dir' });
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
if (sourceFiles.length) {
|
|
288
|
-
const targetFiles = [];
|
|
289
|
-
const sourceFilesContents = await this.indexedDB.runInTransaction(this.store, 'readonly', objectStore => ( sourceFiles.map(([path]) => objectStore.get(path))));
|
|
290
|
-
for (let index = 0; index < sourceFiles.length; index++) {
|
|
291
|
-
const content = sourceFilesContents[index] instanceof Uint8Array ? sourceFilesContents[index] : isString(sourceFilesContents[index]) ? VSBuffer.fromString(sourceFilesContents[index]).buffer : undefined;
|
|
292
|
-
if (content) {
|
|
293
|
-
targetFiles.push([toTargetResource(sourceFiles[index][0]), content]);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
await this.bulkWrite(targetFiles);
|
|
297
|
-
}
|
|
298
|
-
await this.delete(from, { recursive: true, useTrash: false, atomic: false });
|
|
299
|
-
}
|
|
300
|
-
async delete(resource, opts) {
|
|
301
|
-
let stat;
|
|
302
|
-
try {
|
|
303
|
-
stat = await this.stat(resource);
|
|
304
|
-
}
|
|
305
|
-
catch (e) {
|
|
306
|
-
if (e.code === FileSystemProviderErrorCode.FileNotFound) {
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
throw e;
|
|
310
|
-
}
|
|
311
|
-
let toDelete;
|
|
312
|
-
if (opts.recursive) {
|
|
313
|
-
const tree = await this.tree(resource);
|
|
314
|
-
toDelete = ( tree.map(([path]) => path));
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
317
|
-
if (stat.type === FileType.Directory && (await this.readdir(resource)).length) {
|
|
318
|
-
throw ERR_DIR_NOT_EMPTY;
|
|
319
|
-
}
|
|
320
|
-
toDelete = [resource.path];
|
|
321
|
-
}
|
|
322
|
-
await this.deleteKeys(toDelete);
|
|
323
|
-
(await this.getFiletree()).delete(resource.path);
|
|
324
|
-
toDelete.forEach(key => this.mtimes.delete(key));
|
|
325
|
-
this.triggerChanges(( toDelete.map(
|
|
326
|
-
path => ({ resource: resource.with({ path }), type: 2 })
|
|
327
|
-
)));
|
|
328
|
-
}
|
|
329
|
-
async tree(resource) {
|
|
330
|
-
const stat = await this.stat(resource);
|
|
331
|
-
const allEntries = [[resource.path, stat.type]];
|
|
332
|
-
if (stat.type === FileType.Directory) {
|
|
333
|
-
const dirEntries = await this.readdir(resource);
|
|
334
|
-
for (const [key, type] of dirEntries) {
|
|
335
|
-
const childResource = this.extUri.joinPath(resource, key);
|
|
336
|
-
allEntries.push([childResource.path, type]);
|
|
337
|
-
if (type === FileType.Directory) {
|
|
338
|
-
const childEntries = await this.tree(childResource);
|
|
339
|
-
allEntries.push(...childEntries);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
return allEntries;
|
|
344
|
-
}
|
|
345
|
-
triggerChanges(changes) {
|
|
346
|
-
if (changes.length) {
|
|
347
|
-
this._onDidChangeFile.fire(changes);
|
|
348
|
-
this.changesBroadcastChannel?.postData(changes);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
getFiletree() {
|
|
352
|
-
if (!this.cachedFiletree) {
|
|
353
|
-
this.cachedFiletree = (async () => {
|
|
354
|
-
const rootNode = ( new IndexedDBFileSystemNode({
|
|
355
|
-
children: ( new Map()),
|
|
356
|
-
path: '',
|
|
357
|
-
type: FileType.Directory
|
|
358
|
-
}));
|
|
359
|
-
const result = await this.indexedDB.runInTransaction(this.store, 'readonly', objectStore => objectStore.getAllKeys());
|
|
360
|
-
const keys = ( result.map(key => ( key.toString())));
|
|
361
|
-
keys.forEach(key => rootNode.add(key, { type: 'file' }));
|
|
362
|
-
return rootNode;
|
|
363
|
-
})();
|
|
364
|
-
}
|
|
365
|
-
return this.cachedFiletree;
|
|
366
|
-
}
|
|
367
|
-
async bulkWrite(files) {
|
|
368
|
-
files.forEach(([resource, content]) => this.fileWriteBatch.push({ content, resource }));
|
|
369
|
-
await this.writeManyThrottler.queue(() => this.writeMany());
|
|
370
|
-
const fileTree = await this.getFiletree();
|
|
371
|
-
for (const [resource, content] of files) {
|
|
372
|
-
fileTree.add(resource.path, { type: 'file', size: content.byteLength });
|
|
373
|
-
this.mtimes.set(( resource.toString()), Date.now());
|
|
374
|
-
}
|
|
375
|
-
this.triggerChanges(( files.map(([resource]) => ({ resource, type: 0 }))));
|
|
376
|
-
}
|
|
377
|
-
async writeMany() {
|
|
378
|
-
if (this.fileWriteBatch.length) {
|
|
379
|
-
const fileBatch = this.fileWriteBatch.splice(0, this.fileWriteBatch.length);
|
|
380
|
-
try {
|
|
381
|
-
await this.indexedDB.runInTransaction(this.store, 'readwrite', objectStore => ( fileBatch.map(entry => {
|
|
382
|
-
return objectStore.put(entry.content, entry.resource.path);
|
|
383
|
-
})));
|
|
384
|
-
}
|
|
385
|
-
catch (ex) {
|
|
386
|
-
if (ex instanceof DOMException && ex.name === 'QuotaExceededError') {
|
|
387
|
-
throw ERR_FILE_EXCEEDS_STORAGE_QUOTA;
|
|
388
|
-
}
|
|
389
|
-
throw ex;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
async deleteKeys(keys) {
|
|
394
|
-
if (keys.length) {
|
|
395
|
-
await this.indexedDB.runInTransaction(this.store, 'readwrite', objectStore => ( keys.map(key => objectStore.delete(key))));
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
async reset() {
|
|
399
|
-
await this.indexedDB.runInTransaction(this.store, 'readwrite', objectStore => objectStore.clear());
|
|
400
|
-
}
|
|
401
|
-
reportError(operation, error) {
|
|
402
|
-
this._onReportError.fire({ scheme: this.scheme, operation, code: error instanceof FileSystemProviderError || error instanceof DBClosedError ? error.code : 'unknown' });
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
export { IndexedDBFileSystemProvider };
|