cliProcessMain.ts 7.5 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 13 14 15 16 17 18 19
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 已提交
20
import { IExtensionManagementService, IExtensionGalleryService, IQueryResult } from 'vs/platform/extensionManagement/common/extensionManagement';
J
Joao Moreno 已提交
21 22 23
import { getExtensionId } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
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, eg: {0}", 'ms-vscode.csharp');
J
Joao Moreno 已提交
36

J
Joao Moreno 已提交
37 38 39 40 41 42 43 44
class Main {

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

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

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

	private listExtensions(): TPromise<any> {
		return this.extensionManagementService.getInstalled().then(extensions => {
62
			extensions.forEach(e => console.log(getExtensionId(e)));
J
Joao Moreno 已提交
63 64 65
		});
	}

66
	private installExtension(ids: string[]): TPromise<any> {
67 68
		return sequence(ids.map(id => () => {
			return this.extensionManagementService.getInstalled().then(installed => {
69 70 71
				const isInstalled = installed.some(e => getExtensionId(e) === id);

				if (isInstalled) {
72
					console.log(localize('alreadyInstalled', "Extension '{0}' is already installed.", id));
J
Joao Moreno 已提交
73
					return TPromise.as(null);
74
				}
J
Joao Moreno 已提交
75

J
Joao Moreno 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
				return this.extensionGalleryService.query({ ids: [id] })
					.then<IQueryResult>(null, err => {
						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 已提交
97 98
						return this.extensionManagementService.install(extension.manifest).then(() => {
							console.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed!", id, extension.manifest.version));
J
Joao Moreno 已提交
99
						});
100
					});
101 102
			});
		}));
J
Joao Moreno 已提交
103
	}
J
Joao Moreno 已提交
104

105 106 107 108
	private uninstallExtension(ids: string[]): TPromise<any> {
		return sequence(ids.map(id => () => {
			return this.extensionManagementService.getInstalled().then(installed => {
				const [extension] = installed.filter(e => getExtensionId(e) === id);
J
Joao Moreno 已提交
109

110 111 112
				if (!extension) {
					return TPromise.wrapError(`${ notInstalled(id) }\n${ useId }`);
				}
J
Joao Moreno 已提交
113

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

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

124 125
const eventPrefix = 'monacoworkbench';

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

	const instantiationService: IInstantiationService = new InstantiationService(services);
131 132 133 134 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

	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 已提交
173
}