diff --git a/src/vs/code/buildfile.js b/src/vs/code/buildfile.js index e2f72b52ddae3b5b3794d3bbb08bbc62b2dd88a7..d722dc5e6fa310bf9c0e1eed1cc0da6fed3cb2bc 100644 --- a/src/vs/code/buildfile.js +++ b/src/vs/code/buildfile.js @@ -19,6 +19,7 @@ exports.collectModules= function() { return [ createModuleDescription('vs/code/electron-main/main', []), createModuleDescription('vs/code/node/cli', []), + createModuleDescription('vs/code/node/cliProcessMain', ['vs/code/node/cli']), createModuleDescription('vs/code/node/sharedProcessMain', []) ]; }; \ No newline at end of file diff --git a/src/vs/code/node/argv.ts b/src/vs/code/node/argv.ts index bb63f21e2890176815998d422d4c32cb00baad73..eafcac27695c4b957e591b479499d995a0fcbb1d 100644 --- a/src/vs/code/node/argv.ts +++ b/src/vs/code/node/argv.ts @@ -28,6 +28,7 @@ export interface ParsedArgs extends minimist.ParsedArgs { timestamp: string; debugBrkPluginHost: string; debugPluginHost: string; + 'list-extensions': boolean; } const options: minimist.Opts = { @@ -50,7 +51,8 @@ const options: minimist.Opts = { 'performance', 'verbose', 'logExtensionHostCommunication', - 'disable-extensions' + 'disable-extensions', + 'list-extensions' ], alias: { help: 'h', @@ -89,4 +91,5 @@ ${ indent } window. ${ indent }--user-data-dir Specifies the directory that user data is kept in, ${ indent } useful when running as root. ${ indent }-v, --version Print version. -${ indent }-w, --wait Wait for the window to be closed before returning.`; +${ indent }-w, --wait Wait for the window to be closed before returning. +${ indent }--list-extensions List the installed extensions.`; diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 86dffefb895e40b7554fd366ae2d92e254b9ec89..b11cf38726a79d9affc1a9383ab08f986aa9ca9c 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -4,17 +4,29 @@ *--------------------------------------------------------------------------------------------*/ import { spawn } from 'child_process'; +import { TPromise } from 'vs/base/common/winjs.base'; import { assign } from 'vs/base/common/objects'; -import { parseArgs, helpMessage } from 'vs/code/node/argv'; -import pkg from 'vs/code/node/package'; +import { parseArgs, helpMessage, ParsedArgs } from 'vs/code/node/argv'; +import pkg from 'vs/platform/package'; -export function main(args: string[]) { +function shouldSpawnCliProcess(argv: ParsedArgs): boolean { + return argv['list-extensions']; +} + +interface IMainCli { + main: (argv: ParsedArgs) => TPromise; +} + +export function main(args: string[]): TPromise { const argv = parseArgs(args); if (argv.help) { console.log(helpMessage); } else if (argv.version) { console.log(pkg.version); + } else if (shouldSpawnCliProcess(argv)) { + const mainCli = new TPromise(c => require(['vs/code/node/cliProcessMain'], c)); + return mainCli.then(cli => cli.main(argv)); } else { const env = assign({}, process.env, { // this will signal Code that it was spawned from this module @@ -30,12 +42,16 @@ export function main(args: string[]) { }); if (argv.wait) { - child.on('exit', process.exit); - return; + return new TPromise(c => child.once('exit', ()=> c(null))); } } - process.exit(0); + return TPromise.as(null); } -main(process.argv.slice(2)); +main(process.argv.slice(2)) + .then(() => process.exit(0)) + .then(null, err => { + console.error(err.stack ? err.stack : err); + process.exit(1); + }); diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts new file mode 100644 index 0000000000000000000000000000000000000000..57a2e19589ca7b5fd5ca7e0270b77ef30a96a683 --- /dev/null +++ b/src/vs/code/node/cliProcessMain.ts @@ -0,0 +1,56 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ParsedArgs } from 'vs/code/node/argv'; +import { TPromise } from 'vs/base/common/winjs.base'; +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; +import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; +import { IEnvironmentService } from 'vs/platform/environment/common/environment'; +import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; +import { IEventService } from 'vs/platform/event/common/event'; +import { EventService } from 'vs/platform/event/common/eventService'; +import { IExtensionManagementService, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { getExtensionId } from 'vs/platform/extensionManagement/node/extensionManagementUtil'; +import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService'; +import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; +import { ITelemetryService, NullTelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import { IRequestService } from 'vs/platform/request/common/request'; +import { NodeRequestService } from 'vs/platform/request/node/nodeRequestService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { NodeConfigurationService } from 'vs/platform/configuration/node/nodeConfigurationService'; + +class Main { + + constructor( + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, + @IExtensionGalleryService private extensionGalleryService: IExtensionGalleryService + ) {} + + run(argv: ParsedArgs): TPromise { + if (argv['list-extensions']) { + return this.extensionManagementService.getInstalled().then(extensions => { + extensions.forEach(e => console.log(`${ e.displayName } (${ getExtensionId(e) })`)); + }); + } + } +} + +export function main(argv: ParsedArgs): TPromise { + const services = new ServiceCollection(); + + services.set(IEventService, new SyncDescriptor(EventService)); + services.set(IEnvironmentService, new SyncDescriptor(EnvironmentService)); + services.set(ITelemetryService, NullTelemetryService); + services.set(IConfigurationService, new SyncDescriptor(NodeConfigurationService)); + services.set(IRequestService, new SyncDescriptor(NodeRequestService)); + services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); + services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService)); + + const instantiationService: IInstantiationService = new InstantiationService(services); + const main = instantiationService.createInstance(Main); + return main.run(argv); +}