diff --git a/package.json b/package.json index 7b9986c..675e36b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "code-sync", "displayName": "CodeSync", "description": "Sync VSCode extensions using your favorite file synchronization service (OneDrive, Dropbox, Google Drive, etc.)", - "version": "2.6.2", + "version": "2.7.0", "publisher": "golf1052", "keywords": [ "sync", @@ -157,6 +157,16 @@ "category": "CodeSync", "command": "codeSync.toggleStatusBar", "title": "Toggle status bar icon" + }, + { + "category": "CodeSync", + "command": "codeSync.setCodeExecutableName", + "title": "Set VSCode executable name" + }, + { + "category": "CodeSync", + "command": "codeSync.setCodeSettingsPath", + "title": "Set VSCode settings path" } ] }, diff --git a/src/cs.ts b/src/cs.ts index 499845c..32ae2f6 100644 --- a/src/cs.ts +++ b/src/cs.ts @@ -18,7 +18,7 @@ export const KEYBINDINGS = 'keybindings.json'; export const SNIPPETS = 'snippets'; export const LOCAL_SETTINGS = 'local-settings.json'; -export const currentVersion: string = '2.6.2'; +export const currentVersion: string = '2.7.0'; export let vsCodeExtensionDir: string = helpers.getExtensionDir(); export let codeSyncExtensionDir: string = path.join(vsCodeExtensionDir, 'golf1052.code-sync-' + currentVersion); @@ -110,7 +110,9 @@ export class CodeSync { excluded: { installed: [], external: [] - } + }, + executableName: '', + settingsPath: '' }; this.Settings.Settings = tmpSettings; this.Settings.save(); @@ -159,14 +161,14 @@ export class CodeSync { startFileWatcher = () => { let files: any = {}; - if (fs.existsSync(helpers.getUserSettingsFilePath())) { - files[helpers.getUserSettingsFilePath()] = this.exportSettings.bind(this); + if (fs.existsSync(helpers.getUserSettingsFilePath(this.Settings.Settings))) { + files[helpers.getUserSettingsFilePath(this.Settings.Settings)] = this.exportSettings.bind(this); } - if (fs.existsSync(helpers.getKeybindingsFilePath())) { - files[helpers.getKeybindingsFilePath()] = this.exportKeybindings.bind(this); + if (fs.existsSync(helpers.getKeybindingsFilePath(this.Settings.Settings))) { + files[helpers.getKeybindingsFilePath(this.Settings.Settings)] = this.exportKeybindings.bind(this); } - if (fs.existsSync(helpers.getSnippetsFolderPath())) { - files[helpers.getSnippetsFolderPath()] = this.exportSnippets.bind(this); + if (fs.existsSync(helpers.getSnippetsFolderPath(this.Settings.Settings))) { + files[helpers.getSnippetsFolderPath(this.Settings.Settings)] = this.exportSnippets.bind(this); } this.fileWatcher = new FileWatcher(files, this.Settings); } @@ -204,8 +206,10 @@ export class CodeSync { return; } if (helpers.isFileEmpty(settingsPath) == false && - helpers.isFileContentEmpty(settingsPath) == false) { - this.localSettingsManager.import(settingsPath, helpers.getUserSettingsFilePath()); + helpers.isFileContentEmpty(settingsPath) == false) { + const userSettingsFilePath = helpers.getUserSettingsFilePath(this.Settings.Settings); + this.logger.appendLine(`Importing settings to ${userSettingsFilePath}`); + this.localSettingsManager.import(settingsPath, userSettingsFilePath); } this.statusBar.reset(); this.logger.appendLine('Finished importing settings.'); @@ -216,13 +220,13 @@ export class CodeSync { if (this.Settings.Settings.importSettings) { this.logger.appendLine('Exporting settings.'); this.startSync('Exporting settings'); - let settingsPath: string = helpers.getUserSettingsFilePath(); + let settingsPath: string = helpers.getUserSettingsFilePath(this.Settings.Settings); if (!fs.existsSync(settingsPath)) { this.logger.appendLine(`Could not find settings path at ${settingsPath}. Giving up.`); this.statusBar.reset(); return; } - this.localSettingsManager.export(helpers.getUserSettingsFilePath(), path.join(this.codeSyncDir, SETTINGS)); + this.localSettingsManager.export(settingsPath, path.join(this.codeSyncDir, SETTINGS)); this.statusBar.reset(); this.logger.appendLine('Finished exporting settings.'); } @@ -239,8 +243,10 @@ export class CodeSync { return; } if (helpers.isFileEmpty(keybindingsPath) == false && - helpers.isFileContentEmpty(keybindingsPath) == false) { - await helpers.copy(keybindingsPath, helpers.getKeybindingsFilePath()); + helpers.isFileContentEmpty(keybindingsPath) == false) { + const keybindingsFilePath = helpers.getKeybindingsFilePath(this.Settings.Settings) + this.logger.appendLine(`Importing keybindings to ${keybindingsFilePath}`); + await helpers.copy(keybindingsPath, keybindingsFilePath); } this.statusBar.reset(); this.logger.appendLine('Finished importing keybindings.'); @@ -250,10 +256,13 @@ export class CodeSync { async exportKeybindings() { if (this.Settings.Settings.importKeybindings) { this.startSync('Exporting keybindings'); - if (!fs.existsSync(helpers.getKeybindingsFilePath())) { + let keybindingsPath = helpers.getKeybindingsFilePath(this.Settings.Settings); + if (!fs.existsSync(keybindingsPath)) { + this.logger.appendLine(`Could not find keybindings path at ${keybindingsPath}. Giving up.`); + this.statusBar.reset(); return; } - await helpers.copy(helpers.getKeybindingsFilePath(), path.join(this.codeSyncDir, KEYBINDINGS)); + await helpers.copy(keybindingsPath, path.join(this.codeSyncDir, KEYBINDINGS)); this.statusBar.reset(); } } @@ -273,7 +282,7 @@ export class CodeSync { let s = snippetFiles[i];if (fs.lstatSync(path.join(snippetsDirectory, s)).isFile()) { if (helpers.isFileEmpty(path.join(snippetsDirectory, s)) == false && helpers.isFileContentEmpty(path.join(snippetsDirectory, s)) == false) { - await helpers.copy(path.join(snippetsDirectory, s), path.join(helpers.getSnippetsFolderPath(), s)); + await helpers.copy(path.join(snippetsDirectory, s), path.join(helpers.getSnippetsFolderPath(this.Settings.Settings), s)); } } } @@ -285,10 +294,13 @@ export class CodeSync { async exportSnippets() { if (this.Settings.Settings.importSnippets) { this.startSync('Exporting snippets'); - if (!fs.existsSync(helpers.getSnippetsFolderPath())) { + const snippetsFolderPath = helpers.getSnippetsFolderPath(this.Settings.Settings); + if (!fs.existsSync(snippetsFolderPath)) { + this.logger.appendLine(`Could not find snippets path at ${snippetsFolderPath}. Giving up.`); + this.statusBar.reset(); return; } - await helpers.copy(helpers.getSnippetsFolderPath(), path.join(this.codeSyncDir, SNIPPETS)); + await helpers.copy(snippetsFolderPath, path.join(this.codeSyncDir, SNIPPETS)); this.statusBar.reset(); } } @@ -303,7 +315,7 @@ export class CodeSync { let installedAny: boolean = false; extensions.forEach(e => { if (installedExtensions.filter(i => i.id == e).length == 0) { - let val = helpers.installExtension(e); + let val = helpers.installExtension(e, this.Settings.Settings); if (val) { installedAny = true; } @@ -518,6 +530,68 @@ export class CodeSync { } } + async setCodeExecutableName(): Promise { + let executableName: string = ''; + executableName = await vscode.window.showInputBox({ + prompt: 'Enter the VSCode executable name. NOTE: Do not include the file extension (.exe, .sh, etc.)', + placeHolder: 'code' + }); + + if (executableName == undefined) { + return; + } else { + vscode.window.showInformationMessage('Testing user defined VSCode executable name...'); + let oldExecutableName; + if (this.Settings.Settings.executableName) { + oldExecutableName = this.Settings.Settings.executableName; + } else { + oldExecutableName = ''; + } + let csSettings = this.Settings.Settings; + csSettings.executableName = executableName; + this.Settings.Settings = csSettings; + this.Settings.save(); + + if (helpers.isCodeOnPath(this.Settings.Settings)) { + vscode.window.showInformationMessage(`Test succeeded. Will now use ${executableName} as VSCode executable name.`); + } else { + csSettings.executableName = oldExecutableName; + this.Settings.Settings = csSettings; + this.Settings.save(); + vscode.window.showInformationMessage('Test failed. Reverting back to old VSCode executable name.'); + } + } + } + + async setCodeSettingsPath(): Promise { + let settingsPath: string = ''; + settingsPath = await vscode.window.showInputBox({ + prompt: 'Enter the VSCode user settings path. This must be an absolute path.', + placeHolder: helpers.getDefaultCodeSettingsFolderPath() + }); + + if (settingsPath == undefined) { + return; + } else { + vscode.window.showInformationMessage('Testing user defined VSCode user settings path...'); + const oldSettingsPath = this.Settings.Settings.settingsPath; + this.Settings.Settings.settingsPath = settingsPath; + this.Settings.save(); + + if (!settingsPath) { + settingsPath = helpers.getDefaultCodeSettingsFolderPath(); + } + + if (fs.existsSync(settingsPath)) { + vscode.window.showInformationMessage(`Test succeeded. Will now use ${settingsPath} as VSCode user settings path.`); + } else { + this.Settings.Settings.settingsPath = oldSettingsPath; + this.Settings.save(); + vscode.window.showInformationMessage('Test failed. Reverting back to old VSCode user settings path.'); + } + } + } + private startSync(text: string) { this.statusBar.StatusBarText = text; this.statusBar.setSync(); diff --git a/src/extension.ts b/src/extension.ts index fc0dde4..7ac656b 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -10,8 +10,8 @@ var codeSync: cs.CodeSync; export async function activate(context: vscode.ExtensionContext) { logger = new Logger('extension'); codeSync = new cs.CodeSync(cs.vsCodeExtensionDir, cs.codeSyncExtensionDir, ''); - helpers.isCodeASnapPackage(true); - codeSync.CanManageExtensions = helpers.isCodeOnPath(); + helpers.isCodeASnapPackage(codeSync.Settings.Settings, true); + codeSync.CanManageExtensions = helpers.isCodeOnPath(codeSync.Settings.Settings); if (!codeSync.CanManageExtensions) { await vscode.window.showWarningMessage(helpers.getCodePathWarningMessage()); } @@ -115,6 +115,12 @@ export async function activate(context: vscode.ExtensionContext) { let toggleStatusBarDisposable = vscode.commands.registerCommand('codeSync.toggleStatusBar', function() { codeSync.toggleStatusBarIcon(); }); + const setCodeExecutableName = vscode.commands.registerCommand('codeSync.setCodeExecutableName', async function() { + await codeSync.setCodeExecutableName(); + }); + const setCodeSettingsPath = vscode.commands.registerCommand('codeSync.setCodeSettingsPath', async function() { + await codeSync.setCodeSettingsPath(); + }); context.subscriptions.push( importAllDisposable, @@ -140,7 +146,9 @@ export async function activate(context: vscode.ExtensionContext) { toggleImportSnippetsDisposable, toggleImportExtensionsDisposable, setSyncPathDisposable, - toggleStatusBarDisposable + toggleStatusBarDisposable, + setCodeExecutableName, + setCodeSettingsPath ); } diff --git a/src/file-watcher.ts b/src/file-watcher.ts index dca3221..7c3f02b 100644 --- a/src/file-watcher.ts +++ b/src/file-watcher.ts @@ -3,13 +3,16 @@ import * as chokidar from 'chokidar'; import * as fs from 'fs'; import * as helpers from './helpers'; import * as settings from './settings'; +import { Logger } from './logger'; export class FileWatcher { private watchers: chokidar.FSWatcher[]; private files: any; private codeSyncSettings: settings.CodeSyncSettings; + private logger: Logger; constructor(files: any, codeSyncSettings: settings.CodeSyncSettings) { + this.logger = new Logger('file-watcher'); this.watchers = []; this.files = files; this.codeSyncSettings = codeSyncSettings; @@ -31,11 +34,12 @@ export class FileWatcher { change = (path: string, stats: fs.Stats) => { if (this.codeSyncSettings.Settings.autoExport) { + this.logger.appendLine(`Detected file change at ${path}, syncing...`); if (this.files[path]) { this.files[path](); } - else if (path.includes(helpers.getSnippetsFolderPath())) { - this.files[helpers.getSnippetsFolderPath()](); + else if (path.includes(helpers.getSnippetsFolderPath(this.codeSyncSettings.Settings))) { + this.files[helpers.getSnippetsFolderPath(this.codeSyncSettings.Settings)](); } } } diff --git a/src/helpers.ts b/src/helpers.ts index be48591..4dbf296 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -6,6 +6,7 @@ import * as fs from 'fs'; import * as child_process from 'child_process'; import * as process from 'process'; import * as cs from './cs'; +import * as settings from './settings'; var recursive_copy = require('recursive-copy'); var mkdirp = require('mkdirp'); import * as json from 'comment-json'; @@ -48,7 +49,15 @@ export function getExtensionDir(): string { } } -function getCodeSettingsFolderPath(): string { +function getCodeSettingsFolderPath(settings: settings.Settings): string { + if (settings.settingsPath) { + logger.appendLine(`Using user defined settings path: ${settings.settingsPath}`); + return settings.settingsPath; + } + return getDefaultCodeSettingsFolderPath(); +} + +export function getDefaultCodeSettingsFolderPath(): string { let codeString = 'Code'; if (isInsiders()) { codeString = 'Code - Insiders' @@ -63,20 +72,21 @@ function getCodeSettingsFolderPath(): string { return path.join(os.homedir(), `.config/${codeString}/User/`); } else { + logger.appendLine('Unknown OS type, retur'); return ''; } } -export function getUserSettingsFilePath(): string { - return path.join(getCodeSettingsFolderPath(), cs.SETTINGS); +export function getUserSettingsFilePath(settings: settings.Settings): string { + return path.join(getCodeSettingsFolderPath(settings), cs.SETTINGS); } -export function getKeybindingsFilePath(): string { - return path.join(getCodeSettingsFolderPath(), cs.KEYBINDINGS); +export function getKeybindingsFilePath(settings: settings.Settings): string { + return path.join(getCodeSettingsFolderPath(settings), cs.KEYBINDINGS); } -export function getSnippetsFolderPath(): string { - return path.join(getCodeSettingsFolderPath(), cs.SNIPPETS + '/'); +export function getSnippetsFolderPath(settings: settings.Settings): string { + return path.join(getCodeSettingsFolderPath(settings), cs.SNIPPETS + '/'); } export async function copy(src: string, dest: string) { @@ -93,11 +103,11 @@ export function getDir(path: string): string { // returns false if the extension was already installed // returns true otherwise... -export function installExtension(name: string): boolean { +export function installExtension(name: string, settings: settings.Settings): boolean { logger.appendLine(`Installing extension: ${name}...`); let options: child_process.ExecSyncOptions = {}; options.encoding = 'utf8'; - let command: string = getCodeCommand() + ' --install-extension '; + let command: string = getCodeCommand(settings) + ' --install-extension '; command += name; let out: Buffer = new Buffer(''); try { @@ -121,9 +131,9 @@ export function installExtension(name: string): boolean { } } -export function isCodeOnPath(): boolean { +export function isCodeOnPath(settings: settings.Settings): boolean { let version: string = ''; - let command = getCodeCommand() + ' --version'; + let command = getCodeCommand(settings) + ' --version'; try { version = child_process.execSync(command, {encoding: 'utf8'}); } @@ -149,7 +159,11 @@ export function logError(err: Error): void { logger.appendLine(`\tStacktrace: ${err.stack}`); } -function getCodeString(): string { +function getCodeString(settings: settings.Settings): string { + if (settings.executableName) { + logger.appendLine(`Using user defined executable name: ${settings.executableName}`); + return settings.executableName; + } let codeString: string = 'code'; if (isInsiders()) { codeString = 'code-insiders'; @@ -162,8 +176,8 @@ interface SnapPackageResult { path: string } -export function isCodeASnapPackage(log: boolean = false): SnapPackageResult { - let codeString = getCodeString(); +export function isCodeASnapPackage(settings: settings.Settings, log: boolean = false): SnapPackageResult { + let codeString = getCodeString(settings); if (linux) { const env = process.env; @@ -186,15 +200,15 @@ export function isCodeASnapPackage(log: boolean = false): SnapPackageResult { } } -function getCodeCommand(): string { - let codeString = getCodeString(); +function getCodeCommand(settings: settings.Settings): string { + let codeString = getCodeString(settings); if (windows) { return `${codeString}.cmd`; } else if (osx) { return codeString; } else if (linux) { - let result = isCodeASnapPackage(); + let result = isCodeASnapPackage(settings); if (result.value) { return result.path; } else { diff --git a/src/settings.ts b/src/settings.ts index e51d73b..5bbd6c0 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -17,6 +17,8 @@ export interface Settings { importExtensions: boolean; showStatusBarIcon: boolean; excluded: ExcludedPackages; + executableName: string; + settingsPath: string; } interface ExcludedPackages {