Skip to content

Commit 7feea00

Browse files
aeschlialexdima
authored andcommitted
Exploration with authority
1 parent dc63f09 commit 7feea00

9 files changed

Lines changed: 91 additions & 25 deletions

File tree

src/vs/code/electron-main/window.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,10 @@ export class CodeWindow implements ICodeWindow {
284284
return this.currentConfig ? this.currentConfig.folderUri : void 0;
285285
}
286286

287+
get remoteAuthority(): string {
288+
return this.currentConfig ? this.currentConfig.remoteAuthority : void 0;
289+
}
290+
287291
setReady(): void {
288292
this._readyState = ReadyState.READY;
289293

src/vs/code/electron-main/windows.ts

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import { Queue, timeout } from 'vs/base/common/async';
3737
import { exists } from 'vs/base/node/pfs';
3838
import { getComparisonKey, isEqual, normalizePath } from 'vs/base/common/resources';
3939
import { endsWith } from 'vs/base/common/strings';
40+
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
4041

4142
enum WindowError {
4243
UNRESPONSIVE,
@@ -51,6 +52,7 @@ interface IWindowState {
5152
workspace?: IWorkspaceIdentifier;
5253
folderUri?: URI;
5354
backupPath: string;
55+
remoteAuthority?: string;
5456
uiState: ISingleWindowState;
5557
}
5658

@@ -73,6 +75,8 @@ interface IOpenBrowserWindowOptions {
7375
workspace?: IWorkspaceIdentifier;
7476
folderUri?: URI;
7577

78+
remoteAuthority: string;
79+
7680
initialStartup?: boolean;
7781

7882
fileInputs?: IFileInputs;
@@ -88,13 +92,15 @@ interface IPathParseOptions {
8892
ignoreFileNotFound?: boolean;
8993
gotoLineMode?: boolean;
9094
forceOpenWorkspaceAsFile?: boolean;
95+
remoteAuthority?: string;
9196
}
9297

9398
interface IFileInputs {
9499
filesToOpen: IPath[];
95100
filesToCreate: IPath[];
96101
filesToDiff: IPath[];
97102
filesToWait?: IPathsToWaitFor;
103+
remoteAuthority?: string;
98104
}
99105

100106
interface IPathToOpen extends IPath {
@@ -108,6 +114,9 @@ interface IPathToOpen extends IPath {
108114
// the backup path for a Code instance to use
109115
backupPath?: string;
110116

117+
// the remote authority for the Code instance to open. Undefined if not remote.
118+
remoteAuthority?: string;
119+
111120
// indicator to create the file path in the Code instance
112121
createFilePath?: boolean;
113122
}
@@ -358,6 +367,7 @@ export class WindowsManager implements IWindowsMainService {
358367
workspace: win.openedWorkspace,
359368
folderUri: win.openedFolderUri,
360369
backupPath: win.backupPath,
370+
remoteAuthority: win.remoteAuthority,
361371
uiState: win.serializeWindowState()
362372
};
363373
}
@@ -381,7 +391,7 @@ export class WindowsManager implements IWindowsMainService {
381391
for (const path of pathsToOpen) {
382392
if (path.fileUri) {
383393
if (!fileInputs) {
384-
fileInputs = { filesToCreate: [], filesToOpen: [], filesToDiff: [] };
394+
fileInputs = { filesToCreate: [], filesToOpen: [], filesToDiff: [], remoteAuthority: path.remoteAuthority };
385395
}
386396
if (!path.createFilePath) {
387397
fileInputs.filesToOpen.push(path);
@@ -427,7 +437,7 @@ export class WindowsManager implements IWindowsMainService {
427437
workspacesToRestore.push(...this.workspacesMainService.getUntitledWorkspacesSync()); // collect from previous window session
428438

429439
emptyToRestore = this.backupMainService.getEmptyWindowBackupPaths();
430-
emptyToRestore.push(...pathsToOpen.filter(w => !w.workspace && !w.folderUri && w.backupPath).map(w => ({ backupFolder: basename(w.backupPath) }))); // add empty windows with backupPath
440+
emptyToRestore.push(...pathsToOpen.filter(w => !w.workspace && !w.folderUri && w.backupPath).map(w => ({ backupFolder: basename(w.backupPath), remoteAuthority: w.remoteAuthority }))); // add empty windows with backupPath
431441
emptyToRestore = arrays.distinct(emptyToRestore, info => info.backupFolder); // prevent duplicates
432442
}
433443

@@ -537,7 +547,8 @@ export class WindowsManager implements IWindowsMainService {
537547

538548
// Handle folders to add by looking for the last active workspace (not on initial startup)
539549
if (!openConfig.initialStartup && foldersToAdd.length > 0) {
540-
const lastActiveWindow = this.getLastActiveWindow();
550+
const authority = getRemoteAuthority(foldersToAdd[0]);
551+
const lastActiveWindow = this.getLastActiveWindowForAuthority(authority);
541552
if (lastActiveWindow) {
542553
usedWindows.push(this.doAddFoldersToExistingWindow(lastActiveWindow, foldersToAdd));
543554
}
@@ -552,7 +563,8 @@ export class WindowsManager implements IWindowsMainService {
552563

553564
// Find suitable window or folder path to open files in
554565
const fileToCheck = fileInputs.filesToOpen[0] || fileInputs.filesToCreate[0] || fileInputs.filesToDiff[0];
555-
const windows = WindowsManager.WINDOWS;
566+
// only look at the windows with correct authority
567+
const windows = WindowsManager.WINDOWS.filter(w => w.remoteAuthority === fileInputs.remoteAuthority);
556568

557569
let bestWindowOrFolder = findBestWindowOrFolderForFile({
558570
windows,
@@ -595,6 +607,7 @@ export class WindowsManager implements IWindowsMainService {
595607
initialStartup: openConfig.initialStartup,
596608
fileInputs,
597609
forceNewWindow: true,
610+
remoteAuthority: fileInputs.remoteAuthority,
598611
forceNewTabbedWindow: openConfig.forceNewTabbedWindow
599612
}));
600613

@@ -611,7 +624,7 @@ export class WindowsManager implements IWindowsMainService {
611624
const windowsOnWorkspace = arrays.coalesce(allWorkspacesToOpen.map(workspaceToOpen => findWindowOnWorkspace(WindowsManager.WINDOWS, workspaceToOpen)));
612625
if (windowsOnWorkspace.length > 0) {
613626
const windowOnWorkspace = windowsOnWorkspace[0];
614-
const fileInputsForWindow = fileInputs;
627+
const fileInputsForWindow = (fileInputs && fileInputs.remoteAuthority === windowOnWorkspace.remoteAuthority) ? fileInputs : void 0;
615628

616629
// Do open files
617630
usedWindows.push(this.doOpenFilesInExistingWindow(openConfig, windowOnWorkspace, fileInputsForWindow));
@@ -630,7 +643,7 @@ export class WindowsManager implements IWindowsMainService {
630643
return; // ignore folders that are already open
631644
}
632645

633-
const fileInputsForWindow = fileInputs;
646+
const fileInputsForWindow = (fileInputs && !fileInputs.remoteAuthority) ? fileInputs : void 0;
634647

635648
// Do open folder
636649
usedWindows.push(this.doOpenFolderOrWorkspace(openConfig, { workspace: workspaceToOpen }, openFolderInNewWindow, fileInputsForWindow));
@@ -653,7 +666,7 @@ export class WindowsManager implements IWindowsMainService {
653666
const windowsOnFolderPath = arrays.coalesce(allFoldersToOpen.map(folderToOpen => findWindowOnWorkspace(WindowsManager.WINDOWS, folderToOpen)));
654667
if (windowsOnFolderPath.length > 0) {
655668
const windowOnFolderPath = windowsOnFolderPath[0];
656-
const fileInputsForWindow = fileInputs;
669+
const fileInputsForWindow = fileInputs && fileInputs.remoteAuthority === windowOnFolderPath.remoteAuthority ? fileInputs : void 0;
657670

658671
// Do open files
659672
usedWindows.push(this.doOpenFilesInExistingWindow(openConfig, windowOnFolderPath, fileInputsForWindow));
@@ -673,10 +686,11 @@ export class WindowsManager implements IWindowsMainService {
673686
return; // ignore folders that are already open
674687
}
675688

676-
const fileInputsForWindow = fileInputs;
689+
const remoteAuthority = getRemoteAuthority(folderToOpen);
690+
const fileInputsForWindow = (fileInputs && fileInputs.remoteAuthority === remoteAuthority) ? fileInputs : void 0;
677691

678692
// Do open folder
679-
usedWindows.push(this.doOpenFolderOrWorkspace(openConfig, { folderUri: folderToOpen }, openFolderInNewWindow, fileInputsForWindow));
693+
usedWindows.push(this.doOpenFolderOrWorkspace(openConfig, { folderUri: folderToOpen, remoteAuthority }, openFolderInNewWindow, fileInputsForWindow));
680694

681695
// Reset these because we handled them
682696
if (fileInputsForWindow) {
@@ -690,13 +704,15 @@ export class WindowsManager implements IWindowsMainService {
690704
// Handle empty to restore
691705
if (emptyToRestore.length > 0) {
692706
emptyToRestore.forEach(emptyWindowBackupInfo => {
693-
const fileInputsForWindow = fileInputs;
707+
const remoteAuthority = emptyWindowBackupInfo.remoteAuthority;
708+
const fileInputsForWindow = (fileInputs && fileInputs.remoteAuthority === remoteAuthority) ? fileInputs : void 0;
694709

695710
usedWindows.push(this.openInBrowserWindow({
696711
userEnv: openConfig.userEnv,
697712
cli: openConfig.cli,
698713
initialStartup: openConfig.initialStartup,
699714
fileInputs: fileInputsForWindow,
715+
remoteAuthority,
700716
forceNewWindow: true,
701717
forceNewTabbedWindow: openConfig.forceNewTabbedWindow,
702718
emptyWindowBackupInfo
@@ -716,11 +732,13 @@ export class WindowsManager implements IWindowsMainService {
716732
if (fileInputs && !emptyToOpen) {
717733
emptyToOpen++;
718734
}
735+
const remoteAuthority = fileInputs ? fileInputs.remoteAuthority : (openConfig.cli && openConfig.cli.remote || void 0);
719736
for (let i = 0; i < emptyToOpen; i++) {
720737
usedWindows.push(this.openInBrowserWindow({
721738
userEnv: openConfig.userEnv,
722739
cli: openConfig.cli,
723740
initialStartup: openConfig.initialStartup,
741+
remoteAuthority,
724742
forceNewWindow: openFolderInNewWindow,
725743
forceNewTabbedWindow: openConfig.forceNewTabbedWindow,
726744
fileInputs
@@ -777,6 +795,7 @@ export class WindowsManager implements IWindowsMainService {
777795
workspace: folderOrWorkspace.workspace,
778796
folderUri: folderOrWorkspace.folderUri,
779797
fileInputs,
798+
remoteAuthority: folderOrWorkspace.remoteAuthority,
780799
forceNewWindow,
781800
forceNewTabbedWindow: openConfig.forceNewTabbedWindow,
782801
windowToUse
@@ -821,7 +840,7 @@ export class WindowsManager implements IWindowsMainService {
821840
const workspace = this.workspacesMainService.createWorkspaceSync(foldersToOpen.map(folder => ({ uri: folder.folderUri })));
822841

823842
// Add workspace and remove folders thereby
824-
windowsToOpen.push({ workspace });
843+
windowsToOpen.push({ workspace, remoteAuthority: foldersToOpen[0].remoteAuthority });
825844
windowsToOpen = windowsToOpen.filter(path => !path.folderUri);
826845
}
827846
}
@@ -869,7 +888,7 @@ export class WindowsManager implements IWindowsMainService {
869888

870889
private doExtractPathsFromCLI(cli: ParsedArgs): IPath[] {
871890
const pathsToOpen: IPathToOpen[] = [];
872-
const parseOptions: IPathParseOptions = { ignoreFileNotFound: true, gotoLineMode: cli.goto };
891+
const parseOptions: IPathParseOptions = { ignoreFileNotFound: true, gotoLineMode: cli.goto, remoteAuthority: cli.remote || void 0 };
873892

874893
// folder uris
875894
const folderUris = asArray(cli['folder-uri']);
@@ -932,17 +951,17 @@ export class WindowsManager implements IWindowsMainService {
932951
const windowsToOpen: IPathToOpen[] = [];
933952
for (const openedWindow of openedWindows) {
934953
if (openedWindow.workspace) { // Workspaces
935-
const pathToOpen = this.parsePath(openedWindow.workspace.configPath);
954+
const pathToOpen = this.parsePath(openedWindow.workspace.configPath, { remoteAuthority: openedWindow.remoteAuthority });
936955
if (pathToOpen && pathToOpen.workspace) {
937956
windowsToOpen.push(pathToOpen);
938957
}
939958
} else if (openedWindow.folderUri) { // Folders
940-
const pathToOpen = this.parseUri(openedWindow.folderUri, false);
959+
const pathToOpen = this.parseUri(openedWindow.folderUri, false, { remoteAuthority: openedWindow.remoteAuthority });
941960
if (pathToOpen && pathToOpen.folderUri) {
942961
windowsToOpen.push(pathToOpen);
943962
}
944963
} else if (restoreWindows !== 'folders' && openedWindow.backupPath) { // Windows that were Empty
945-
windowsToOpen.push({ backupPath: openedWindow.backupPath });
964+
windowsToOpen.push({ backupPath: openedWindow.backupPath, remoteAuthority: openedWindow.remoteAuthority });
946965
}
947966
}
948967

@@ -994,6 +1013,10 @@ export class WindowsManager implements IWindowsMainService {
9941013
if (uri.scheme === Schemas.file) {
9951014
return this.parsePath(uri.fsPath, options);
9961015
}
1016+
1017+
// open remote if either specified in the cli or if it's a remotehost URI
1018+
const remoteAuthority = options && options.remoteAuthority || getRemoteAuthority(uri);
1019+
9971020
// normalize URI
9981021
uri = normalizePath(uri);
9991022
if (endsWith(uri.path, '/')) {
@@ -1005,15 +1028,18 @@ export class WindowsManager implements IWindowsMainService {
10051028
return {
10061029
fileUri: uri.with({ path: parsedPath.path }),
10071030
lineNumber: parsedPath.line,
1008-
columnNumber: parsedPath.column
1031+
columnNumber: parsedPath.column,
1032+
remoteAuthority
10091033
};
10101034
}
10111035
return {
1012-
fileUri: uri
1036+
fileUri: uri,
1037+
remoteAuthority
10131038
};
10141039
}
10151040
return {
1016-
folderUri: uri
1041+
folderUri: uri,
1042+
remoteAuthority
10171043
};
10181044
}
10191045

@@ -1030,6 +1056,9 @@ export class WindowsManager implements IWindowsMainService {
10301056
anyPath = parsedPath.path;
10311057
}
10321058

1059+
// open remote if either specified in the cli even if it is a local file. TODO: Future idea: resolve in remote host context.
1060+
const remoteAuthority = options && options.remoteAuthority;
1061+
10331062
const candidate = normalize(anyPath);
10341063
try {
10351064
const candidateStat = fs.statSync(candidate);
@@ -1040,15 +1069,16 @@ export class WindowsManager implements IWindowsMainService {
10401069
if (!options || !options.forceOpenWorkspaceAsFile) {
10411070
const workspace = this.workspacesMainService.resolveWorkspaceSync(candidate);
10421071
if (workspace) {
1043-
return { workspace: { id: workspace.id, configPath: workspace.configPath } };
1072+
return { workspace: { id: workspace.id, configPath: workspace.configPath }, remoteAuthority };
10441073
}
10451074
}
10461075

10471076
// File
10481077
return {
10491078
fileUri: URI.file(candidate),
10501079
lineNumber: gotoLineMode ? parsedPath.line : void 0,
1051-
columnNumber: gotoLineMode ? parsedPath.column : void 0
1080+
columnNumber: gotoLineMode ? parsedPath.column : void 0,
1081+
remoteAuthority
10521082
};
10531083
}
10541084

@@ -1057,7 +1087,8 @@ export class WindowsManager implements IWindowsMainService {
10571087
// over to us)
10581088
else if (candidateStat.isDirectory()) {
10591089
return {
1060-
folderUri: URI.file(candidate)
1090+
folderUri: URI.file(candidate),
1091+
remoteAuthority
10611092
};
10621093
}
10631094
}
@@ -1066,7 +1097,7 @@ export class WindowsManager implements IWindowsMainService {
10661097
this.historyMainService.removeFromRecentlyOpened([fileUri]); // since file does not seem to exist anymore, remove from recent
10671098

10681099
if (options && options.ignoreFileNotFound) {
1069-
return { fileUri, createFilePath: true }; // assume this is a file that does not yet exist
1100+
return { fileUri, createFilePath: true, remoteAuthority }; // assume this is a file that does not yet exist
10701101
}
10711102
}
10721103

@@ -1181,6 +1212,7 @@ export class WindowsManager implements IWindowsMainService {
11811212
configuration.isInitialStartup = options.initialStartup;
11821213
configuration.workspace = options.workspace;
11831214
configuration.folderUri = options.folderUri;
1215+
configuration.remoteAuthority = options.remoteAuthority;
11841216

11851217
const fileInputs = options.fileInputs;
11861218
if (fileInputs) {
@@ -1286,7 +1318,7 @@ export class WindowsManager implements IWindowsMainService {
12861318
configuration.backupPath = this.backupMainService.registerFolderBackupSync(configuration.folderUri);
12871319
} else {
12881320
const backupFolder = options.emptyWindowBackupInfo && options.emptyWindowBackupInfo.backupFolder;
1289-
configuration.backupPath = this.backupMainService.registerEmptyWindowBackupSync({ backupFolder });
1321+
configuration.backupPath = this.backupMainService.registerEmptyWindowBackupSync({ backupFolder, remoteAuthority: configuration.remoteAuthority });
12901322
}
12911323
}
12921324

@@ -1444,7 +1476,8 @@ export class WindowsManager implements IWindowsMainService {
14441476
closeWorkspace(win: ICodeWindow): void {
14451477
this.openInBrowserWindow({
14461478
cli: this.environmentService.args,
1447-
windowToUse: win
1479+
windowToUse: win,
1480+
remoteAuthority: win.remoteAuthority
14481481
});
14491482
}
14501483

@@ -1528,8 +1561,16 @@ export class WindowsManager implements IWindowsMainService {
15281561
return getLastActiveWindow(WindowsManager.WINDOWS);
15291562
}
15301563

1564+
getLastActiveWindowForAuthority(remoteAuthority: string): ICodeWindow {
1565+
return getLastActiveWindow(WindowsManager.WINDOWS.filter(w => w.remoteAuthority === remoteAuthority));
1566+
}
1567+
15311568
openNewWindow(context: OpenContext, options?: INewWindowOptions): ICodeWindow[] {
15321569
let cli = this.environmentService.args;
1570+
let remote = options && options.remoteAuthority || void 0;
1571+
if (cli && (cli.remote !== remote)) {
1572+
cli = { ...cli, remote };
1573+
}
15331574
return this.open({ context, cli, forceNewWindow: true, forceEmpty: true });
15341575
}
15351576

src/vs/platform/backup/common/backup.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export const IBackupMainService = createDecorator<IBackupMainService>('backupMai
2121

2222
export interface IEmptyWindowBackupInfo {
2323
backupFolder: string;
24+
remoteAuthority?: string;
2425
}
2526

2627
export interface IBackupMainService {

src/vs/platform/backup/electron-main/backupMainService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,13 @@ export class BackupMainService implements IBackupMainService {
139139
public registerEmptyWindowBackupSync(backupInfo: IEmptyWindowBackupInfo): string {
140140

141141
let backupFolder = backupInfo.backupFolder;
142+
let remoteAuthority = backupInfo.remoteAuthority;
142143
// Generate a new folder if this is a new empty workspace
143144
if (!backupFolder) {
144145
backupFolder = this.getRandomEmptyWindowId();
145146
}
146147
if (!this.emptyWorkspaces.some(w => isEqual(w.backupFolder, backupFolder, !platform.isLinux))) {
147-
this.emptyWorkspaces.push({ backupFolder });
148+
this.emptyWorkspaces.push({ backupFolder, remoteAuthority });
148149
this.saveSync();
149150
}
150151
return this.getBackupPath(backupFolder);

src/vs/platform/environment/common/environment.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export interface ParsedArgs {
6868
'upload-logs'?: string;
6969
'driver'?: string;
7070
'driver-verbose'?: boolean;
71+
remote?: string;
7172
}
7273

7374
export const IEnvironmentService = createDecorator<IEnvironmentService>('environmentService');

src/vs/platform/environment/node/argv.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const options: minimist.Opts = {
2020
'extensions-dir',
2121
'folder-uri',
2222
'file-uri',
23+
'remote',
2324
'extensionDevelopmentPath',
2425
'extensionTestsPath',
2526
'install-extension',

0 commit comments

Comments
 (0)