提交 272a2882 编写于 作者: B Benjamin Pasero

wire in support for opening workspace config from the main side

上级 ef50310e
......@@ -264,6 +264,10 @@ export class CodeWindow implements ICodeWindow {
return this.currentConfig ? this.currentConfig.backupPath : void 0;
}
public get openedWorkspaceConfigPath(): string {
return this.currentConfig ? this.currentConfig.workspaceConfigPath : void 0;
}
public get openedFolderPath(): string {
return this.currentConfig ? this.currentConfig.folderPath : void 0;
}
......
......@@ -20,7 +20,7 @@ import { ILifecycleService, UnloadReason } from 'vs/platform/lifecycle/electron-
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService } from 'vs/platform/log/common/log';
import { IWindowSettings, OpenContext, IPath, IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnFolder } from 'vs/code/node/windowsFinder';
import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnFolder, findWindowOnWorkspace } from 'vs/code/node/windowsFinder';
import CommonEvent, { Emitter } from 'vs/base/common/event';
import product from 'vs/platform/node/product';
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
......@@ -29,6 +29,7 @@ import { IWindowsMainService, IOpenConfiguration } from "vs/platform/windows/ele
import { IHistoryMainService } from "vs/platform/history/electron-main/historyMainService";
import { IProcessEnvironment, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
import { TPromise } from "vs/base/common/winjs.base";
import { isParent } from "vs/platform/files/common/files";
enum WindowError {
UNRESPONSIVE,
......@@ -64,6 +65,8 @@ type RestoreWindowsSetting = 'all' | 'folders' | 'one' | 'none';
interface IOpenBrowserWindowOptions {
userEnv?: IProcessEnvironment;
cli?: ParsedArgs;
workspaceConfigPath?: string;
folderPath?: string;
initialStartup?: boolean;
......@@ -80,6 +83,9 @@ interface IOpenBrowserWindowOptions {
interface IWindowToOpen extends IPath {
// the workspace config path for a Code instance to open
workspaceConfigPath?: string;
// the folder path for a Code instance to open
folderPath?: string;
......@@ -279,11 +285,6 @@ export class WindowsManager implements IWindowsMainService {
public open(openConfig: IOpenConfiguration): CodeWindow[] {
const windowsToOpen = this.getWindowsToOpen(openConfig);
//
// These are windows to open to show either folders or files (including diffing files or creating them)
//
const foldersToOpen = arrays.distinct(windowsToOpen.filter(win => win.folderPath && !win.filePath).map(win => win.folderPath), folder => isLinux ? folder : folder.toLowerCase()); // prevent duplicates
let filesToOpen = windowsToOpen.filter(path => !!path.filePath && !path.createFilePath);
let filesToCreate = windowsToOpen.filter(path => !!path.filePath && path.createFilePath);
let filesToDiff: IPath[];
......@@ -295,22 +296,33 @@ export class WindowsManager implements IWindowsMainService {
filesToDiff = [];
}
//
// These are windows to open to show workspaces
//
const workspacesToOpen = arrays.distinct(windowsToOpen.filter(win => !!win.workspaceConfigPath).map(win => win.workspaceConfigPath), workspaceConfigPath => isLinux ? workspaceConfigPath : workspaceConfigPath.toLowerCase()); // prevent duplicates
//
// These are windows to open to show either folders or files (including diffing files or creating them)
//
const foldersToOpen = arrays.distinct(windowsToOpen.filter(win => win.folderPath && !win.filePath).map(win => win.folderPath), folder => isLinux ? folder : folder.toLowerCase()); // prevent duplicates
//
// These are windows to restore because of hot-exit or empty windows from previous session
//
const hotExitRestore = (openConfig.initialStartup && !openConfig.cli.extensionDevelopmentPath);
const foldersToRestore = hotExitRestore ? this.backupService.getWorkspaceBackupPaths() : [];
const foldersToRestore = hotExitRestore ? this.backupService.getFolderBackupPaths() : [];
const workspacesToRestore = hotExitRestore ? this.backupService.getWorkspaceBackupPaths() : [];
let emptyToRestore = hotExitRestore ? this.backupService.getEmptyWindowBackupPaths() : [];
emptyToRestore.push(...windowsToOpen.filter(w => !w.folderPath && w.backupPath).map(w => path.basename(w.backupPath))); // add empty windows with backupPath
emptyToRestore.push(...windowsToOpen.filter(w => !w.workspaceConfigPath && !w.folderPath && w.backupPath).map(w => path.basename(w.backupPath))); // add empty windows with backupPath
emptyToRestore = arrays.distinct(emptyToRestore); // prevent duplicates
//
// These are empty windows to open
//
const emptyToOpen = windowsToOpen.filter(win => !win.folderPath && !win.filePath && !win.backupPath).length;
const emptyToOpen = windowsToOpen.filter(win => !win.workspaceConfigPath && !win.folderPath && !win.filePath && !win.backupPath).length;
// Open based on config
const usedWindows = this.doOpen(openConfig, foldersToOpen, foldersToRestore, emptyToRestore, emptyToOpen, filesToOpen, filesToCreate, filesToDiff);
const usedWindows = this.doOpen(openConfig, workspacesToOpen, workspacesToRestore, foldersToOpen, foldersToRestore, emptyToRestore, emptyToOpen, filesToOpen, filesToCreate, filesToDiff);
// Make sure the last active window gets focus if we opened multiple
if (usedWindows.length > 1 && this.windowsState.lastActiveWindow) {
......@@ -353,6 +365,8 @@ export class WindowsManager implements IWindowsMainService {
private doOpen(
openConfig: IOpenConfiguration,
workspacesToOpen: string[],
workspacesToRestore: string[],
foldersToOpen: string[],
foldersToRestore: string[],
emptyToRestore: string[],
......@@ -410,22 +424,55 @@ export class WindowsManager implements IWindowsMainService {
}
}
// Handle workspaces to open (instructed and to restore)
const allWorkspacesToOpen = arrays.distinct([...workspacesToOpen, ...workspacesToRestore], workspace => isLinux ? workspace : workspace.toLowerCase()); // prevent duplicates
if (allWorkspacesToOpen.length > 0) {
// Check for existing instances
const windowsOnWorkspace = arrays.coalesce(allWorkspacesToOpen.map(workspaceToOpen => findWindowOnWorkspace(WindowsManager.WINDOWS, workspaceToOpen)));
if (windowsOnWorkspace.length > 0) {
const windowOnWorkspace = windowsOnWorkspace[0];
// Do open files
this.doOpenFilesInExistingWindow(windowOnWorkspace, filesToOpen, filesToCreate, filesToDiff);
// Reset these because we handled them
filesToOpen = [];
filesToCreate = [];
filesToDiff = [];
openFolderInNewWindow = true; // any other folders to open must open in new window then
}
// Open remaining ones
allWorkspacesToOpen.forEach(workspaceToOpen => {
if (windowsOnWorkspace.some(win => isEqual(win.openedWorkspaceConfigPath, workspaceToOpen, !isLinux /* ignorecase */))) {
return; // ignore folders that are already open
}
// Do open folder
usedWindows.push(this.doOpenFolderOrWorkspace(openConfig, { workspaceConfigPath: workspaceToOpen }, openFolderInNewWindow, filesToOpen, filesToCreate, filesToDiff));
// Reset these because we handled them
filesToOpen = [];
filesToCreate = [];
filesToDiff = [];
openFolderInNewWindow = true; // any other folders to open must open in new window then
});
}
// Handle folders to open (instructed and to restore)
let allFoldersToOpen = arrays.distinct([...foldersToOpen, ...foldersToRestore], folder => isLinux ? folder : folder.toLowerCase()); // prevent duplicates
const allFoldersToOpen = arrays.distinct([...foldersToOpen, ...foldersToRestore], folder => isLinux ? folder : folder.toLowerCase()); // prevent duplicates
if (allFoldersToOpen.length > 0) {
// Check for existing instances
const windowsOnFolderPath = arrays.coalesce(allFoldersToOpen.map(folderToOpen => findWindowOnFolder(WindowsManager.WINDOWS, folderToOpen)));
if (windowsOnFolderPath.length > 0) {
const browserWindow = windowsOnFolderPath[0];
browserWindow.focus(); // just focus one of them
const files = { filesToOpen, filesToCreate, filesToDiff }; // copy to object because they get reset shortly after
browserWindow.ready().then(readyWindow => {
readyWindow.send('vscode:openFiles', files);
});
const windowOnFolderPath = windowsOnFolderPath[0];
usedWindows.push(browserWindow);
// Do open files
this.doOpenFilesInExistingWindow(windowOnFolderPath, filesToOpen, filesToCreate, filesToDiff);
// Reset these because we handled them
filesToOpen = [];
......@@ -441,18 +488,8 @@ export class WindowsManager implements IWindowsMainService {
return; // ignore folders that are already open
}
const browserWindow = this.openInBrowserWindow({
userEnv: openConfig.userEnv,
cli: openConfig.cli,
initialStartup: openConfig.initialStartup,
folderPath: folderToOpen,
filesToOpen,
filesToCreate,
filesToDiff,
forceNewWindow: openFolderInNewWindow,
windowToUse: openFolderInNewWindow ? void 0 : openConfig.windowToUse as CodeWindow
});
usedWindows.push(browserWindow);
// Do open folder
usedWindows.push(this.doOpenFolderOrWorkspace(openConfig, { folderPath: folderToOpen }, openFolderInNewWindow, filesToOpen, filesToCreate, filesToDiff));
// Reset these because we handled them
filesToOpen = [];
......@@ -506,6 +543,31 @@ export class WindowsManager implements IWindowsMainService {
return arrays.distinct(usedWindows);
}
private doOpenFilesInExistingWindow(window: CodeWindow, filesToOpen: IPath[], filesToCreate: IPath[], filesToDiff: IPath[]): void {
window.focus(); // make sure window has focus
window.ready().then(readyWindow => {
readyWindow.send('vscode:openFiles', { filesToOpen, filesToCreate, filesToDiff });
});
}
private doOpenFolderOrWorkspace(openConfig: IOpenConfiguration, folderOrWorkspace: IWindowToOpen, openInNewWindow: boolean, filesToOpen: IPath[], filesToCreate: IPath[], filesToDiff: IPath[]): CodeWindow {
const browserWindow = this.openInBrowserWindow({
userEnv: openConfig.userEnv,
cli: openConfig.cli,
initialStartup: openConfig.initialStartup,
workspaceConfigPath: folderOrWorkspace.workspaceConfigPath,
folderPath: folderOrWorkspace.folderPath,
filesToOpen,
filesToCreate,
filesToDiff,
forceNewWindow: openInNewWindow,
windowToUse: openInNewWindow ? void 0 : openConfig.windowToUse as CodeWindow
});
return browserWindow;
}
private getWindowsToOpen(openConfig: IOpenConfiguration): IWindowToOpen[] {
let windowsToOpen: IWindowToOpen[];
......@@ -676,10 +738,12 @@ export class WindowsManager implements IWindowsMainService {
const candidateStat = fs.statSync(candidate);
if (candidateStat) {
// File
// File / Workspace
if (candidateStat.isFile()) {
const isWorkspaceConfig = isParent(candidate, this.environmentService.workspacesHome);
return {
filePath: candidate,
workspaceConfigPath: isWorkspaceConfig ? candidate : void 0,
filePath: !isWorkspaceConfig ? candidate : void 0,
lineNumber: gotoLineMode ? parsedPath.line : void 0,
columnNumber: gotoLineMode ? parsedPath.column : void 0
};
......@@ -771,6 +835,7 @@ export class WindowsManager implements IWindowsMainService {
configuration.execPath = process.execPath;
configuration.userEnv = assign({}, this.initialUserEnv, options.userEnv || {});
configuration.isInitialStartup = options.initialStartup;
configuration.workspaceConfigPath = options.workspaceConfigPath;
configuration.folderPath = options.folderPath;
configuration.filesToOpen = options.filesToOpen;
configuration.filesToCreate = options.filesToCreate;
......@@ -859,7 +924,9 @@ export class WindowsManager implements IWindowsMainService {
// Register window for backups
if (!configuration.extensionDevelopmentPath) {
if (configuration.folderPath) {
if (configuration.workspaceConfigPath) {
configuration.backupPath = this.backupService.registerWorkspaceBackupSync(configuration.workspaceConfigPath);
} else if (configuration.folderPath) {
configuration.backupPath = this.backupService.registerFolderBackupSync(configuration.folderPath);
} else {
configuration.backupPath = this.backupService.registerEmptyWindowBackupSync(options.emptyWindowBackupFolder);
......
......@@ -12,7 +12,8 @@ import * as paths from 'vs/base/common/paths';
import { OpenContext } from 'vs/platform/windows/common/windows';
export interface ISimpleWindow {
openedFolderPath: string;
openedWorkspaceConfigPath?: string;
openedFolderPath?: string;
openedFilePath?: string;
extensionDevelopmentPath?: string;
lastFocusTime: number;
......@@ -107,20 +108,30 @@ export function getLastActiveWindow<W extends ISimpleWindow>(windows: W[]): W {
export function findWindowOnFolder<W extends ISimpleWindow>(windows: W[], folderPath: string): W {
if (windows.length) {
const res = windows.filter(w => {
// match on folder
if (typeof w.openedFolderPath === 'string' && (paths.isEqual(w.openedFolderPath, folderPath, !platform.isLinux /* ignorecase */))) {
return true;
}
// Sort the last active window to the front of the array of windows to test
const windowsToTest = windows.slice(0);
const lastActiveWindow = getLastActiveWindow(windows);
if (lastActiveWindow) {
windowsToTest.splice(windowsToTest.indexOf(lastActiveWindow), 1);
windowsToTest.unshift(lastActiveWindow);
return false;
});
if (res && res.length) {
return res[0];
}
}
// Find it
const res = windowsToTest.filter(w => {
return null;
}
// match on folder
if (typeof w.openedFolderPath === 'string' && (paths.isEqual(w.openedFolderPath, folderPath, !platform.isLinux /* ignorecase */))) {
export function findWindowOnWorkspace<W extends ISimpleWindow>(windows: W[], workspaceConfigPath: string): W {
if (windows.length) {
const res = windows.filter(w => {
// match on workspace
if (typeof w.openedWorkspaceConfigPath === 'string' && (paths.isEqual(w.openedWorkspaceConfigPath, workspaceConfigPath, !platform.isLinux /* ignorecase */))) {
return true;
}
......
......@@ -6,6 +6,7 @@
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export interface IBackupWorkspacesFormat {
rootWorkspaces: string[];
folderWorkspaces: string[];
emptyWorkspaces: string[];
}
......@@ -16,8 +17,10 @@ export interface IBackupMainService {
_serviceBrand: any;
getWorkspaceBackupPaths(): string[];
getFolderBackupPaths(): string[];
getEmptyWindowBackupPaths(): string[];
registerWorkspaceBackupSync(workspaceConfigPath: string): string;
registerFolderBackupSync(folderPath: string): string;
registerEmptyWindowBackupSync(backupFolder?: string): string;
}
\ No newline at end of file
......@@ -22,7 +22,7 @@ export class BackupMainService implements IBackupMainService {
protected backupHome: string;
protected workspacesJsonPath: string;
private backups: IBackupWorkspacesFormat;
protected backups: IBackupWorkspacesFormat;
constructor(
@IEnvironmentService environmentService: IEnvironmentService,
......@@ -36,8 +36,16 @@ export class BackupMainService implements IBackupMainService {
}
public getWorkspaceBackupPaths(): string[] {
const config = this.configurationService.getConfiguration<IFilesConfiguration>();
if (config && config.files && config.files.hotExit === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) {
if (this.isHotExitOnExitAndWindowClose()) {
// Only non-folder windows are restored on main process launch when
// hot exit is configured as onExitAndWindowClose.
return [];
}
return this.backups.rootWorkspaces.slice(0); // return a copy
}
public getFolderBackupPaths(): string[] {
if (this.isHotExitOnExitAndWindowClose()) {
// Only non-folder windows are restored on main process launch when
// hot exit is configured as onExitAndWindowClose.
return [];
......@@ -45,12 +53,24 @@ export class BackupMainService implements IBackupMainService {
return this.backups.folderWorkspaces.slice(0); // return a copy
}
private isHotExitOnExitAndWindowClose(): boolean {
const config = this.configurationService.getConfiguration<IFilesConfiguration>();
return config && config.files && config.files.hotExit === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE;
}
public getEmptyWindowBackupPaths(): string[] {
return this.backups.emptyWorkspaces.slice(0); // return a copy
}
public registerWorkspaceBackupSync(workspaceConfigPath: string): string {
this.pushBackupPathsSync(workspaceConfigPath, this.backups.rootWorkspaces);
return path.join(this.backupHome, this.getWorkspaceHash(workspaceConfigPath));
}
public registerFolderBackupSync(folderPath: string): string {
this.pushBackupPathsSync(folderPath);
this.pushBackupPathsSync(folderPath, this.backups.folderWorkspaces);
return path.join(this.backupHome, this.getWorkspaceHash(folderPath));
}
......@@ -62,47 +82,40 @@ export class BackupMainService implements IBackupMainService {
backupFolder = this.getRandomEmptyWindowId();
}
this.pushBackupPathsSync(backupFolder, true);
this.pushBackupPathsSync(backupFolder, this.backups.emptyWorkspaces);
return path.join(this.backupHome, backupFolder);
}
private pushBackupPathsSync(workspaceIdentifier: string, isEmptyWindow?: boolean): string {
const array = isEmptyWindow ? this.backups.emptyWorkspaces : this.backups.folderWorkspaces;
if (this.indexOf(workspaceIdentifier, isEmptyWindow) === -1) {
array.push(workspaceIdentifier);
private pushBackupPathsSync(workspaceIdentifier: string, target: string[]): string {
if (this.indexOf(workspaceIdentifier, target) === -1) {
target.push(workspaceIdentifier);
this.saveSync();
}
return workspaceIdentifier;
}
protected removeBackupPathSync(workspaceIdentifier: string, isEmptyWindow: boolean): void {
const array = isEmptyWindow ? this.backups.emptyWorkspaces : this.backups.folderWorkspaces;
if (!array) {
protected removeBackupPathSync(workspaceIdentifier: string, target: string[]): void {
if (!target) {
return;
}
const index = this.indexOf(workspaceIdentifier, isEmptyWindow);
const index = this.indexOf(workspaceIdentifier, target);
if (index === -1) {
return;
}
array.splice(index, 1);
target.splice(index, 1);
this.saveSync();
}
private indexOf(workspaceIdentifier: string, isEmptyWindow: boolean): number {
const array = isEmptyWindow ? this.backups.emptyWorkspaces : this.backups.folderWorkspaces;
if (!array) {
private indexOf(workspaceIdentifier: string, target: string[]): number {
if (!target) {
return -1;
}
if (isEmptyWindow) {
return array.indexOf(workspaceIdentifier);
}
// for backup workspaces, sanitize the workspace identifier to accomodate for case insensitive file systems
const sanitizedWorkspaceIdentifier = this.sanitizePath(workspaceIdentifier);
return arrays.firstIndex(array, id => this.sanitizePath(id) === sanitizedWorkspaceIdentifier);
return arrays.firstIndex(target, id => this.sanitizePath(id) === sanitizedWorkspaceIdentifier);
}
protected loadSync(): void {
......@@ -113,6 +126,16 @@ export class BackupMainService implements IBackupMainService {
backups = Object.create(null);
}
// Ensure rootWorkspaces is a string[]
if (backups.rootWorkspaces) {
const rws = backups.rootWorkspaces;
if (!Array.isArray(rws) || rws.some(r => typeof r !== 'string')) {
backups.rootWorkspaces = [];
}
} else {
backups.rootWorkspaces = [];
}
// Ensure folderWorkspaces is a string[]
if (backups.folderWorkspaces) {
const fws = backups.folderWorkspaces;
......@@ -133,43 +156,49 @@ export class BackupMainService implements IBackupMainService {
backups.emptyWorkspaces = [];
}
this.backups = this.dedupeFolderWorkspaces(backups);
this.backups = this.dedupeBackups(backups);
// Validate backup workspaces
this.validateBackupWorkspaces(backups);
}
protected dedupeFolderWorkspaces(backups: IBackupWorkspacesFormat): IBackupWorkspacesFormat {
// De-duplicate folder workspaces, don't worry about cleaning them up any duplicates as
protected dedupeBackups(backups: IBackupWorkspacesFormat): IBackupWorkspacesFormat {
// De-duplicate folder/workspace backups. don't worry about cleaning them up any duplicates as
// they will be removed when there are no backups.
backups.folderWorkspaces = arrays.distinct(backups.folderWorkspaces, ws => this.sanitizePath(ws));
backups.rootWorkspaces = arrays.distinct(backups.rootWorkspaces, ws => this.sanitizePath(ws));
return backups;
}
private validateBackupWorkspaces(backups: IBackupWorkspacesFormat): void {
const staleBackupWorkspaces: { workspaceIdentifier: string; backupPath: string; isEmptyWindow: boolean }[] = [];
const staleBackupWorkspaces: { workspaceIdentifier: string; backupPath: string; target: string[] }[] = [];
const workspaceAndFolders: { path: string, target: string[] }[] = [];
workspaceAndFolders.push(...backups.rootWorkspaces.map(r => ({ path: r, target: backups.rootWorkspaces })));
workspaceAndFolders.push(...backups.folderWorkspaces.map(f => ({ path: f, target: backups.folderWorkspaces })));
// Validate Folder Workspaces
backups.folderWorkspaces.forEach(workspacePath => {
const backupPath = path.join(this.backupHome, this.getWorkspaceHash(workspacePath));
// Validate Workspace and Folder Backups
workspaceAndFolders.forEach(workspaceOrFolder => {
const backupPath = path.join(this.backupHome, this.getWorkspaceHash(workspaceOrFolder.path));
const hasBackups = this.hasBackupsSync(backupPath);
const missingWorkspace = hasBackups && !fs.existsSync(workspacePath);
const missingWorkspace = hasBackups && !fs.existsSync(workspaceOrFolder.path);
// If the folder has no backups, make sure to delete it
// If the folder has backups, but the target workspace is missing, convert backups to empty ones
// If the workspace/folder has no backups, make sure to delete it
// If the workspace/folder has backups, but the target workspace is missing, convert backups to empty ones
if (!hasBackups || missingWorkspace) {
staleBackupWorkspaces.push({ workspaceIdentifier: workspacePath, backupPath, isEmptyWindow: false });
staleBackupWorkspaces.push({ workspaceIdentifier: workspaceOrFolder.path, backupPath, target: workspaceOrFolder.target });
if (missingWorkspace) {
const identifier = this.pushBackupPathsSync(this.getRandomEmptyWindowId(), true /* is empty workspace */);
const identifier = this.pushBackupPathsSync(this.getRandomEmptyWindowId(), this.backups.emptyWorkspaces);
const newEmptyWindowBackupPath = path.join(path.dirname(backupPath), identifier);
try {
fs.renameSync(backupPath, newEmptyWindowBackupPath);
} catch (ex) {
this.logService.error(`Backup: Could not rename backup folder for missing workspace: ${ex.toString()}`);
this.removeBackupPathSync(identifier, true);
this.removeBackupPathSync(identifier, this.backups.emptyWorkspaces);
}
}
}
......@@ -179,13 +208,13 @@ export class BackupMainService implements IBackupMainService {
backups.emptyWorkspaces.forEach(backupFolder => {
const backupPath = path.join(this.backupHome, backupFolder);
if (!this.hasBackupsSync(backupPath)) {
staleBackupWorkspaces.push({ workspaceIdentifier: backupFolder, backupPath, isEmptyWindow: true });
staleBackupWorkspaces.push({ workspaceIdentifier: backupFolder, backupPath, target: backups.emptyWorkspaces });
}
});
// Clean up stale backups
staleBackupWorkspaces.forEach(staleBackupWorkspace => {
const { backupPath, workspaceIdentifier, isEmptyWindow } = staleBackupWorkspace;
const { backupPath, workspaceIdentifier, target } = staleBackupWorkspace;
try {
extfs.delSync(backupPath);
......@@ -193,7 +222,7 @@ export class BackupMainService implements IBackupMainService {
this.logService.error(`Backup: Could not delete stale backup: ${ex.toString()}`);
}
this.removeBackupPathSync(workspaceIdentifier, isEmptyWindow);
this.removeBackupPathSync(workspaceIdentifier, target);
});
}
......
......@@ -63,6 +63,8 @@ export interface IEnvironmentService {
backupHome: string;
backupWorkspacesPath: string;
workspacesHome: string;
isExtensionDevelopment: boolean;
disableExtensions: boolean;
extensionsPath: string;
......
......@@ -92,6 +92,9 @@ export class EnvironmentService implements IEnvironmentService {
@memoize
get backupWorkspacesPath(): string { return path.join(this.backupHome, 'workspaces.json'); }
@memoize
get workspacesHome(): string { return path.join(this.userDataPath, 'Workspaces'); }
@memoize
get extensionsPath(): string { return parsePathArg(this._args['extensions-dir'], process) || path.join(this.userHome, product.dataFolderName, 'extensions'); }
......
......@@ -204,6 +204,7 @@ export interface IWindowConfiguration extends ParsedArgs, IOpenFileRequest {
perfAppReady?: number;
perfWindowLoadTime?: number;
workspaceConfigPath?: string;
folderPath?: string;
backupPath?: string;
......
......@@ -17,7 +17,10 @@ export interface ICodeWindow {
id: number;
win: Electron.BrowserWindow;
config: IWindowConfiguration;
openedFolderPath: string;
openedWorkspaceConfigPath: string;
lastFocusTime: number;
readyState: ReadyState;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册