Initial VS Code 1.19 source merge (#571)

* Initial 1.19 xcopy

* Fix yarn build

* Fix numerous build breaks

* Next batch of build break fixes

* More build break fixes

* Runtime breaks

* Additional post merge fixes

* Fix windows setup file

* Fix test failures.

* Update license header blocks to refer to source eula
This commit is contained in:
Karl Burtram
2018-01-28 23:37:17 -08:00
committed by GitHub
parent 9a1ac20710
commit 251ae01c3e
8009 changed files with 93378 additions and 35634 deletions

View File

@@ -5,22 +5,25 @@
'use strict';
import { app } from 'electron';
import { app, dialog } from 'electron';
import { assign } from 'vs/base/common/objects';
import * as platform from 'vs/base/common/platform';
import product from 'vs/platform/node/product';
import * as path from 'path';
import { parseMainProcessArgv } from 'vs/platform/environment/node/argv';
import { mkdirp } from 'vs/base/node/pfs';
import { mkdirp, readdir, rimraf } from 'vs/base/node/pfs';
import { validatePaths } from 'vs/code/node/paths';
import { LifecycleService, ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain';
import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net';
import { TPromise } from 'vs/base/common/winjs.base';
import { ILaunchChannel, LaunchChannelClient } from './launch';
import { ILaunchChannel, LaunchChannelClient } from 'vs/code/electron-main/launch';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { ILogService, LogMainService } from 'vs/platform/log/common/log';
import { IStorageService, StorageService } from 'vs/platform/storage/node/storage';
import { ILogService, ConsoleLogMainService, MultiplexLogService } from 'vs/platform/log/common/log';
import { StateService } from 'vs/platform/state/node/stateService';
import { IStateService } from 'vs/platform/state/common/state';
import { IBackupMainService } from 'vs/platform/backup/common/backup';
import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
@@ -37,16 +40,30 @@ import { HistoryMainService } from 'vs/platform/history/electron-main/historyMai
import { IHistoryMainService } from 'vs/platform/history/common/history';
import { WorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { IWorkspacesMainService } from 'vs/platform/workspaces/common/workspaces';
import { localize } from 'vs/nls';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { createLogService } from 'vs/platform/log/node/spdlogService';
import { printDiagnostics } from 'vs/code/electron-main/diagnostics';
function createServices(args: ParsedArgs): IInstantiationService {
const services = new ServiceCollection();
services.set(IEnvironmentService, new SyncDescriptor(EnvironmentService, args, process.execPath));
services.set(ILogService, new SyncDescriptor(LogMainService));
const environmentService = new EnvironmentService(args, process.execPath);
const spdlogService = createLogService('main', environmentService);
const consoleLogService = new ConsoleLogMainService(environmentService);
const logService = new MultiplexLogService([consoleLogService, spdlogService]);
process.once('exit', () => logService.dispose());
// Eventually cleanup
setTimeout(() => cleanupOlderLogs(environmentService).then(null, err => console.error(err)), 10000);
services.set(IEnvironmentService, environmentService);
services.set(ILogService, logService);
services.set(IWorkspacesMainService, new SyncDescriptor(WorkspacesMainService));
services.set(IHistoryMainService, new SyncDescriptor(HistoryMainService));
services.set(ILifecycleService, new SyncDescriptor(LifecycleService));
services.set(IStorageService, new SyncDescriptor(StorageService));
services.set(IStateService, new SyncDescriptor(StateService));
services.set(IConfigurationService, new SyncDescriptor(ConfigurationService));
services.set(IRequestService, new SyncDescriptor(RequestService));
services.set(IURLService, new SyncDescriptor(URLService, args['open-url'] ? args._urls : []));
@@ -55,12 +72,28 @@ function createServices(args: ParsedArgs): IInstantiationService {
return new InstantiationService(services, true);
}
/**
* Cleans up older logs, while keeping the 10 most recent ones.
*/
async function cleanupOlderLogs(environmentService: EnvironmentService): TPromise<void> {
const currentLog = path.basename(environmentService.logsPath);
const logsRoot = path.dirname(environmentService.logsPath);
const children = await readdir(logsRoot);
const allSessions = children.filter(name => /^\d{8}T\d{6}$/.test(name));
const oldSessions = allSessions.sort().filter((d, i) => d !== currentLog);
const toDelete = oldSessions.slice(0, Math.max(0, oldSessions.length - 9));
await TPromise.join(toDelete.map(name => rimraf(path.join(logsRoot, name))));
}
function createPaths(environmentService: IEnvironmentService): TPromise<any> {
const paths = [
environmentService.appSettingsHome,
environmentService.extensionsPath,
environmentService.nodeCachedDataDir
environmentService.nodeCachedDataDir,
environmentService.logsPath
];
return TPromise.join(paths.map(p => p && mkdirp(p))) as TPromise<any>;
}
@@ -73,11 +106,11 @@ function setupIPC(accessor: ServicesAccessor): TPromise<Server> {
const environmentService = accessor.get(IEnvironmentService);
function allowSetForegroundWindow(service: LaunchChannelClient): TPromise<void> {
let promise = TPromise.as<void>(void 0);
let promise = TPromise.wrap<void>(void 0);
if (platform.isWindows) {
promise = service.getMainProcessId()
.then(processId => {
logService.log('Sending some foreground love to the running instance:', processId);
logService.trace('Sending some foreground love to the running instance:', processId);
try {
const { allowSetForegroundWindow } = <any>require.__$__nodeRequire('windows-foreground-love');
@@ -93,10 +126,22 @@ function setupIPC(accessor: ServicesAccessor): TPromise<Server> {
function setup(retry: boolean): TPromise<Server> {
return serve(environmentService.mainIPCHandle).then(server => {
if (platform.isMacintosh) {
app.dock.show(); // dock might be hidden at this case due to a retry
// 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...');
}
// 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 => {
if (err.code !== 'EADDRINUSE') {
@@ -121,18 +166,53 @@ function setupIPC(accessor: ServicesAccessor): TPromise<Server> {
return TPromise.wrapError<Server>(new Error(msg));
}
logService.log('Sending env to running instance...');
// 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: number;
if (!environmentService.wait && !environmentService.status) {
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<ILaunchChannel>('launch');
const service = new LaunchChannelClient(channel);
// Process Info
if (environmentService.args.status) {
return service.getMainProcessInfo().then(info => {
return printDiagnostics(info).then(() => TPromise.wrapError(new ExpectedError()));
});
}
logService.trace('Sending env to running instance...');
return allowSetForegroundWindow(service)
.then(() => service.start(environmentService.args, process.env))
.then(() => client.dispose())
.then(() => TPromise.wrapError(new ExpectedError('Sent env to running instance. Terminating...')));
.then(() => {
// Now that we started, make sure the warning dialog is prevented
if (startupWarningDialogHandle) {
clearTimeout(startupWarningDialogHandle);
}
return TPromise.wrapError(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 TPromise.wrapError<Server>(err);
}
@@ -142,7 +222,7 @@ function setupIPC(accessor: ServicesAccessor): TPromise<Server> {
try {
fs.unlinkSync(environmentService.mainIPCHandle);
} catch (e) {
logService.log('Fatal error deleting obsolete instance handle', e);
logService.warn('Could not delete obsolete instance handle', e);
return TPromise.wrapError<Server>(e);
}
@@ -155,6 +235,17 @@ function setupIPC(accessor: ServicesAccessor): TPromise<Server> {
return setup(true);
}
function showStartupWarningDialog(message: string, detail: string): void {
dialog.showMessageBox(null, {
title: product.nameLong,
type: 'warning',
buttons: [mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
message,
detail,
noLink: true
});
}
function quit(accessor: ServicesAccessor, reason?: ExpectedError | Error): void {
const logService = accessor.get(ILogService);
const lifecycleService = accessor.get(ILifecycleService);
@@ -163,14 +254,16 @@ function quit(accessor: ServicesAccessor, reason?: ExpectedError | Error): void
if (reason) {
if ((reason as ExpectedError).isExpected) {
logService.log(reason.message);
if (reason.message) {
logService.trace(reason.message);
}
} else {
exitCode = 1; // signal error to the outside
if (reason.stack) {
console.error(reason.stack);
logService.error(reason.stack);
} else {
console.error(`Startup error: ${reason.toString()}`);
logService.error(`Startup error: ${reason.toString()}`);
}
}
}
@@ -198,19 +291,16 @@ function main() {
// Patch `process.env` with the instance's environment
const environmentService = accessor.get(IEnvironmentService);
const instanceEnv: typeof process.env = {
VSCODE_PID: String(process.pid),
VSCODE_IPC_HOOK: environmentService.mainIPCHandle,
VSCODE_NLS_CONFIG: process.env['VSCODE_NLS_CONFIG']
VSCODE_NLS_CONFIG: process.env['VSCODE_NLS_CONFIG'],
VSCODE_LOGS: process.env['VSCODE_LOGS']
};
assign(process.env, instanceEnv);
// Startup
return instantiationService.invokeFunction(a => createPaths(a.get(IEnvironmentService)))
.then(() => instantiationService.invokeFunction(setupIPC))
.then(mainIpcServer => {
const app = instantiationService.createInstance(CodeApplication, mainIpcServer, instanceEnv);
app.startup();
});
.then(mainIpcServer => instantiationService.createInstance(CodeApplication, mainIpcServer, instanceEnv).startup());
}).done(null, err => instantiationService.invokeFunction(quit, err));
}