|
|
|
@ -107,6 +107,74 @@ export class Manager implements vscode.TaskProvider, vscode.TerminalLinkProvider
|
|
|
|
|
* @param {FileSystemConfig} config - 文件系统的配置
|
|
|
|
|
* @returns {Promise<SSHFileSystem>} - 当文件系统创建完成时解析的 Promise
|
|
|
|
|
*/
|
|
|
|
|
/** 类图
|
|
|
|
|
* @startuml
|
|
|
|
|
* class SSHFileSystemManager {
|
|
|
|
|
* + createFileSystem(name: string, config?: FileSystemConfig): Promise<SSHFileSystem>
|
|
|
|
|
* + createTerminal(name: string, config?: FileSystemConfig | Connection, uri?: vscode.Uri): Promise<void>
|
|
|
|
|
* + getActiveFileSystems(): readonly SSHFileSystem[]
|
|
|
|
|
* + getFs(uri: vscode.Uri): SSHFileSystem | null
|
|
|
|
|
* + promptReconnect(name: string): Promise<void>
|
|
|
|
|
* }
|
|
|
|
|
* class SSHFileSystem {
|
|
|
|
|
* + onClose(handler: () => void): void
|
|
|
|
|
* }
|
|
|
|
|
* class Connection {
|
|
|
|
|
* + actualConfig: FileSystemConfig
|
|
|
|
|
* + filesystems: SSHFileSystem[]
|
|
|
|
|
* + pendingUserCount: number
|
|
|
|
|
* + home: string
|
|
|
|
|
* + client: any
|
|
|
|
|
* }
|
|
|
|
|
* class FileSystemConfig {
|
|
|
|
|
* + flags: any
|
|
|
|
|
* }
|
|
|
|
|
* SSHFileSystemManager --> Connection : uses
|
|
|
|
|
* SSHFileSystemManager --> SSHFileSystem : creates
|
|
|
|
|
* SSHFileSystem --> Connection : belongs to
|
|
|
|
|
* Connection --> FileSystemConfig : has
|
|
|
|
|
* @enduml
|
|
|
|
|
*/
|
|
|
|
|
/** 流程图
|
|
|
|
|
* @startuml
|
|
|
|
|
* start
|
|
|
|
|
* :防止启动时的竞态条件,并等待当前配置重载完成;
|
|
|
|
|
* if (检查是否已经存在一个具有指定名称的 SSHFileSystem 实例?) then (yes)
|
|
|
|
|
* :如果存在,则直接返回该实例;
|
|
|
|
|
* else (no)
|
|
|
|
|
* :声明一个名为 con 的变量,用于存储即将创建的 Connection 实例;
|
|
|
|
|
* :尝试从 creatingFileSystems 中获取已存在的 Promise,如果不存在则创建一个新的 Promise;
|
|
|
|
|
* :获取文件系统配置;
|
|
|
|
|
* if (如果没有提供配置?) then (yes)
|
|
|
|
|
* :如果没有找到配置,则抛出错误;
|
|
|
|
|
* else (no)
|
|
|
|
|
* :创建一个新的连接;
|
|
|
|
|
* :更新连接管理器中的连接信息;
|
|
|
|
|
* :获取连接的实际配置;
|
|
|
|
|
* :导入 getSFTP 和 SSHFileSystem 模块;
|
|
|
|
|
* :使用连接的实际配置创建 SFTP 会话;
|
|
|
|
|
* :创建一个新的 SSH 文件系统实例;
|
|
|
|
|
* :记录日志,表示已创建 SSH 文件系统并正在读取根目录;
|
|
|
|
|
* :添加文件系统到连接管理器,更新连接管理器中的文件系统列表;
|
|
|
|
|
* :将新创建的文件系统添加到 fileSystems 数组中;
|
|
|
|
|
* :从 creatingFileSystems 中删除该文件系统的 Promise;
|
|
|
|
|
* :监听文件系统的关闭事件,当文件系统关闭时,从 fileSystems 数组中删除该文件系统,并更新连接管理器中的文件系统列表;
|
|
|
|
|
* :刷新文件资源管理器,以显示新创建的文件系统;
|
|
|
|
|
* :更新连接管理器中的连接信息;
|
|
|
|
|
* if (检查是否可以访问主目录?) then (yes)
|
|
|
|
|
* :解决 Promise,返回创建的文件系统实例;
|
|
|
|
|
* else (no)
|
|
|
|
|
* :show error message and options;
|
|
|
|
|
* if (如果用户选择停止?) then (yes)
|
|
|
|
|
* :则拒绝 Promise 并抛出错误;
|
|
|
|
|
* else (no)
|
|
|
|
|
* :解决 Promise,返回创建的文件系统实例;
|
|
|
|
|
* endif
|
|
|
|
|
* endif
|
|
|
|
|
* endif
|
|
|
|
|
* stop
|
|
|
|
|
* @enduml
|
|
|
|
|
*/
|
|
|
|
|
public async createFileSystem(name: string, config?: FileSystemConfig): Promise<SSHFileSystem> {
|
|
|
|
|
await LOADING_CONFIGS; // Prevent race condition on startup, and wait for any current config reload to finish 防止启动时的竞态条件,并等待当前配置重载完成
|
|
|
|
|
// 检查是否已经存在一个具有指定名称的 SSHFileSystem 实例
|
|
|
|
@ -117,7 +185,7 @@ export class Manager implements vscode.TaskProvider, vscode.TerminalLinkProvider
|
|
|
|
|
let con: Connection | undefined;
|
|
|
|
|
// 尝试从 creatingFileSystems 中获取已存在的 Promise,如果不存在则创建一个新的 Promise
|
|
|
|
|
return this.creatingFileSystems[name] ||= catchingPromise<SSHFileSystem>(async (resolve, reject) => {
|
|
|
|
|
// 如果没有提供配置,则从默认配置中获取
|
|
|
|
|
// 获取文件系统配置,如果没有提供配置,则尝试从配置管理器中获取
|
|
|
|
|
config ||= getConfig(name);
|
|
|
|
|
// 如果没有找到配置,则抛出错误
|
|
|
|
|
if (!config) throw new Error(`Couldn't find a configuration with the name '${name}'`);
|
|
|
|
@ -221,6 +289,21 @@ export class Manager implements vscode.TaskProvider, vscode.TerminalLinkProvider
|
|
|
|
|
* @param {vscode.Uri} uri - URI 对象,指定终端的工作目录
|
|
|
|
|
* @returns {Promise<void>} - 当终端创建完成时解析的 Promise
|
|
|
|
|
*/
|
|
|
|
|
/** 流程图
|
|
|
|
|
* @startuml
|
|
|
|
|
* start
|
|
|
|
|
* :导入 createTerminal 模块;
|
|
|
|
|
* :创建连接(如果配置中没有提供连接);
|
|
|
|
|
* :更新连接管理器中的连接信息(pendingUserCount 加 1);
|
|
|
|
|
* :创建伪终端实例;
|
|
|
|
|
* :监听伪终端关闭事件;
|
|
|
|
|
* :更新连接管理器中的连接信息(移除已关闭的伪终端,pendingUserCount 减 1);
|
|
|
|
|
* :创建并显示图形终端;
|
|
|
|
|
* :将伪终端实例与图形终端关联;
|
|
|
|
|
* :显示图形终端;
|
|
|
|
|
* end
|
|
|
|
|
* @enduml
|
|
|
|
|
*/
|
|
|
|
|
public async createTerminal(name: string, config?: FileSystemConfig | Connection, uri?: vscode.Uri): Promise<void> {
|
|
|
|
|
const { createTerminal } = await import('./pseudoTerminal');
|
|
|
|
|
// Create connection (early so we have .actualConfig.root)
|
|
|
|
@ -421,6 +504,24 @@ export class Manager implements vscode.TaskProvider, vscode.TerminalLinkProvider
|
|
|
|
|
* @param {FileSystemConfig} config - 文件系统的配置
|
|
|
|
|
* @returns {Promise<void>} - 当连接完成时解析的 Promise
|
|
|
|
|
*/
|
|
|
|
|
/** 流程图
|
|
|
|
|
* @startuml
|
|
|
|
|
* start
|
|
|
|
|
* :记录接收到的连接命令信息;
|
|
|
|
|
* :获取当前工作区的文件夹;
|
|
|
|
|
* :在工作区文件夹中查找是否已经存在指定名称的 SSH 文件系统;
|
|
|
|
|
* if (已经存在) then (是)
|
|
|
|
|
* :刷新文件资源管理器;
|
|
|
|
|
* :结束;
|
|
|
|
|
* else (否)
|
|
|
|
|
* :获取文件系统的根目录,默认值为 '/';
|
|
|
|
|
* :如果根目录以 '~' 开头,则将其替换为连接的主目录;
|
|
|
|
|
* :如果根目录以 '/' 开头,则去除开头的 '/';
|
|
|
|
|
* :更新工作区文件夹,添加新的 SSH 文件系统;
|
|
|
|
|
* endif
|
|
|
|
|
* stop
|
|
|
|
|
* @enduml
|
|
|
|
|
*/
|
|
|
|
|
public async commandConnect(config: FileSystemConfig) {
|
|
|
|
|
// 记录接收到的连接命令信息
|
|
|
|
|
Logging.info`Command received to connect ${config.name}`;
|
|
|
|
@ -452,6 +553,27 @@ export class Manager implements vscode.TaskProvider, vscode.TerminalLinkProvider
|
|
|
|
|
* @param target - 要断开连接的文件系统的名称或连接对象
|
|
|
|
|
* @returns {Promise<void>} - 当断开连接完成时解析的 Promise
|
|
|
|
|
*/
|
|
|
|
|
/** 流程图
|
|
|
|
|
* @startuml
|
|
|
|
|
* start
|
|
|
|
|
* :记录接收到的断开连接命令信息;
|
|
|
|
|
* :初始化一个数组来存储要断开连接的连接对象;
|
|
|
|
|
* if (目标是一个对象并且包含 'client' 属性) then (是)
|
|
|
|
|
* :将目标连接对象添加到数组中;
|
|
|
|
|
* :获取目标连接对象的实际配置名称;
|
|
|
|
|
* else (否)
|
|
|
|
|
* :获取所有活动连接中名称与目标匹配的连接对象;
|
|
|
|
|
* endif
|
|
|
|
|
* :遍历所有要断开连接的连接对象,调用连接管理器的 closeConnection 方法来关闭它们;
|
|
|
|
|
* :获取所有活动连接中名称与目标相同的其他连接对象;
|
|
|
|
|
* if (没有其他相同名称的文件系统连接) then (是)
|
|
|
|
|
* :直接返回;
|
|
|
|
|
* else (否)
|
|
|
|
|
* :移除所有相关的工作区文件夹;
|
|
|
|
|
* endif
|
|
|
|
|
* stop
|
|
|
|
|
* @enduml
|
|
|
|
|
*/
|
|
|
|
|
public commandDisconnect(target: string | Connection) {
|
|
|
|
|
// 记录接收到的断开连接命令信息
|
|
|
|
|
Logging.info`Command received to disconnect ${commandArgumentToName(target)}`;
|
|
|
|
@ -503,6 +625,24 @@ export class Manager implements vscode.TaskProvider, vscode.TerminalLinkProvider
|
|
|
|
|
* @param uri - 可选的 URI 对象,指定终端的工作目录
|
|
|
|
|
* @returns {Promise<void>} - 当终端创建完成时解析的 Promise
|
|
|
|
|
*/
|
|
|
|
|
/** 流程图
|
|
|
|
|
* @startuml
|
|
|
|
|
* start
|
|
|
|
|
* :记录接收到的连接命令信息;
|
|
|
|
|
* :获取当前工作区的文件夹;
|
|
|
|
|
* :在工作区文件夹中查找是否已经存在指定名称的 SSH 文件系统;
|
|
|
|
|
* if (已经存在) then (是)
|
|
|
|
|
* :刷新文件资源管理器;
|
|
|
|
|
* :结束;
|
|
|
|
|
* else (否)
|
|
|
|
|
* :获取文件系统的根目录,默认值为 '/';
|
|
|
|
|
* :如果根目录以 '~' 开头,则将其替换为连接的主目录;
|
|
|
|
|
* :如果根目录以 '/' 开头,则去除开头的 '/';
|
|
|
|
|
* :更新工作区文件夹,添加新的 SSH 文件系统;
|
|
|
|
|
* endif
|
|
|
|
|
* stop
|
|
|
|
|
* @enduml
|
|
|
|
|
*/
|
|
|
|
|
public async commandTerminal(target: FileSystemConfig | Connection, uri?: vscode.Uri) {
|
|
|
|
|
// 记录接收到的打开终端命令信息
|
|
|
|
|
Logging.info`Command received to open a terminal for ${commandArgumentToName(target)}${uri ? ` in ${uri}` : ''}`;
|
|
|
|
@ -527,6 +667,35 @@ export class Manager implements vscode.TaskProvider, vscode.TerminalLinkProvider
|
|
|
|
|
* @param target - 要配置的文件系统的名称或配置对象
|
|
|
|
|
* @returns {Promise<void>} - 当配置完成时解析的 Promise
|
|
|
|
|
*/
|
|
|
|
|
/** 流程图
|
|
|
|
|
* @startuml
|
|
|
|
|
* start
|
|
|
|
|
* :记录接收到的配置命令信息;
|
|
|
|
|
* if (目标是一个对象) then (是)
|
|
|
|
|
* :检查对象是否有 _location 或 _locations 属性;
|
|
|
|
|
* if (没有) then (是)
|
|
|
|
|
* :显示错误信息;
|
|
|
|
|
* stop
|
|
|
|
|
* else (否)
|
|
|
|
|
* :打开设置界面,导航到编辑配置页面;
|
|
|
|
|
* stop
|
|
|
|
|
* endif
|
|
|
|
|
* else (否)
|
|
|
|
|
* :将目标字符串转换为小写;
|
|
|
|
|
* :加载所有配置;
|
|
|
|
|
* :过滤出名称与目标匹配的配置;
|
|
|
|
|
* if (没有找到匹配的配置) then (是)
|
|
|
|
|
* :显示错误信息;
|
|
|
|
|
* :记录错误信息;
|
|
|
|
|
* :结束;
|
|
|
|
|
* else (否)
|
|
|
|
|
* :如果只有一个匹配的配置,直接使用它;
|
|
|
|
|
* :打开设置界面,导航到编辑配置页面;
|
|
|
|
|
* endif
|
|
|
|
|
* endif
|
|
|
|
|
* stop
|
|
|
|
|
* @enduml
|
|
|
|
|
*/
|
|
|
|
|
public async commandConfigure(target: string | FileSystemConfig) {
|
|
|
|
|
// 记录接收到的配置命令信息
|
|
|
|
|
Logging.info`Command received to configure ${typeof target === 'string' ? target : target.name}`;
|
|
|
|
|