@@ -28,6 +28,9 @@ import { IInitData } from 'vs/workbench/services/timer/common/timerService';
2828import { TimerService } from 'vs/workbench/services/timer/node/timerService' ;
2929import { KeyboardMapperFactory } from "vs/workbench/services/keybinding/electron-browser/keybindingService" ;
3030import { IWindowConfiguration , IPath } from "vs/platform/windows/common/windows" ;
31+ import { IStorageService } from "vs/platform/storage/common/storage" ;
32+ import { IEnvironmentService } from "vs/platform/environment/common/environment" ;
33+ import { StorageService , inMemoryLocalStorageInstance , IWorkspaceStorageIdentifier } from "vs/platform/storage/common/storageService" ;
3134
3235import { webFrame } from 'electron' ;
3336
@@ -62,12 +65,8 @@ export function startup(configuration: IWindowConfiguration): TPromise<void> {
6265 filesToDiff
6366 } ;
6467
65- // Resolve workspace
66- return getWorkspace ( configuration . workspacePath ) . then ( workspace => {
67-
68- // Open workbench
69- return openWorkbench ( configuration , workspace , shellOptions ) ;
70- } ) ;
68+ // Open workbench
69+ return openWorkbench ( configuration , shellOptions ) ;
7170}
7271
7372function toInputs ( paths : IPath [ ] , isUntitledFile ?: boolean ) : IResourceInput [ ] {
@@ -95,12 +94,53 @@ function toInputs(paths: IPath[], isUntitledFile?: boolean): IResourceInput[] {
9594 } ) ;
9695}
9796
98- function getWorkspace ( workspacePath : string ) : TPromise < Workspace > {
99- if ( ! workspacePath ) {
97+ function openWorkbench ( configuration : IWindowConfiguration , options : IOptions ) : TPromise < void > {
98+ return getWorkspace ( configuration ) . then ( workspace => {
99+ const environmentService = new EnvironmentService ( configuration , configuration . execPath ) ;
100+ const workspaceConfigurationService = new WorkspaceConfigurationService ( environmentService , workspace ) ;
101+ const timerService = new TimerService ( ( < any > window ) . MonacoEnvironment . timers as IInitData , ! workspaceConfigurationService . hasWorkspace ( ) ) ;
102+
103+ return createStorageService ( configuration , environmentService ) . then ( storageService => {
104+
105+ // Since the configuration service is one of the core services that is used in so many places, we initialize it
106+ // right before startup of the workbench shell to have its data ready for consumers
107+ return workspaceConfigurationService . initialize ( ) . then ( ( ) => {
108+ timerService . beforeDOMContentLoaded = Date . now ( ) ;
109+
110+ return domContentLoaded ( ) . then ( ( ) => {
111+ timerService . afterDOMContentLoaded = Date . now ( ) ;
112+
113+ // Open Shell
114+ timerService . beforeWorkbenchOpen = Date . now ( ) ;
115+ const shell = new WorkbenchShell ( document . body , {
116+ contextService : workspaceConfigurationService ,
117+ configurationService : workspaceConfigurationService ,
118+ environmentService,
119+ timerService,
120+ storageService
121+ } , configuration , options ) ;
122+ shell . open ( ) ;
123+
124+ // Inform user about loading issues from the loader
125+ ( < any > self ) . require . config ( {
126+ onError : ( err : any ) => {
127+ if ( err . errorCode === 'load' ) {
128+ shell . onUnexpectedError ( loaderError ( err ) ) ;
129+ }
130+ }
131+ } ) ;
132+ } ) ;
133+ } ) ;
134+ } ) ;
135+ } ) ;
136+ }
137+
138+ function getWorkspace ( configuration : IWindowConfiguration ) : TPromise < Workspace > {
139+ if ( ! configuration . workspacePath ) {
100140 return TPromise . as ( null ) ;
101141 }
102142
103- return realpath ( workspacePath ) . then ( realWorkspacePath => {
143+ return realpath ( configuration . workspacePath ) . then ( realWorkspacePath => {
104144
105145 // for some weird reason, node adds a trailing slash to UNC paths
106146 // we never ever want trailing slashes as our workspace path unless
@@ -110,55 +150,44 @@ function getWorkspace(workspacePath: string): TPromise<Workspace> {
110150 realWorkspacePath = strings . rtrim ( realWorkspacePath , paths . nativeSep ) ;
111151 }
112152
153+ // update config
154+ configuration . workspacePath = realWorkspacePath ;
155+
113156 const workspaceResource = uri . file ( realWorkspacePath ) ;
114157 const folderName = path . basename ( realWorkspacePath ) || realWorkspacePath ;
115158
116- return stat ( realWorkspacePath ) . then ( folderStat => {
117- return new Workspace (
118- workspaceResource ,
119- platform . isLinux ? folderStat . ino : folderStat . birthtime . getTime ( ) ,
120- folderName // On Linux, birthtime is ctime, so we cannot use it! We use the ino instead!
121- ) ;
122- } ) ;
159+ return new Workspace ( workspaceResource , folderName ) ;
123160 } , error => {
124161 errors . onUnexpectedError ( error ) ;
125162
126163 return null ; // treat invalid paths as empty workspace
127164 } ) ;
128165}
129166
130- function openWorkbench ( configuration : IWindowConfiguration , workspace : Workspace , options : IOptions ) : TPromise < void > {
131- const environmentService = new EnvironmentService ( configuration , configuration . execPath ) ;
132- const workspaceConfigurationService = new WorkspaceConfigurationService ( environmentService , workspace ) ;
133- const timerService = new TimerService ( ( < any > window ) . MonacoEnvironment . timers as IInitData , ! workspaceConfigurationService . hasWorkspace ( ) ) ;
134-
135- // Since the configuration service is one of the core services that is used in so many places, we initialize it
136- // right before startup of the workbench shell to have its data ready for consumers
137- return workspaceConfigurationService . initialize ( ) . then ( ( ) => {
138- timerService . beforeDOMContentLoaded = Date . now ( ) ;
139-
140- return domContentLoaded ( ) . then ( ( ) => {
141- timerService . afterDOMContentLoaded = Date . now ( ) ;
142-
143- // Open Shell
144- timerService . beforeWorkbenchOpen = Date . now ( ) ;
145- const shell = new WorkbenchShell ( document . body , {
146- contextService : workspaceConfigurationService ,
147- configurationService : workspaceConfigurationService ,
148- environmentService,
149- timerService
150- } , configuration , options ) ;
151- shell . open ( ) ;
152-
153- // Inform user about loading issues from the loader
154- ( < any > self ) . require . config ( {
155- onError : ( err : any ) => {
156- if ( err . errorCode === 'load' ) {
157- shell . onUnexpectedError ( loaderError ( err ) ) ;
158- }
159- }
160- } ) ;
161- } ) ;
167+ function createStorageService ( configuration : IWindowConfiguration , environmentService : IEnvironmentService ) : TPromise < IStorageService > {
168+ let workspaceStatPromise : TPromise < fs . Stats > = TPromise . as ( null ) ;
169+ if ( configuration . workspacePath ) {
170+ workspaceStatPromise = stat ( configuration . workspacePath ) ;
171+ }
172+
173+ return workspaceStatPromise . then ( stat => {
174+ let id : IWorkspaceStorageIdentifier ;
175+ if ( stat ) {
176+ id = { resource : uri . file ( configuration . workspacePath ) , uid : platform . isLinux ? stat . ino : stat . birthtime . getTime ( ) } ;
177+ } else if ( configuration . backupPath ) {
178+ // if we do not have a workspace open, we need to find another identifier for the window to store
179+ // workspace UI state. if we have a backup path in the configuration we can use that because this
180+ // will be a unique identifier per window that is stable between restarts as long as there are
181+ // dirty files in the workspace.
182+ // We use basename() to produce a short identifier, we do not need the full path. We use a custom
183+ // scheme so that we can later distinguish these identifiers from the workspace one.
184+ id = { resource : uri . from ( { path : path . basename ( configuration . backupPath ) , scheme : 'empty' } ) } ;
185+ }
186+
187+ const disableStorage = ! ! environmentService . extensionTestsPath ; // never keep any state when running extension tests!
188+ const storage = disableStorage ? inMemoryLocalStorageInstance : window . localStorage ;
189+
190+ return new StorageService ( storage , storage , id ) ;
162191 } ) ;
163192}
164193
0 commit comments