diff --git a/src/config.ts b/src/config.ts index 4150c2f..2144009 100644 --- a/src/config.ts +++ b/src/config.ts @@ -11,7 +11,36 @@ export function invalidConfigName(name: string) { return `A SSH FS name can only exists of lowercase alphanumeric characters, slashes and any of these: _.+-@`; } -export function loadConfigs() { +function randomAvailableName(index = 0): [string, number] { + let name = index ? `unnamed${index}` : 'unnamed'; + while (loadConfigs(true).find(c => c.name === name)) { + index += 1; + name = `unnamed${index}`; + } + return [name, index + 1]; +} + +export async function renameNameless() { + const conf = vscode.workspace.getConfiguration('sshfs'); + const inspect = conf.inspect('configs')!; + let randomIndex = 0; + const patch = (v?: FileSystemConfig[]) => { + if (v) { + v.forEach((config) => { + if (!config.name) { + [config.name, randomIndex] = randomAvailableName(randomIndex); + Logging.warning(`Renamed unnamed config to ${config.name}`); + } + }); + } + return v; + }; + await conf.update('configs', patch(inspect.globalValue), vscode.ConfigurationTarget.Global).then(() => { }, () => { }); + await conf.update('configs', patch(inspect.workspaceValue), vscode.ConfigurationTarget.Workspace).then(() => { }, () => { }); + await conf.update('configs', patch(inspect.workspaceFolderValue), vscode.ConfigurationTarget.WorkspaceFolder).then(() => { }, () => { }); +} + +export function loadConfigs(raw = false) { const config = vscode.workspace.getConfiguration('sshfs'); if (!config) return []; const inspect = config.inspect('configs')!; @@ -20,23 +49,25 @@ export function loadConfigs() { ...(inspect.workspaceValue || []), ...(inspect.globalValue || []), ]; - configs.forEach(c => c.name = c.name.toLowerCase()); + configs.forEach(c => c.name = (c.name || '').toLowerCase()); configs = configs.filter((c, i) => configs.findIndex(c2 => c2.name === c.name) === i); - for (const index in configs) { - if (!configs[index].name) { - Logging.error(`Skipped an invalid SSH FS config (missing a name field):\n${JSON.stringify(configs[index], undefined, 4)}`); + if (raw) return configs; + renameNameless(); + for (const conf of configs) { + if (!conf.name) { + Logging.error(`Skipped an invalid SSH FS config (missing a name field):\n${JSON.stringify(conf, undefined, 4)}`); vscode.window.showErrorMessage(`Skipped an invalid SSH FS config (missing a name field)`); - } else if (invalidConfigName(configs[index].name)) { - const conf = configs[index]; + } else if (invalidConfigName(conf.name)) { if (skippedConfigNames.indexOf(conf.name) !== -1) continue; Logging.error(`Found a SSH FS config with the invalid name "${conf.name}", prompting user how to handle`); vscode.window.showErrorMessage(`Invalid SSH FS config name: ${conf.name}`, 'Rename', 'Delete', 'Skip').then(async (answer) => { if (answer === 'Rename') { const name = await vscode.window.showInputBox({ prompt: `New name for: ${conf.name}`, validateInput: invalidConfigName, placeHolder: 'New name' }); if (name) { - Logging.info(`Renaming config "${conf.name}" to "${name}"`); + const oldName = conf.name; + Logging.info(`Renaming config "${oldName}" to "${name}"`); conf.name = name; - return updateConfig(conf.name, conf); + return updateConfig(oldName, conf); } } else if (answer === 'Delete') { return updateConfig(conf.name); @@ -69,7 +100,7 @@ export async function updateConfig(name: string, config?: FileSystemConfig) { // const contains = (v?: FileSystemConfig[]) => v && v.find(c => c.name === name); const patch = (v: FileSystemConfig[]) => { const con = v.findIndex(c => c.name === name); - if (!config) return v.filter(c => c.name.toLowerCase() !== name); + if (!config) return v.filter(c => !c.name || c.name.toLowerCase() !== name); v[con === -1 ? v.length : con] = config; return v; }; diff --git a/src/extension.ts b/src/extension.ts index 57aeb41..c4dc949 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,10 +1,11 @@ import * as vscode from 'vscode'; -import { invalidConfigName, loadConfigs } from './config'; +import { invalidConfigName, loadConfigs, renameNameless } from './config'; import * as Logging from './logging'; import { Manager } from './manager'; async function pickConfig(manager: Manager, activeOrNot?: boolean) { + await renameNameless(); let names = manager.getActive(); const others = loadConfigs(); if (activeOrNot === false) { @@ -37,6 +38,7 @@ export function activate(context: vscode.ExtensionContext) { } registerCommand('sshfs.new', async () => { + await renameNameless(); const name = await vscode.window.showInputBox({ placeHolder: 'Name for the new SSH file system', validateInput: invalidConfigName }); if (name) vscode.window.showTextDocument(vscode.Uri.parse(`ssh:///${name}.sshfs.jsonc`), { preview: false }); });