mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-15 18:46:36 -05:00
* Merge from vscode 504f934659740e9d41501cad9f162b54d7745ad9 * delete unused folders * distro * Bump build node version * update chokidar * FIx hygiene errors * distro * Fix extension lint issues * Remove strict-vscode * Add copyright header exemptions * Bump vscode-extension-telemetry to fix webpacking issue with zone.js * distro * Fix failing tests (revert marked.js back to current one until we decide to update) * Skip searchmodel test * Fix mac build * temp debug script loading * Try disabling coverage * log error too * Revert "log error too" This reverts commit af0183e5d4ab458fdf44b88fbfab9908d090526f. * Revert "temp debug script loading" This reverts commit 3d687d541c76db2c5b55626c78ae448d3c25089c. * Add comments explaining coverage disabling * Fix ansi_up loading issue * Merge latest from ads * Use newer option * Fix compile * add debug logging warn * Always log stack * log more * undo debug * Update to use correct base path (+cleanup) * distro * fix compile errors * Remove strict-vscode * Fix sql editors not showing * Show db dropdown input & fix styling * Fix more info in gallery * Fix gallery asset requests * Delete unused workflow * Fix tapable resolutions for smoke test compile error * Fix smoke compile * Disable crash reporting * Disable interactive Co-authored-by: ADS Merger <karlb@microsoft.com>
231 lines
7.1 KiB
TypeScript
231 lines
7.1 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { Emitter, Event } from 'vs/base/common/event';
|
|
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
|
import * as resources from 'vs/base/common/resources';
|
|
import { URI } from 'vs/base/common/uri';
|
|
import { FileChangeType, FileDeleteOptions, FileOverwriteOptions, FileSystemProviderCapabilities, FileSystemProviderError, FileSystemProviderErrorCode, FileType, FileWriteOptions, IFileChange, IFileSystemProviderWithFileReadWriteCapability, IStat, IWatchOptions } from 'vs/platform/files/common/files';
|
|
|
|
class File implements IStat {
|
|
|
|
type: FileType.File;
|
|
ctime: number;
|
|
mtime: number;
|
|
size: number;
|
|
|
|
name: string;
|
|
data?: Uint8Array;
|
|
|
|
constructor(name: string) {
|
|
this.type = FileType.File;
|
|
this.ctime = Date.now();
|
|
this.mtime = Date.now();
|
|
this.size = 0;
|
|
this.name = name;
|
|
}
|
|
}
|
|
|
|
class Directory implements IStat {
|
|
|
|
type: FileType.Directory;
|
|
ctime: number;
|
|
mtime: number;
|
|
size: number;
|
|
|
|
name: string;
|
|
entries: Map<string, File | Directory>;
|
|
|
|
constructor(name: string) {
|
|
this.type = FileType.Directory;
|
|
this.ctime = Date.now();
|
|
this.mtime = Date.now();
|
|
this.size = 0;
|
|
this.name = name;
|
|
this.entries = new Map();
|
|
}
|
|
}
|
|
|
|
export type Entry = File | Directory;
|
|
|
|
export class InMemoryFileSystemProvider extends Disposable implements IFileSystemProviderWithFileReadWriteCapability {
|
|
|
|
readonly capabilities: FileSystemProviderCapabilities =
|
|
FileSystemProviderCapabilities.FileReadWrite
|
|
| FileSystemProviderCapabilities.PathCaseSensitive;
|
|
readonly onDidChangeCapabilities: Event<void> = Event.None;
|
|
|
|
root = new Directory('');
|
|
|
|
// --- manage file metadata
|
|
|
|
async stat(resource: URI): Promise<IStat> {
|
|
return this._lookup(resource, false);
|
|
}
|
|
|
|
async readdir(resource: URI): Promise<[string, FileType][]> {
|
|
const entry = this._lookupAsDirectory(resource, false);
|
|
let result: [string, FileType][] = [];
|
|
entry.entries.forEach((child, name) => result.push([name, child.type]));
|
|
return result;
|
|
}
|
|
|
|
// --- manage file contents
|
|
|
|
async readFile(resource: URI): Promise<Uint8Array> {
|
|
const data = this._lookupAsFile(resource, false).data;
|
|
if (data) {
|
|
return data;
|
|
}
|
|
throw new FileSystemProviderError('file not found', FileSystemProviderErrorCode.FileNotFound);
|
|
}
|
|
|
|
async writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise<void> {
|
|
let basename = resources.basename(resource);
|
|
let parent = this._lookupParentDirectory(resource);
|
|
let entry = parent.entries.get(basename);
|
|
if (entry instanceof Directory) {
|
|
throw new FileSystemProviderError('file is directory', FileSystemProviderErrorCode.FileIsADirectory);
|
|
}
|
|
if (!entry && !opts.create) {
|
|
throw new FileSystemProviderError('file not found', FileSystemProviderErrorCode.FileNotFound);
|
|
}
|
|
if (entry && opts.create && !opts.overwrite) {
|
|
throw new FileSystemProviderError('file exists already', FileSystemProviderErrorCode.FileExists);
|
|
}
|
|
if (!entry) {
|
|
entry = new File(basename);
|
|
parent.entries.set(basename, entry);
|
|
this._fireSoon({ type: FileChangeType.ADDED, resource });
|
|
}
|
|
entry.mtime = Date.now();
|
|
entry.size = content.byteLength;
|
|
entry.data = content;
|
|
|
|
this._fireSoon({ type: FileChangeType.UPDATED, resource });
|
|
}
|
|
|
|
// --- manage files/folders
|
|
|
|
async rename(from: URI, to: URI, opts: FileOverwriteOptions): Promise<void> {
|
|
if (!opts.overwrite && this._lookup(to, true)) {
|
|
throw new FileSystemProviderError('file exists already', FileSystemProviderErrorCode.FileExists);
|
|
}
|
|
|
|
let entry = this._lookup(from, false);
|
|
let oldParent = this._lookupParentDirectory(from);
|
|
|
|
let newParent = this._lookupParentDirectory(to);
|
|
let newName = resources.basename(to);
|
|
|
|
oldParent.entries.delete(entry.name);
|
|
entry.name = newName;
|
|
newParent.entries.set(newName, entry);
|
|
|
|
this._fireSoon(
|
|
{ type: FileChangeType.DELETED, resource: from },
|
|
{ type: FileChangeType.ADDED, resource: to }
|
|
);
|
|
}
|
|
|
|
async delete(resource: URI, opts: FileDeleteOptions): Promise<void> {
|
|
let dirname = resources.dirname(resource);
|
|
let basename = resources.basename(resource);
|
|
let parent = this._lookupAsDirectory(dirname, false);
|
|
if (parent.entries.has(basename)) {
|
|
parent.entries.delete(basename);
|
|
parent.mtime = Date.now();
|
|
parent.size -= 1;
|
|
this._fireSoon({ type: FileChangeType.UPDATED, resource: dirname }, { resource, type: FileChangeType.DELETED });
|
|
}
|
|
}
|
|
|
|
async mkdir(resource: URI): Promise<void> {
|
|
let basename = resources.basename(resource);
|
|
let dirname = resources.dirname(resource);
|
|
let parent = this._lookupAsDirectory(dirname, false);
|
|
|
|
let entry = new Directory(basename);
|
|
parent.entries.set(entry.name, entry);
|
|
parent.mtime = Date.now();
|
|
parent.size += 1;
|
|
this._fireSoon({ type: FileChangeType.UPDATED, resource: dirname }, { type: FileChangeType.ADDED, resource });
|
|
}
|
|
|
|
// --- lookup
|
|
|
|
private _lookup(uri: URI, silent: false): Entry;
|
|
private _lookup(uri: URI, silent: boolean): Entry | undefined;
|
|
private _lookup(uri: URI, silent: boolean): Entry | undefined {
|
|
let parts = uri.path.split('/');
|
|
let entry: Entry = this.root;
|
|
for (const part of parts) {
|
|
if (!part) {
|
|
continue;
|
|
}
|
|
let child: Entry | undefined;
|
|
if (entry instanceof Directory) {
|
|
child = entry.entries.get(part);
|
|
}
|
|
if (!child) {
|
|
if (!silent) {
|
|
throw new FileSystemProviderError('file not found', FileSystemProviderErrorCode.FileNotFound);
|
|
} else {
|
|
return undefined;
|
|
}
|
|
}
|
|
entry = child;
|
|
}
|
|
return entry;
|
|
}
|
|
|
|
private _lookupAsDirectory(uri: URI, silent: boolean): Directory {
|
|
let entry = this._lookup(uri, silent);
|
|
if (entry instanceof Directory) {
|
|
return entry;
|
|
}
|
|
throw new FileSystemProviderError('file not a directory', FileSystemProviderErrorCode.FileNotADirectory);
|
|
}
|
|
|
|
private _lookupAsFile(uri: URI, silent: boolean): File {
|
|
let entry = this._lookup(uri, silent);
|
|
if (entry instanceof File) {
|
|
return entry;
|
|
}
|
|
throw new FileSystemProviderError('file is a directory', FileSystemProviderErrorCode.FileIsADirectory);
|
|
}
|
|
|
|
private _lookupParentDirectory(uri: URI): Directory {
|
|
const dirname = resources.dirname(uri);
|
|
return this._lookupAsDirectory(dirname, false);
|
|
}
|
|
|
|
// --- manage file events
|
|
|
|
private readonly _onDidChangeFile = this._register(new Emitter<readonly IFileChange[]>());
|
|
readonly onDidChangeFile: Event<readonly IFileChange[]> = this._onDidChangeFile.event;
|
|
|
|
private _bufferedChanges: IFileChange[] = [];
|
|
private _fireSoonHandle?: any;
|
|
|
|
watch(resource: URI, opts: IWatchOptions): IDisposable {
|
|
// ignore, fires for all changes...
|
|
return Disposable.None;
|
|
}
|
|
|
|
private _fireSoon(...changes: IFileChange[]): void {
|
|
this._bufferedChanges.push(...changes);
|
|
|
|
if (this._fireSoonHandle) {
|
|
clearTimeout(this._fireSoonHandle);
|
|
}
|
|
|
|
this._fireSoonHandle = setTimeout(() => {
|
|
this._onDidChangeFile.fire(this._bufferedChanges);
|
|
this._bufferedChanges.length = 0;
|
|
}, 5);
|
|
}
|
|
}
|