cliProcessMain.ts 7.6 KB
Newer Older
J
Joao Moreno 已提交
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

J
Joao Moreno 已提交
6
import { localize } from 'vs/nls';
7 8
import product from 'vs/platform/product';
import pkg from 'vs/platform/package';
J
Joao Moreno 已提交
9 10
import { ParsedArgs } from 'vs/code/node/argv';
import { TPromise } from 'vs/base/common/winjs.base';
11
import { sequence } from 'vs/base/common/async';
J
Joao Moreno 已提交
12
import { IPager } from 'vs/base/common/paging';
J
Joao Moreno 已提交
13 14 15 16 17 18 19 20
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';
J
Joao Moreno 已提交
21
import { IExtensionManagementService, IExtensionGalleryService, IExtensionManifest, IGalleryExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
J
Joao Moreno 已提交
22 23
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
24 25 26
import { ITelemetryService, combinedAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService';
import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties';
J
Joao Moreno 已提交
27 28 29 30
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';
31
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
J
Joao Moreno 已提交
32

J
Joao Moreno 已提交
33
const notFound = id => localize('notFound', "Extension '{0}' not found.", id);
J
Joao Moreno 已提交
34
const notInstalled = id => localize('notInstalled', "Extension '{0}' is not installed.", id);
J
Joao Moreno 已提交
35
const useId = localize('useId', "Make sure you use the full extension ID, including the publisher, eg: {0}", 'ms-vscode.csharp');
J
Joao Moreno 已提交
36

J
Joao Moreno 已提交
37 38 39 40
function getId(manifest: IExtensionManifest): string {
	return `${ manifest.publisher }.${ manifest.name }`;
}

J
Joao Moreno 已提交
41 42 43 44 45 46 47 48
class Main {

	constructor(
		@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
		@IExtensionGalleryService private extensionGalleryService: IExtensionGalleryService
	) {}

	run(argv: ParsedArgs): TPromise<any> {
J
Joao Moreno 已提交
49 50
		// TODO@joao - make this contributable

J
Joao Moreno 已提交
51
		if (argv['list-extensions']) {
J
Joao Moreno 已提交
52 53
			return this.listExtensions();
		} else if (argv['install-extension']) {
54 55 56
			const arg = argv['install-extension'];
			const ids: string[] = typeof arg === 'string' ? [arg] : arg;
			return this.installExtension(ids);
J
Joao Moreno 已提交
57
		} else if (argv['uninstall-extension']) {
58 59 60
			const arg = argv['uninstall-extension'];
			const ids: string[] = typeof arg === 'string' ? [arg] : arg;
			return this.uninstallExtension(ids);
J
Joao Moreno 已提交
61 62
		}
	}
J
Joao Moreno 已提交
63 64 65

	private listExtensions(): TPromise<any> {
		return this.extensionManagementService.getInstalled().then(extensions => {
J
Joao Moreno 已提交
66
			extensions.forEach(e => console.log(getId(e.manifest)));
J
Joao Moreno 已提交
67 68 69
		});
	}

70
	private installExtension(ids: string[]): TPromise<any> {
71 72
		return sequence(ids.map(id => () => {
			return this.extensionManagementService.getInstalled().then(installed => {
J
Joao Moreno 已提交
73
				const isInstalled = installed.some(e => getId(e.manifest) === id);
74 75

				if (isInstalled) {
76
					console.log(localize('alreadyInstalled', "Extension '{0}' is already installed.", id));
J
Joao Moreno 已提交
77
					return TPromise.as(null);
78
				}
J
Joao Moreno 已提交
79

80
				return this.extensionGalleryService.query({ names: [id] })
J
Joao Moreno 已提交
81
					.then<IPager<IGalleryExtension>>(null, err => {
J
Joao Moreno 已提交
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
						if (err.responseText) {
							try {
								const response = JSON.parse(err.responseText);
								return TPromise.wrapError(response.message);
							} catch (e) {
								return TPromise.wrapError(err);
							}
						}
					})
					.then(result => {
						const [extension] = result.firstPage;

						if (!extension) {
							return TPromise.wrapError(`${ notFound(id) }\n${ useId }`);
						}

						console.log(localize('foundExtension', "Found '{0}' in the marketplace.", id));
						console.log(localize('installing', "Installing..."));

J
Joao Moreno 已提交
101
						return this.extensionManagementService.install(extension).then(() => {
J
Joao Moreno 已提交
102
							console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed!", id, extension.versions[0].version));
J
Joao Moreno 已提交
103
						});
104
					});
105 106
			});
		}));
J
Joao Moreno 已提交
107
	}
J
Joao Moreno 已提交
108

109 110 111
	private uninstallExtension(ids: string[]): TPromise<any> {
		return sequence(ids.map(id => () => {
			return this.extensionManagementService.getInstalled().then(installed => {
J
Joao Moreno 已提交
112
				const [extension] = installed.filter(e => getId(e.manifest) === id);
J
Joao Moreno 已提交
113

114 115 116
				if (!extension) {
					return TPromise.wrapError(`${ notInstalled(id) }\n${ useId }`);
				}
J
Joao Moreno 已提交
117

118
				console.log(localize('uninstalling', "Uninstalling {0}...", id));
J
Joao Moreno 已提交
119

120 121 122
				return this.extensionManagementService.uninstall(extension).then(() => {
					console.log(localize('successUninstall', "Extension '{0}' was successfully uninstalled!", id));
				});
J
Joao Moreno 已提交
123
			});
124
		}));
J
Joao Moreno 已提交
125
	}
J
Joao Moreno 已提交
126 127
}

128 129
const eventPrefix = 'monacoworkbench';

J
Joao Moreno 已提交
130 131 132 133 134
export function main(argv: ParsedArgs): TPromise<void> {
	const services = new ServiceCollection();
	services.set(IEnvironmentService, new SyncDescriptor(EnvironmentService));

	const instantiationService: IInstantiationService = new InstantiationService(services);
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176

	return instantiationService.invokeFunction(accessor => {
		const services = new ServiceCollection();
		services.set(IEventService, new SyncDescriptor(EventService));
		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 { appRoot, extensionsPath, extensionDevelopmentPath, isBuilt } = accessor.get(IEnvironmentService);

		if (isBuilt && !extensionDevelopmentPath && product.enableTelemetry) {
			const appenders: AppInsightsAppender[] = [];

			if (product.aiConfig && product.aiConfig.key) {
				appenders.push(new AppInsightsAppender(eventPrefix, null, product.aiConfig.key));
			}

			if (product.aiConfig && product.aiConfig.asimovKey) {
				appenders.push(new AppInsightsAppender(eventPrefix, null, product.aiConfig.asimovKey));
			}

			// It is important to dispose the AI adapter properly because
			// only then they flush remaining data.
			process.once('exit', () => appenders.forEach(a => a.dispose()));

			const config: ITelemetryServiceConfig = {
				appender: combinedAppender(...appenders),
				commonProperties: resolveCommonProperties(product.commit, pkg.version),
				piiPaths: [appRoot, extensionsPath]
			};

			services.set(ITelemetryService, new SyncDescriptor(TelemetryService, config));
		} else {
			services.set(ITelemetryService, NullTelemetryService);
		}

		const instantiationService2 = instantiationService.createChild(services);
		const main = instantiationService2.createInstance(Main);

		return main.run(argv);
	});
J
Joao Moreno 已提交
177
}