mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-05 21:07:16 +01:00
debt - convert main startup code to async
This commit is contained in:
@@ -310,7 +310,7 @@ export class CodeApplication extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
startup(): Promise<void> {
|
||||
async startup(): Promise<void> {
|
||||
this.logService.debug('Starting VS Code');
|
||||
this.logService.debug(`from: ${this.environmentService.appRoot}`);
|
||||
this.logService.debug('args:', this.environmentService.args);
|
||||
@@ -340,62 +340,55 @@ export class CodeApplication extends Disposable {
|
||||
// Create Electron IPC Server
|
||||
this.electronIpcServer = new ElectronIPCServer();
|
||||
|
||||
const startupWithMachineId = (machineId: string) => {
|
||||
this.logService.trace(`Resolved machine identifier: ${machineId}`);
|
||||
|
||||
// Spawn shared process
|
||||
this.sharedProcess = this.instantiationService.createInstance(SharedProcess, machineId, this.userEnv);
|
||||
this.sharedProcessClient = this.sharedProcess.whenReady().then(() => connect(this.environmentService.sharedIPCHandle, 'main'));
|
||||
|
||||
// Services
|
||||
return this.initServices(machineId).then(appInstantiationService => {
|
||||
|
||||
// Create driver
|
||||
if (this.environmentService.driverHandle) {
|
||||
serveDriver(this.electronIpcServer, this.environmentService.driverHandle, this.environmentService, appInstantiationService).then(server => {
|
||||
this.logService.info('Driver started at:', this.environmentService.driverHandle);
|
||||
this._register(server);
|
||||
});
|
||||
}
|
||||
|
||||
// Setup Auth Handler
|
||||
const authHandler = appInstantiationService.createInstance(ProxyAuthHandler);
|
||||
this._register(authHandler);
|
||||
|
||||
// Open Windows
|
||||
const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor));
|
||||
|
||||
// Post Open Windows Tasks
|
||||
appInstantiationService.invokeFunction(accessor => this.afterWindowOpen(accessor));
|
||||
|
||||
// Tracing: Stop tracing after windows are ready if enabled
|
||||
if (this.environmentService.args.trace) {
|
||||
this.stopTracingEventually(windows);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Resolve unique machine ID
|
||||
this.logService.trace('Resolving machine identifier...');
|
||||
const resolvedMachineId = this.resolveMachineId();
|
||||
if (typeof resolvedMachineId === 'string') {
|
||||
return startupWithMachineId(resolvedMachineId);
|
||||
} else {
|
||||
return resolvedMachineId.then(machineId => startupWithMachineId(machineId));
|
||||
const machineId = await this.resolveMachineId();
|
||||
this.logService.trace(`Resolved machine identifier: ${machineId}`);
|
||||
|
||||
// Spawn shared process
|
||||
this.sharedProcess = this.instantiationService.createInstance(SharedProcess, machineId, this.userEnv);
|
||||
this.sharedProcessClient = this.sharedProcess.whenReady().then(() => connect(this.environmentService.sharedIPCHandle, 'main'));
|
||||
|
||||
// Services
|
||||
const appInstantiationService = await this.initServices(machineId);
|
||||
|
||||
// Create driver
|
||||
if (this.environmentService.driverHandle) {
|
||||
(async () => {
|
||||
const server = await serveDriver(this.electronIpcServer, this.environmentService.driverHandle!, this.environmentService, appInstantiationService);
|
||||
|
||||
this.logService.info('Driver started at:', this.environmentService.driverHandle);
|
||||
this._register(server);
|
||||
})();
|
||||
}
|
||||
|
||||
// Setup Auth Handler
|
||||
const authHandler = appInstantiationService.createInstance(ProxyAuthHandler);
|
||||
this._register(authHandler);
|
||||
|
||||
// Open Windows
|
||||
const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor));
|
||||
|
||||
// Post Open Windows Tasks
|
||||
appInstantiationService.invokeFunction(accessor => this.afterWindowOpen(accessor));
|
||||
|
||||
// Tracing: Stop tracing after windows are ready if enabled
|
||||
if (this.environmentService.args.trace) {
|
||||
this.stopTracingEventually(windows);
|
||||
}
|
||||
}
|
||||
|
||||
private resolveMachineId(): string | Promise<string> {
|
||||
const machineId = this.stateService.getItem<string>(CodeApplication.MACHINE_ID_KEY);
|
||||
private async resolveMachineId(): Promise<string> {
|
||||
let machineId = this.stateService.getItem<string>(CodeApplication.MACHINE_ID_KEY);
|
||||
if (machineId) {
|
||||
return machineId;
|
||||
}
|
||||
|
||||
return getMachineId().then(machineId => {
|
||||
this.stateService.setItem(CodeApplication.MACHINE_ID_KEY, machineId);
|
||||
machineId = await getMachineId();
|
||||
|
||||
return machineId;
|
||||
});
|
||||
this.stateService.setItem(CodeApplication.MACHINE_ID_KEY, machineId);
|
||||
|
||||
return machineId;
|
||||
}
|
||||
|
||||
private stopTracingEventually(windows: ICodeWindow[]): void {
|
||||
@@ -433,7 +426,7 @@ export class CodeApplication extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
private initServices(machineId: string): Promise<IInstantiationService> {
|
||||
private async initServices(machineId: string): Promise<IInstantiationService> {
|
||||
const services = new ServiceCollection();
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
@@ -475,10 +468,12 @@ export class CodeApplication extends Disposable {
|
||||
const appInstantiationService = this.instantiationService.createChild(services);
|
||||
|
||||
// Init services that require it
|
||||
return appInstantiationService.invokeFunction(accessor => Promise.all([
|
||||
await appInstantiationService.invokeFunction(accessor => Promise.all([
|
||||
this.initStorageService(accessor),
|
||||
this.initBackupService(accessor)
|
||||
])).then(() => appInstantiationService);
|
||||
]));
|
||||
|
||||
return appInstantiationService;
|
||||
}
|
||||
|
||||
private initStorageService(accessor: ServicesAccessor): Promise<void> {
|
||||
@@ -558,15 +553,17 @@ export class CodeApplication extends Disposable {
|
||||
const environmentService = accessor.get(IEnvironmentService);
|
||||
|
||||
urlService.registerHandler({
|
||||
handleURL(uri: URI): Promise<boolean> {
|
||||
async handleURL(uri: URI): Promise<boolean> {
|
||||
if (windowsMainService.getWindowCount() === 0) {
|
||||
const cli = { ...environmentService.args, goto: true };
|
||||
const [window] = windowsMainService.open({ context: OpenContext.API, cli, forceEmpty: true });
|
||||
|
||||
return window.ready().then(() => urlService.open(uri));
|
||||
await window.ready();
|
||||
|
||||
return urlService.open(uri);
|
||||
}
|
||||
|
||||
return Promise.resolve(false);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -738,9 +735,7 @@ export class CodeApplication extends Disposable {
|
||||
dispose(): void {
|
||||
this._disposeRunner.dispose();
|
||||
connectionPool.delete(this._authority);
|
||||
this._connection.then((connection) => {
|
||||
connection.dispose();
|
||||
});
|
||||
this._connection.then(connection => connection.dispose());
|
||||
}
|
||||
|
||||
async getClient(): Promise<Client<RemoteAgentConnectionContext>> {
|
||||
|
||||
+144
-129
@@ -61,42 +61,21 @@ function setupIPC(accessor: ServicesAccessor): Promise<Server> {
|
||||
}
|
||||
}
|
||||
|
||||
function setup(retry: boolean): Promise<Server> {
|
||||
return serve(environmentService.mainIPCHandle).then(server => {
|
||||
|
||||
// Print --status usage info
|
||||
if (environmentService.args.status) {
|
||||
logService.warn('Warning: The --status argument can only be used if Code is already running. Please run it again after Code has started.');
|
||||
throw new ExpectedError('Terminating...');
|
||||
}
|
||||
|
||||
// Log uploader usage info
|
||||
if (typeof environmentService.args['upload-logs'] !== 'undefined') {
|
||||
logService.warn('Warning: The --upload-logs argument can only be used if Code is already running. Please run it again after Code has started.');
|
||||
throw new ExpectedError('Terminating...');
|
||||
}
|
||||
|
||||
// dock might be hidden at this case due to a retry
|
||||
if (platform.isMacintosh) {
|
||||
app.dock.show();
|
||||
}
|
||||
|
||||
// Set the VSCODE_PID variable here when we are sure we are the first
|
||||
// instance to startup. Otherwise we would wrongly overwrite the PID
|
||||
process.env['VSCODE_PID'] = String(process.pid);
|
||||
|
||||
return server;
|
||||
}, err => {
|
||||
async function setup(retry: boolean): Promise<Server> {
|
||||
let server: Server;
|
||||
try {
|
||||
server = await serve(environmentService.mainIPCHandle);
|
||||
} catch (error) {
|
||||
|
||||
// Handle unexpected errors (the only expected error is EADDRINUSE that
|
||||
// indicates a second instance of Code is running)
|
||||
if (err.code !== 'EADDRINUSE') {
|
||||
if (error.code !== 'EADDRINUSE') {
|
||||
|
||||
// Show a dialog for errors that can be resolved by the user
|
||||
handleStartupDataDirError(environmentService, err);
|
||||
handleStartupDataDirError(environmentService, error);
|
||||
|
||||
// Any other runtime error is just printed to the console
|
||||
return Promise.reject<Server>(err);
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Since we are the second instance, we do not want to show the dock
|
||||
@@ -105,93 +84,120 @@ function setupIPC(accessor: ServicesAccessor): Promise<Server> {
|
||||
}
|
||||
|
||||
// there's a running instance, let's connect to it
|
||||
return connect(environmentService.mainIPCHandle, 'main').then(
|
||||
client => {
|
||||
try {
|
||||
const client = await connect(environmentService.mainIPCHandle, 'main');
|
||||
|
||||
// Tests from CLI require to be the only instance currently
|
||||
if (environmentService.extensionTestsLocationURI && !environmentService.debugExtensionHost.break) {
|
||||
const msg = 'Running extension tests from the command line is currently only supported if no other instance of Code is running.';
|
||||
logService.error(msg);
|
||||
client.dispose();
|
||||
// Tests from CLI require to be the only instance currently
|
||||
if (environmentService.extensionTestsLocationURI && !environmentService.debugExtensionHost.break) {
|
||||
const msg = 'Running extension tests from the command line is currently only supported if no other instance of Code is running.';
|
||||
logService.error(msg);
|
||||
client.dispose();
|
||||
|
||||
return Promise.reject(new Error(msg));
|
||||
}
|
||||
|
||||
// Show a warning dialog after some timeout if it takes long to talk to the other instance
|
||||
// Skip this if we are running with --wait where it is expected that we wait for a while.
|
||||
// Also skip when gathering diagnostics (--status) which can take a longer time.
|
||||
let startupWarningDialogHandle: NodeJS.Timeout;
|
||||
if (!environmentService.wait && !environmentService.status && !environmentService.args['upload-logs']) {
|
||||
startupWarningDialogHandle = setTimeout(() => {
|
||||
showStartupWarningDialog(
|
||||
localize('secondInstanceNoResponse', "Another instance of {0} is running but not responding", product.nameShort),
|
||||
localize('secondInstanceNoResponseDetail', "Please close all other instances and try again.")
|
||||
);
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
const channel = client.getChannel('launch');
|
||||
const service = new LaunchChannelClient(channel);
|
||||
|
||||
// Process Info
|
||||
if (environmentService.args.status) {
|
||||
return instantiationService.invokeFunction(accessor => {
|
||||
return accessor.get(IDiagnosticsService).getDiagnostics(service).then(diagnostics => {
|
||||
console.log(diagnostics);
|
||||
return Promise.reject(new ExpectedError());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Log uploader
|
||||
if (typeof environmentService.args['upload-logs'] !== 'undefined') {
|
||||
return instantiationService.invokeFunction(accessor => {
|
||||
return uploadLogs(service, accessor.get(IRequestService), environmentService)
|
||||
.then(() => Promise.reject(new ExpectedError()));
|
||||
});
|
||||
}
|
||||
|
||||
logService.trace('Sending env to running instance...');
|
||||
|
||||
return windowsAllowSetForegroundWindow(service)
|
||||
.then(() => service.start(environmentService.args, process.env as platform.IProcessEnvironment))
|
||||
.then(() => client.dispose())
|
||||
.then(() => {
|
||||
|
||||
// Now that we started, make sure the warning dialog is prevented
|
||||
if (startupWarningDialogHandle) {
|
||||
clearTimeout(startupWarningDialogHandle);
|
||||
}
|
||||
|
||||
return Promise.reject(new ExpectedError('Sent env to running instance. Terminating...'));
|
||||
});
|
||||
},
|
||||
err => {
|
||||
if (!retry || platform.isWindows || err.code !== 'ECONNREFUSED') {
|
||||
if (err.code === 'EPERM') {
|
||||
showStartupWarningDialog(
|
||||
localize('secondInstanceAdmin', "A second instance of {0} is already running as administrator.", product.nameShort),
|
||||
localize('secondInstanceAdminDetail', "Please close the other instance and try again.")
|
||||
);
|
||||
}
|
||||
|
||||
return Promise.reject<Server>(err);
|
||||
}
|
||||
|
||||
// it happens on Linux and OS X that the pipe is left behind
|
||||
// let's delete it, since we can't connect to it
|
||||
// and then retry the whole thing
|
||||
try {
|
||||
fs.unlinkSync(environmentService.mainIPCHandle);
|
||||
} catch (e) {
|
||||
logService.warn('Could not delete obsolete instance handle', e);
|
||||
return Promise.reject<Server>(e);
|
||||
}
|
||||
|
||||
return setup(false);
|
||||
throw new Error(msg);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// Show a warning dialog after some timeout if it takes long to talk to the other instance
|
||||
// Skip this if we are running with --wait where it is expected that we wait for a while.
|
||||
// Also skip when gathering diagnostics (--status) which can take a longer time.
|
||||
let startupWarningDialogHandle: NodeJS.Timeout | undefined = undefined;
|
||||
if (!environmentService.wait && !environmentService.status && !environmentService.args['upload-logs']) {
|
||||
startupWarningDialogHandle = setTimeout(() => {
|
||||
showStartupWarningDialog(
|
||||
localize('secondInstanceNoResponse', "Another instance of {0} is running but not responding", product.nameShort),
|
||||
localize('secondInstanceNoResponseDetail', "Please close all other instances and try again.")
|
||||
);
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
const channel = client.getChannel('launch');
|
||||
const service = new LaunchChannelClient(channel);
|
||||
|
||||
// Process Info
|
||||
if (environmentService.args.status) {
|
||||
return instantiationService.invokeFunction(async accessor => {
|
||||
const diagnostics = await accessor.get(IDiagnosticsService).getDiagnostics(service);
|
||||
|
||||
console.log(diagnostics);
|
||||
throw new ExpectedError();
|
||||
});
|
||||
}
|
||||
|
||||
// Log uploader
|
||||
if (typeof environmentService.args['upload-logs'] !== 'undefined') {
|
||||
return instantiationService.invokeFunction(async accessor => {
|
||||
await uploadLogs(service, accessor.get(IRequestService), environmentService);
|
||||
|
||||
throw new ExpectedError();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Windows: allow to set foreground
|
||||
if (platform.isWindows) {
|
||||
await windowsAllowSetForegroundWindow(service);
|
||||
}
|
||||
|
||||
// Send environment over...
|
||||
logService.trace('Sending env to running instance...');
|
||||
await service.start(environmentService.args, process.env as platform.IProcessEnvironment);
|
||||
|
||||
// Cleanup
|
||||
await client.dispose();
|
||||
|
||||
// Now that we started, make sure the warning dialog is prevented
|
||||
if (startupWarningDialogHandle) {
|
||||
clearTimeout(startupWarningDialogHandle);
|
||||
}
|
||||
|
||||
throw new ExpectedError('Sent env to running instance. Terminating...');
|
||||
} catch (error) {
|
||||
if (!retry || platform.isWindows || error.code !== 'ECONNREFUSED') {
|
||||
if (error.code === 'EPERM') {
|
||||
showStartupWarningDialog(
|
||||
localize('secondInstanceAdmin', "A second instance of {0} is already running as administrator.", product.nameShort),
|
||||
localize('secondInstanceAdminDetail', "Please close the other instance and try again.")
|
||||
);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
|
||||
// it happens on Linux and OS X that the pipe is left behind
|
||||
// let's delete it, since we can't connect to it
|
||||
// and then retry the whole thing
|
||||
try {
|
||||
fs.unlinkSync(environmentService.mainIPCHandle);
|
||||
} catch (error) {
|
||||
logService.warn('Could not delete obsolete instance handle', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return setup(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Print --status usage info
|
||||
if (environmentService.args.status) {
|
||||
logService.warn('Warning: The --status argument can only be used if Code is already running. Please run it again after Code has started.');
|
||||
throw new ExpectedError('Terminating...');
|
||||
}
|
||||
|
||||
// Log uploader usage info
|
||||
if (typeof environmentService.args['upload-logs'] !== 'undefined') {
|
||||
logService.warn('Warning: The --upload-logs argument can only be used if Code is already running. Please run it again after Code has started.');
|
||||
throw new ExpectedError('Terminating...');
|
||||
}
|
||||
|
||||
// dock might be hidden at this case due to a retry
|
||||
if (platform.isMacintosh) {
|
||||
app.dock.show();
|
||||
}
|
||||
|
||||
// Set the VSCODE_PID variable here when we are sure we are the first
|
||||
// instance to startup. Otherwise we would wrongly overwrite the PID
|
||||
process.env['VSCODE_PID'] = String(process.pid);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
return setup(true);
|
||||
@@ -258,7 +264,7 @@ function patchEnvironment(environmentService: IEnvironmentService): typeof proce
|
||||
return instanceEnvironment;
|
||||
}
|
||||
|
||||
function startup(args: ParsedArgs): void {
|
||||
async function startup(args: ParsedArgs): Promise<void> {
|
||||
|
||||
// We need to buffer the spdlog logs until we are sure
|
||||
// we are the only instance running, otherwise we'll have concurrent
|
||||
@@ -266,28 +272,37 @@ function startup(args: ParsedArgs): void {
|
||||
const bufferLogService = new BufferLogService();
|
||||
|
||||
const instantiationService = createServices(args, bufferLogService);
|
||||
instantiationService.invokeFunction(accessor => {
|
||||
const environmentService = accessor.get(IEnvironmentService);
|
||||
const stateService = accessor.get(IStateService);
|
||||
try {
|
||||
await instantiationService.invokeFunction(async accessor => {
|
||||
const environmentService = accessor.get(IEnvironmentService);
|
||||
const stateService = accessor.get(IStateService);
|
||||
|
||||
// Patch `process.env` with the instance's environment
|
||||
const instanceEnvironment = patchEnvironment(environmentService);
|
||||
// Patch `process.env` with the instance's environment
|
||||
const instanceEnvironment = patchEnvironment(environmentService);
|
||||
|
||||
// Startup
|
||||
return initServices(environmentService, stateService as StateService)
|
||||
.then(() => instantiationService.invokeFunction(setupIPC), error => {
|
||||
// Startup
|
||||
try {
|
||||
await initServices(environmentService, stateService as StateService);
|
||||
} catch (error) {
|
||||
|
||||
// Show a dialog for errors that can be resolved by the user
|
||||
handleStartupDataDirError(environmentService, error);
|
||||
|
||||
return Promise.reject(error);
|
||||
})
|
||||
.then(mainIpcServer => {
|
||||
createSpdLogService('main', bufferLogService.getLevel(), environmentService.logsPath).then(logger => bufferLogService.logger = logger);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return instantiationService.createInstance(CodeApplication, mainIpcServer, instanceEnvironment).startup();
|
||||
});
|
||||
}).then(null, err => instantiationService.invokeFunction(quit, err));
|
||||
const mainIpcServer = await instantiationService.invokeFunction(setupIPC);
|
||||
|
||||
(async () => {
|
||||
const logger = await createSpdLogService('main', bufferLogService.getLevel(), environmentService.logsPath);
|
||||
bufferLogService.logger = logger;
|
||||
})();
|
||||
|
||||
return instantiationService.createInstance(CodeApplication, mainIpcServer, instanceEnvironment).startup();
|
||||
});
|
||||
} catch (error) {
|
||||
instantiationService.invokeFunction(quit, error);
|
||||
}
|
||||
}
|
||||
|
||||
function createServices(args: ParsedArgs, bufferLogService: BufferLogService): IInstantiationService {
|
||||
|
||||
@@ -1536,14 +1536,13 @@ export class WindowsManager implements IWindowsMainService {
|
||||
return state;
|
||||
}
|
||||
|
||||
reload(win: ICodeWindow, cli?: ParsedArgs): void {
|
||||
async reload(win: ICodeWindow, cli?: ParsedArgs): Promise<void> {
|
||||
|
||||
// Only reload when the window has not vetoed this
|
||||
this.lifecycleService.unload(win, UnloadReason.RELOAD).then(veto => {
|
||||
if (!veto) {
|
||||
win.reload(undefined, cli);
|
||||
}
|
||||
});
|
||||
const veto = await this.lifecycleService.unload(win, UnloadReason.RELOAD);
|
||||
if (!veto) {
|
||||
win.reload(undefined, cli);
|
||||
}
|
||||
}
|
||||
|
||||
closeWorkspace(win: ICodeWindow): void {
|
||||
@@ -1554,8 +1553,10 @@ export class WindowsManager implements IWindowsMainService {
|
||||
});
|
||||
}
|
||||
|
||||
enterWorkspace(win: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | undefined> {
|
||||
return this.workspacesManager.enterWorkspace(win, path).then(result => result ? this.doEnterWorkspace(win, result) : undefined);
|
||||
async enterWorkspace(win: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | undefined> {
|
||||
const result = await this.workspacesManager.enterWorkspace(win, path);
|
||||
|
||||
return result ? this.doEnterWorkspace(win, result) : undefined;
|
||||
}
|
||||
|
||||
private doEnterWorkspace(win: ICodeWindow, result: IEnterWorkspaceResult): IEnterWorkspaceResult {
|
||||
@@ -1751,8 +1752,10 @@ export class WindowsManager implements IWindowsMainService {
|
||||
const paths = await this.dialogs.pick({ ...options, pickFolders: true, pickFiles: true, title });
|
||||
if (paths) {
|
||||
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFileFolder', options.telemetryExtraData);
|
||||
const urisToOpen = await Promise.all(paths.map(path => {
|
||||
return dirExists(path).then(isDir => isDir ? { folderUri: URI.file(path) } : { fileUri: URI.file(path) });
|
||||
const urisToOpen = await Promise.all(paths.map(async path => {
|
||||
const isDir = await dirExists(path);
|
||||
|
||||
return isDir ? { folderUri: URI.file(path) } : { fileUri: URI.file(path) };
|
||||
}));
|
||||
this.open({
|
||||
context: OpenContext.DIALOG,
|
||||
@@ -1880,7 +1883,7 @@ class Dialogs {
|
||||
this.noWindowDialogQueue = new Queue<void>();
|
||||
}
|
||||
|
||||
pick(options: IInternalNativeOpenDialogOptions): Promise<string[] | undefined> {
|
||||
async pick(options: IInternalNativeOpenDialogOptions): Promise<string[] | undefined> {
|
||||
|
||||
// Ensure dialog options
|
||||
const dialogOptions: Electron.OpenDialogOptions = {
|
||||
@@ -1913,16 +1916,16 @@ class Dialogs {
|
||||
// Show Dialog
|
||||
const focusedWindow = (typeof options.windowId === 'number' ? this.windowsMainService.getWindowById(options.windowId) : undefined) || this.windowsMainService.getFocusedWindow();
|
||||
|
||||
return this.showOpenDialog(dialogOptions, focusedWindow).then(paths => {
|
||||
if (paths && paths.length > 0) {
|
||||
const paths = await this.showOpenDialog(dialogOptions, focusedWindow);
|
||||
if (paths && paths.length > 0) {
|
||||
|
||||
// Remember path in storage for next time
|
||||
this.stateService.setItem(Dialogs.workingDirPickerStorageKey, dirname(paths[0]));
|
||||
return paths;
|
||||
}
|
||||
// Remember path in storage for next time
|
||||
this.stateService.setItem(Dialogs.workingDirPickerStorageKey, dirname(paths[0]));
|
||||
|
||||
return undefined;
|
||||
});
|
||||
return paths;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private getDialogQueue(window?: ICodeWindow): Queue<any> {
|
||||
@@ -2028,28 +2031,26 @@ class WorkspacesManager {
|
||||
private readonly windowsMainService: IWindowsMainService,
|
||||
) { }
|
||||
|
||||
enterWorkspace(window: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | null> {
|
||||
async enterWorkspace(window: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | null> {
|
||||
if (!window || !window.win || !window.isReady) {
|
||||
return Promise.resolve(null); // return early if the window is not ready or disposed
|
||||
return null; // return early if the window is not ready or disposed
|
||||
}
|
||||
|
||||
return this.isValidTargetWorkspacePath(window, path).then(isValid => {
|
||||
if (!isValid) {
|
||||
return null; // return early if the workspace is not valid
|
||||
}
|
||||
const workspaceIdentifier = getWorkspaceIdentifier(path);
|
||||
return this.doOpenWorkspace(window, workspaceIdentifier);
|
||||
});
|
||||
const isValid = await this.isValidTargetWorkspacePath(window, path);
|
||||
if (!isValid) {
|
||||
return null; // return early if the workspace is not valid
|
||||
}
|
||||
|
||||
return this.doOpenWorkspace(window, getWorkspaceIdentifier(path));
|
||||
}
|
||||
|
||||
private isValidTargetWorkspacePath(window: ICodeWindow, path?: URI): Promise<boolean> {
|
||||
private async isValidTargetWorkspacePath(window: ICodeWindow, path?: URI): Promise<boolean> {
|
||||
if (!path) {
|
||||
return Promise.resolve(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (window.openedWorkspace && isEqual(window.openedWorkspace.configPath, path)) {
|
||||
return Promise.resolve(false); // window is already opened on a workspace with that path
|
||||
return false; // window is already opened on a workspace with that path
|
||||
}
|
||||
|
||||
// Prevent overwriting a workspace that is currently opened in another window
|
||||
@@ -2063,10 +2064,12 @@ class WorkspacesManager {
|
||||
noLink: true
|
||||
};
|
||||
|
||||
return this.windowsMainService.showMessageBox(options, this.windowsMainService.getFocusedWindow()).then(() => false);
|
||||
await this.windowsMainService.showMessageBox(options, this.windowsMainService.getFocusedWindow());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return Promise.resolve(true); // OK
|
||||
return true; // OK
|
||||
}
|
||||
|
||||
private doOpenWorkspace(window: ICodeWindow, workspace: IWorkspaceIdentifier): IEnterWorkspaceResult {
|
||||
@@ -2090,14 +2093,16 @@ class WorkspacesManager {
|
||||
|
||||
return { workspace, backupPath };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function resourceFromURIToOpen(u: IURIToOpen) {
|
||||
function resourceFromURIToOpen(u: IURIToOpen): URI {
|
||||
if (isWorkspaceToOpen(u)) {
|
||||
return u.workspaceUri;
|
||||
} else if (isFolderToOpen(u)) {
|
||||
}
|
||||
|
||||
if (isFolderToOpen(u)) {
|
||||
return u.folderUri;
|
||||
}
|
||||
|
||||
return u.fileUri;
|
||||
}
|
||||
Reference in New Issue
Block a user