提交 5c6a7d6e 编写于 作者: B Benjamin Pasero

code --wait should return control when closing window (fixes #18199)

上级 bed46e2d
......@@ -12,7 +12,6 @@ import { IURLService } from 'vs/platform/url/common/url';
import { IProcessEnvironment } from 'vs/base/common/platform';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { once } from 'vs/base/common/event';
import { OpenContext } from 'vs/platform/windows/common/windows';
import { IWindowsMainService, ICodeWindow } from "vs/platform/windows/electron-main/windows";
......@@ -115,16 +114,7 @@ export class LaunchService implements ILaunchService {
// If the other instance is waiting to be killed, we hook up a window listener if one window
// is being used and only then resolve the startup promise which will kill this second instance
if (args.wait && usedWindows.length === 1 && usedWindows[0]) {
const windowId = usedWindows[0].id;
return new TPromise<void>((c, e) => {
const onceWindowClose = once(this.windowsService.onWindowClose);
onceWindowClose(id => {
if (id === windowId) {
c(null);
}
});
});
return this.windowsService.waitForWindowClose(usedWindows[0].id);
}
return TPromise.as(null);
......
......@@ -315,6 +315,13 @@ export class WindowsManager implements IWindowsMainService {
this._onPathsOpen.fire(windowsToOpen);
}
// If we got started with --wait from the CLI, we need to signal to the outside when the window
// used for the edit operation is closed so that the waiting process can continue. We do this by
// deleting the waitMarkerFilePath.
if (openConfig.context === OpenContext.CLI && openConfig.cli.wait && openConfig.cli.waitMarkerFilePath && usedWindows.length === 1 && usedWindows[0]) {
this.waitForWindowClose(usedWindows[0].id).done(() => fs.unlink(openConfig.cli.waitMarkerFilePath, error => void 0));
}
return usedWindows;
}
......@@ -1044,6 +1051,17 @@ export class WindowsManager implements IWindowsMainService {
this.open({ context, cli: this.environmentService.args, forceNewWindow: true, forceEmpty: true });
}
public waitForWindowClose(windowId: number): TPromise<void> {
return new TPromise<void>(c => {
const toDispose = this.onWindowClose(id => {
if (id === windowId) {
toDispose.dispose();
c(null);
}
});
});
}
public sendToFocused(channel: string, ...args: any[]): void {
const focusedWindow = this.getFocusedWindow() || this.getLastActiveWindow();
......
......@@ -11,6 +11,10 @@ import { ParsedArgs } from 'vs/platform/environment/common/environment';
import product from 'vs/platform/node/product';
import pkg from 'vs/platform/node/package';
import * as fs from 'fs';
import * as paths from 'path';
import * as os from 'os';
function shouldSpawnCliProcess(argv: ParsedArgs): boolean {
return argv['list-extensions'] || !!argv['install-extension'] || !!argv['uninstall-extension'];
}
......@@ -49,9 +53,34 @@ export function main(argv: string[]): TPromise<void> {
env['ELECTRON_ENABLE_LOGGING'] = '1';
}
// If we are started with --wait create a random temporary file
// and pass it over to the starting instance. We can use this file
// to wait for it to be deleted to monitor that the edited file
// is closed and then exit the waiting process.
let waitMarkerFilePath: string;
if (args.wait) {
let waitMarkerError: Error;
const randomTmpFile = paths.join(os.tmpdir(), Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10));
try {
fs.writeFileSync(randomTmpFile, '');
waitMarkerFilePath = randomTmpFile;
argv.push('--waitMarkerFilePath', waitMarkerFilePath);
} catch (error) {
waitMarkerError = error;
}
if (args.verbose) {
if (waitMarkerError) {
console.error(`Failed to create marker file for --wait: ${waitMarkerError.toString()}`);
} else {
console.log(`Marker file for --wait created: ${waitMarkerFilePath}`);
}
}
}
const options = {
detached: true,
env,
env
};
if (!args.verbose) {
......@@ -65,9 +94,27 @@ export function main(argv: string[]): TPromise<void> {
child.stderr.on('data', (data: Buffer) => console.log(data.toString('utf8').trim()));
}
if (args.wait || args.verbose) {
if (args.verbose) {
return new TPromise<void>(c => child.once('exit', () => c(null)));
}
if (args.wait && waitMarkerFilePath) {
return new TPromise<void>(c => {
// Complete when process exits
child.once('exit', () => c(null));
// Complete when wait marker file is deleted
const interval = setInterval(() => {
fs.exists(waitMarkerFilePath, exists => {
if (!exists) {
clearInterval(interval);
c(null);
}
});
}, 1000);
});
}
}
return TPromise.as(null);
......
......@@ -11,6 +11,7 @@ export interface ParsedArgs {
help?: boolean;
version?: boolean;
wait?: boolean;
waitMarkerFilePath?: string;
diff?: boolean;
goto?: boolean;
'new-window'?: boolean;
......
......@@ -55,6 +55,7 @@ export interface IWindowsMainService {
pickFolder(options?: { buttonLabel: string; title: string; }): TPromise<string[]>;
focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow;
getLastActiveWindow(): ICodeWindow;
waitForWindowClose(windowId: number): TPromise<void>;
findWindow(workspacePath: string, filePath?: string, extensionDevelopmentPath?: string): ICodeWindow;
openNewWindow(context: OpenContext): void;
sendToFocused(channel: string, ...args: any[]): void;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册