|
|
@ -1,12 +1,23 @@
|
|
|
|
import * as vscode from 'vscode';
|
|
|
|
import * as vscode from 'vscode';
|
|
|
|
|
|
|
|
import { getFlag, subscribeToGlobalFlags } from './config';
|
|
|
|
import { Logging } from './logging';
|
|
|
|
import { Logging } from './logging';
|
|
|
|
import type { Manager } from './manager';
|
|
|
|
import type { Manager } from './manager';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const ALL_DEBUG_FLAGS = [
|
|
|
|
|
|
|
|
'stat', 'readDirectory', 'createDirectory',
|
|
|
|
|
|
|
|
'readFile', 'writeFile', 'delete', 'rename',
|
|
|
|
|
|
|
|
].map(v => v.toLowerCase());
|
|
|
|
|
|
|
|
|
|
|
|
export class FileSystemRouter implements vscode.FileSystemProvider {
|
|
|
|
export class FileSystemRouter implements vscode.FileSystemProvider {
|
|
|
|
public onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]>;
|
|
|
|
public onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]>;
|
|
|
|
protected onDidChangeFileEmitter = new vscode.EventEmitter<vscode.FileChangeEvent[]>();
|
|
|
|
protected onDidChangeFileEmitter = new vscode.EventEmitter<vscode.FileChangeEvent[]>();
|
|
|
|
|
|
|
|
protected debugFlags: string[];
|
|
|
|
constructor(protected readonly manager: Manager) {
|
|
|
|
constructor(protected readonly manager: Manager) {
|
|
|
|
this.onDidChangeFile = this.onDidChangeFileEmitter.event;
|
|
|
|
this.onDidChangeFile = this.onDidChangeFileEmitter.event;
|
|
|
|
|
|
|
|
subscribeToGlobalFlags(() => {
|
|
|
|
|
|
|
|
this.debugFlags = `${getFlag('DEBUG_FSR')?.[0] || ''}`.toLowerCase().split(/,\s*|\s+/g);
|
|
|
|
|
|
|
|
if (this.debugFlags.includes('all')) this.debugFlags.push(...ALL_DEBUG_FLAGS);
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public async assertFs(uri: vscode.Uri): Promise<vscode.FileSystemProvider> {
|
|
|
|
public async assertFs(uri: vscode.Uri): Promise<vscode.FileSystemProvider> {
|
|
|
|
const fs = this.manager.getFs(uri);
|
|
|
|
const fs = this.manager.getFs(uri);
|
|
|
@ -24,30 +35,41 @@ export class FileSystemRouter implements vscode.FileSystemProvider {
|
|
|
|
return new vscode.Disposable(() => { });
|
|
|
|
return new vscode.Disposable(() => { });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public async stat(uri: vscode.Uri): Promise<vscode.FileStat> {
|
|
|
|
public async stat(uri: vscode.Uri): Promise<vscode.FileStat> {
|
|
|
|
|
|
|
|
if (this.debugFlags.includes('stat'))
|
|
|
|
|
|
|
|
Logging.debug`Performing stat for ${uri}`;
|
|
|
|
return (await this.assertFs(uri)).stat(uri);
|
|
|
|
return (await this.assertFs(uri)).stat(uri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public async readDirectory(uri: vscode.Uri): Promise<[string, vscode.FileType][]> {
|
|
|
|
public async readDirectory(uri: vscode.Uri): Promise<[string, vscode.FileType][]> {
|
|
|
|
|
|
|
|
if (this.debugFlags.includes('readdirectory'))
|
|
|
|
|
|
|
|
Logging.debug`Reading directory ${uri}`;
|
|
|
|
return (await this.assertFs(uri)).readDirectory(uri);
|
|
|
|
return (await this.assertFs(uri)).readDirectory(uri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public async createDirectory(uri: vscode.Uri): Promise<void> {
|
|
|
|
public async createDirectory(uri: vscode.Uri): Promise<void> {
|
|
|
|
|
|
|
|
if (this.debugFlags.includes('createdirectory'))
|
|
|
|
|
|
|
|
Logging.debug`Creating directory ${uri}`;
|
|
|
|
return (await this.assertFs(uri)).createDirectory(uri);
|
|
|
|
return (await this.assertFs(uri)).createDirectory(uri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public async readFile(uri: vscode.Uri): Promise<Uint8Array> {
|
|
|
|
public async readFile(uri: vscode.Uri): Promise<Uint8Array> {
|
|
|
|
|
|
|
|
if (this.debugFlags.includes('readfile'))
|
|
|
|
Logging.debug`Reading ${uri}`;
|
|
|
|
Logging.debug`Reading ${uri}`;
|
|
|
|
return (await this.assertFs(uri)).readFile(uri);
|
|
|
|
return (await this.assertFs(uri)).readFile(uri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public async writeFile(uri: vscode.Uri, content: Uint8Array, options: { create: boolean; overwrite: boolean; }): Promise<void> {
|
|
|
|
public async writeFile(uri: vscode.Uri, content: Uint8Array, options: { create: boolean; overwrite: boolean; }): Promise<void> {
|
|
|
|
Logging.debug`Writing ${content.length} bytes to ${uri}`;
|
|
|
|
if (this.debugFlags.includes('writefile'))
|
|
|
|
|
|
|
|
Logging.debug`Writing ${content.length} bytes to ${uri} (options: ${options})`;
|
|
|
|
return (await this.assertFs(uri)).writeFile(uri, content, options);
|
|
|
|
return (await this.assertFs(uri)).writeFile(uri, content, options);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public async delete(uri: vscode.Uri, options: { recursive: boolean; }): Promise<void> {
|
|
|
|
public async delete(uri: vscode.Uri, options: { recursive: boolean; }): Promise<void> {
|
|
|
|
Logging.debug`Deleting ${uri}`;
|
|
|
|
if (this.debugFlags.includes('delete'))
|
|
|
|
|
|
|
|
Logging.debug`Deleting ${uri} (options: ${options})`;
|
|
|
|
return (await this.assertFs(uri)).delete(uri, options);
|
|
|
|
return (await this.assertFs(uri)).delete(uri, options);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
public async rename(oldUri: vscode.Uri, newUri: vscode.Uri, options: { overwrite: boolean; }): Promise<void> {
|
|
|
|
public async rename(oldUri: vscode.Uri, newUri: vscode.Uri, options: { overwrite: boolean; }): Promise<void> {
|
|
|
|
|
|
|
|
if (this.debugFlags.includes('rename'))
|
|
|
|
Logging.debug`Renaming ${oldUri} to ${newUri}`;
|
|
|
|
Logging.debug`Renaming ${oldUri} to ${newUri}`;
|
|
|
|
const fs = await this.assertFs(oldUri);
|
|
|
|
const fs = await this.assertFs(oldUri);
|
|
|
|
if (fs !== (await this.assertFs(newUri))) throw new Error(`Can't rename between different SSH filesystems`);
|
|
|
|
if (fs !== (await this.assertFs(newUri)))
|
|
|
|
|
|
|
|
throw new Error(`Can't rename between different SSH filesystems`);
|
|
|
|
return fs.rename(oldUri, newUri, options);
|
|
|
|
return fs.rename(oldUri, newUri, options);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|