Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/filesystem/common/fileSystemService.ts
13401 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 type { FileStat, FileSystem, FileSystemWatcher, RelativePattern, Uri } from 'vscode';
7
import { LRUCache } from '../../../util/common/cache';
8
import { createServiceIdentifier } from '../../../util/common/services';
9
import { FileType } from './fileTypes';
10
11
export const IFileSystemService = createServiceIdentifier<IFileSystemService>('IFileSystemService');
12
13
export interface IFileSystemService extends FileSystem {
14
15
readonly _serviceBrand: undefined;
16
17
stat(uri: Uri): Promise<FileStat>;
18
readDirectory(uri: Uri): Promise<[string, FileType][]>;
19
createDirectory(uri: Uri): Promise<void>;
20
21
/**
22
* @param uri
23
* @param disableLimit Disable the {@link FS_READ_MAX_FILE_SIZE} limit and potentially crash the EH. USE THIS WITH CAUTION!
24
*/
25
readFile(uri: Uri, disableLimit?: boolean): Promise<Uint8Array>;
26
writeFile(uri: Uri, content: Uint8Array): Promise<void>;
27
delete(uri: Uri, options?: { recursive?: boolean; useTrash?: boolean }): Promise<void>;
28
rename(oldURI: Uri, newURI: Uri, options?: { overwrite?: boolean }): Promise<void>;
29
copy(source: Uri, destination: Uri, options?: { overwrite?: boolean }): Promise<void>;
30
isWritableFileSystem(scheme: string): boolean | undefined;
31
32
createFileSystemWatcher(glob: string | RelativePattern): FileSystemWatcher;
33
}
34
35
/**
36
* This is here to allow us to reuse the same readFile/JSON.parse across multiple invocations during simulations.
37
* This is disabled in production.
38
*/
39
export const fileSystemServiceReadAsJSON = new class {
40
private _cache: LRUCache<any> | null = null;
41
42
enable(): void {
43
this._cache = new LRUCache<any>(10);
44
}
45
46
public async readJSON<T>(fileSystemService: IFileSystemService, uri: Uri): Promise<T> {
47
if (!this._cache) {
48
return this._readJSON<T>(fileSystemService, uri);
49
}
50
const cachedValue = this._cache.get(uri.toString());
51
if (cachedValue !== undefined) {
52
return cachedValue;
53
}
54
const value = await this._readJSON<T>(fileSystemService, uri);
55
this._cache.put(uri.toString(), value);
56
return value;
57
}
58
59
private async _readJSON<T>(fileSystemService: IFileSystemService, uri: Uri): Promise<T> {
60
const buffer = await fileSystemService.readFile(uri, true);
61
return JSON.parse(buffer.toString()) as T;
62
}
63
}();
64
65
66
export const FS_READ_MAX_FILE_SIZE = 1024 * 1024 * 5; // 5 MB
67
68
export async function assertReadFileSizeLimit(fileSystemService: IFileSystemService, uri: Uri, onlyWarn?: boolean) {
69
const stat = await fileSystemService.stat(uri);
70
if (stat.size > FS_READ_MAX_FILE_SIZE) {
71
if (!onlyWarn) {
72
const message = `[FileSystemService] ${uri.toString()} EXCEEDS max file size. FAILED to read ${Math.round(stat.size / (1024 * 1024))}MB > ${Math.round(FS_READ_MAX_FILE_SIZE / (1024 * 1024))}MB`;
73
throw new Error(message);
74
} else {
75
const message = `[FileSystemService] ${uri.toString()} is a LARGE file (${Math.round(stat.size / (1024 * 1024))}MB > ${Math.round(FS_READ_MAX_FILE_SIZE / (1024 * 1024))}MB)`;
76
console.warn(message);
77
}
78
}
79
}
80
81
export async function createDirectoryIfNotExists(fileSystemService: IFileSystemService, uri: Uri): Promise<void> {
82
try {
83
const exists = await fileSystemService.stat(uri).then(() => true).catch(() => false);
84
if (exists) {
85
return;
86
}
87
await fileSystemService.createDirectory(uri);
88
} catch (err) {
89
// Possibly created by another asyn operation. Check again.
90
const exists = await fileSystemService.stat(uri).then(() => true).catch(() => false);
91
if (exists) {
92
return;
93
}
94
throw err;
95
}
96
}
97
98