Skip to content

Commit

Permalink
transient workspaces - prevent to restore transient workspaces (#119695)
Browse files Browse the repository at this point in the history
  • Loading branch information
bpasero committed Jun 24, 2021
1 parent 4826505 commit 9672045
Showing 1 changed file with 53 additions and 14 deletions.
67 changes: 53 additions & 14 deletions src/vs/platform/windows/electron-main/windowsMainService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,37 @@ interface IOpenBrowserWindowOptions {
}

interface IPathResolveOptions {

/**
* By default, resolving a path will check
* if the path exists. This can be disabled
* with this flag.
*/
readonly ignoreFileNotFound?: boolean;

/**
* Will reject a path if it points to a transient
* workspace as indicated by a `transient: true`
* property in the workspace file.
*/
readonly rejectTransientWorkspaces?: boolean;

/**
* If enabled, will resolve the path line/column
* aware and properly remove this information
* from the resulting file path.
*/
readonly gotoLineMode?: boolean;

/**
* Forces to resolve the provided path as workspace
* file instead of opening it as a file.
*/
readonly forceOpenWorkspaceAsFile?: boolean;

/**
* The remoteAuthority to use if the URL to open is neither file nor vscode-remote
* The remoteAuthority to use if the URL to open is
* neither `file` nor `vscode-remote`.
*/
readonly remoteAuthority?: string;
}
Expand Down Expand Up @@ -209,9 +235,12 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic

const foldersToAdd: ISingleFolderWorkspacePathToOpen[] = [];
const foldersToOpen: ISingleFolderWorkspacePathToOpen[] = [];

const workspacesToOpen: IWorkspacePathToOpen[] = [];
const workspacesToRestore: IWorkspacePathToOpen[] = [];
const emptyToRestore: IEmptyWindowBackupInfo[] = [];
const untitledWorkspacesToRestore: IWorkspacePathToOpen[] = [];

const emptyWindowsWithBackupsToRestore: IEmptyWindowBackupInfo[] = [];

let filesToOpen: IFilesToOpen | undefined;
let emptyToOpen = 0;

Expand All @@ -235,7 +264,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
}
filesToOpen.filesToOpenOrCreate.push(path);
} else if (path.backupPath) {
emptyToRestore.push({ backupFolder: basename(path.backupPath), remoteAuthority: path.remoteAuthority });
emptyWindowsWithBackupsToRestore.push({ backupFolder: basename(path.backupPath), remoteAuthority: path.remoteAuthority });
} else {
emptyToOpen++;
}
Expand All @@ -257,19 +286,19 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
if (openConfig.initialStartup) {

// Untitled workspaces are always restored
workspacesToRestore.push(...this.workspacesManagementMainService.getUntitledWorkspacesSync());
workspacesToOpen.push(...workspacesToRestore);
untitledWorkspacesToRestore.push(...this.workspacesManagementMainService.getUntitledWorkspacesSync());
workspacesToOpen.push(...untitledWorkspacesToRestore);

// Empty windows with backups are always restored
emptyToRestore.push(...this.backupMainService.getEmptyWindowBackupPaths());
emptyWindowsWithBackupsToRestore.push(...this.backupMainService.getEmptyWindowBackupPaths());
} else {
emptyToRestore.length = 0;
emptyWindowsWithBackupsToRestore.length = 0;
}

// Open based on config
const { windows: usedWindows, filesOpenedInWindow } = this.doOpen(openConfig, workspacesToOpen, foldersToOpen, emptyToRestore, emptyToOpen, filesToOpen, foldersToAdd);
const { windows: usedWindows, filesOpenedInWindow } = this.doOpen(openConfig, workspacesToOpen, foldersToOpen, emptyWindowsWithBackupsToRestore, emptyToOpen, filesToOpen, foldersToAdd);

this.logService.trace(`windowsManager#open used window count ${usedWindows.length} (workspacesToOpen: ${workspacesToOpen.length}, foldersToOpen: ${foldersToOpen.length}, emptyToRestore: ${emptyToRestore.length}, emptyToOpen: ${emptyToOpen})`);
this.logService.trace(`windowsManager#open used window count ${usedWindows.length} (workspacesToOpen: ${workspacesToOpen.length}, foldersToOpen: ${foldersToOpen.length}, emptyToRestore: ${emptyWindowsWithBackupsToRestore.length}, emptyToOpen: ${emptyToOpen})`);

// Make sure to pass focus to the most relevant of the windows if we open multiple
if (usedWindows.length > 1) {
Expand Down Expand Up @@ -300,8 +329,8 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
for (let i = usedWindows.length - 1; i >= 0; i--) {
const usedWindow = usedWindows[i];
if (
(usedWindow.openedWorkspace && workspacesToRestore.some(workspace => usedWindow.openedWorkspace && workspace.workspace.id === usedWindow.openedWorkspace.id)) || // skip over restored workspace
(usedWindow.backupPath && emptyToRestore.some(empty => usedWindow.backupPath && empty.backupFolder === basename(usedWindow.backupPath))) // skip over restored empty window
(usedWindow.openedWorkspace && untitledWorkspacesToRestore.some(workspace => usedWindow.openedWorkspace && workspace.workspace.id === usedWindow.openedWorkspace.id)) || // skip over restored workspace
(usedWindow.backupPath && emptyWindowsWithBackupsToRestore.some(empty => usedWindow.backupPath && empty.backupFolder === basename(usedWindow.backupPath))) // skip over restored empty window
) {
continue;
}
Expand Down Expand Up @@ -810,7 +839,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic

// Workspaces
if (lastSessionWindow.workspace) {
const pathToOpen = this.resolveOpenable({ workspaceUri: lastSessionWindow.workspace.configPath }, { remoteAuthority: lastSessionWindow.remoteAuthority });
const pathToOpen = this.resolveOpenable({ workspaceUri: lastSessionWindow.workspace.configPath }, { remoteAuthority: lastSessionWindow.remoteAuthority, rejectTransientWorkspaces: true /* https://github.com/microsoft/vscode/issues/119695 */ });
if (isWorkspacePathToOpen(pathToOpen)) {
pathsToOpen.push(pathToOpen);
}
Expand Down Expand Up @@ -850,7 +879,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
return restoreWindows;
}

private resolveOpenable(openable: IWindowOpenable, options: IPathResolveOptions = {}): IPathToOpen | undefined {
private resolveOpenable(openable: IWindowOpenable, options: IPathResolveOptions = Object.create(null)): IPathToOpen | undefined {

// handle file:// openables with some extra validation
let uri = this.resourceFromOpenable(openable);
Expand Down Expand Up @@ -927,6 +956,16 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
if (!options.forceOpenWorkspaceAsFile) {
const workspace = this.workspacesManagementMainService.resolveLocalWorkspaceSync(URI.file(path));
if (workspace) {

// If the workspace is transient and we are to ignore
// transient workspaces, reject it. Also remove traces
// in the history if any.
if (workspace.transient && options.rejectTransientWorkspaces) {
this.workspacesHistoryMainService.removeRecentlyOpened([URI.file(path)]);

return undefined;
}

return { workspace: { id: workspace.id, configPath: workspace.configPath }, remoteAuthority: workspace.remoteAuthority, exists: true };
}
}
Expand Down

0 comments on commit 9672045

Please sign in to comment.