@@ -37,6 +37,7 @@ import { Queue, timeout } from 'vs/base/common/async';
3737import { exists } from 'vs/base/node/pfs' ;
3838import { getComparisonKey , isEqual , normalizePath } from 'vs/base/common/resources' ;
3939import { endsWith } from 'vs/base/common/strings' ;
40+ import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts' ;
4041
4142enum 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
9398interface IFileInputs {
9499 filesToOpen : IPath [ ] ;
95100 filesToCreate : IPath [ ] ;
96101 filesToDiff : IPath [ ] ;
97102 filesToWait ?: IPathsToWaitFor ;
103+ remoteAuthority ?: string ;
98104}
99105
100106interface 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
0 commit comments