From a50020021c0c528f0644e8ec814ef68e3ee8b9c6 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 7 Mar 2019 10:42:53 +0100 Subject: [PATCH] Fix #69940 --- .../sharedProcess/contrib/contributions.ts | 20 ----- .../sharedProcess/sharedProcessMain.ts | 22 ++++-- src/vs/code/node/cliProcessMain.ts | 79 +++++++++++-------- .../localizations/node/localizations.ts | 16 ++-- 4 files changed, 66 insertions(+), 71 deletions(-) delete mode 100644 src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts diff --git a/src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts b/src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts deleted file mode 100644 index 03f038fc1fb..00000000000 --- a/src/vs/code/electron-browser/sharedProcess/contrib/contributions.ts +++ /dev/null @@ -1,20 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner'; -import { LanguagePackCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle'; -import { StorageDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner'; -import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner'; - -export function createSharedProcessContributions(service: IInstantiationService): IDisposable { - return combinedDisposable([ - service.createInstance(NodeCachedDataCleaner), - service.createInstance(LanguagePackCachedDataCleaner), - service.createInstance(StorageDataCleaner), - service.createInstance(LogsDataCleaner) - ]); -} diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 25de96deb9e..2cd26d6cf6a 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -30,7 +30,6 @@ import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppen import { IWindowsService, ActiveWindowManager } from 'vs/platform/windows/common/windows'; import { WindowsChannelClient } from 'vs/platform/windows/node/windowsIpc'; import { ipcRenderer } from 'electron'; -import { createSharedProcessContributions } from 'vs/code/electron-browser/sharedProcess/contrib/contributions'; import { createSpdLogService } from 'vs/platform/log/node/spdlogService'; import { ILogService, LogLevel } from 'vs/platform/log/common/log'; import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/node/logIpc'; @@ -39,10 +38,14 @@ import { ILocalizationsService } from 'vs/platform/localizations/common/localiza import { LocalizationsChannel } from 'vs/platform/localizations/node/localizationsIpc'; import { DialogChannelClient } from 'vs/platform/dialogs/node/dialogIpc'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { IDisposable, dispose } from 'vs/base/common/lifecycle'; +import { IDisposable, dispose, combinedDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { DownloadService } from 'vs/platform/download/node/downloadService'; import { IDownloadService } from 'vs/platform/download/common/download'; import { StaticRouter } from 'vs/base/parts/ipc/node/ipc'; +import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner'; +import { LanguagePackCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner'; +import { StorageDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner'; +import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner'; export interface ISharedProcessConfiguration { readonly machineId: string; @@ -135,14 +138,21 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I const channel = new ExtensionManagementChannel(extensionManagementService, () => null); server.registerChannel('extensions', channel); - // clean up deprecated extensions - (extensionManagementService as ExtensionManagementService).removeDeprecatedExtensions(); - const localizationsService = accessor.get(ILocalizationsService); const localizationsChannel = new LocalizationsChannel(localizationsService); server.registerChannel('localizations', localizationsChannel); - createSharedProcessContributions(instantiationService2); + disposables.push(combinedDisposable([ + // clean up deprecated extensions + toDisposable(() => (extensionManagementService as ExtensionManagementService).removeDeprecatedExtensions()), + // update localizations cache + toDisposable(() => (localizationsService as LocalizationsService).update()), + // other cache clean ups + instantiationService2.createInstance(NodeCachedDataCleaner), + instantiationService2.createInstance(LanguagePackCachedDataCleaner), + instantiationService2.createInstance(StorageDataCleaner), + instantiationService2.createInstance(LogsDataCleaner) + ])); disposables.push(extensionManagementService as ExtensionManagementService); }); }); diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 566448022a8..d7a0fff87ac 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -9,14 +9,13 @@ import pkg from 'vs/platform/product/node/package'; import * as path from 'vs/base/common/path'; import * as semver from 'semver'; -import { sequence } from 'vs/base/common/async'; 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, ParsedArgs } from 'vs/platform/environment/common/environment'; import { EnvironmentService } from 'vs/platform/environment/node/environmentService'; -import { IExtensionManagementService, IExtensionGalleryService, IGalleryExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { IExtensionManagementService, IExtensionGalleryService, IGalleryExtension, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService'; import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -38,9 +37,10 @@ import { isPromiseCanceledError } from 'vs/base/common/errors'; import { areSameExtensions, adoptToGalleryExtensionId, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { URI } from 'vs/base/common/uri'; import { getManifest } from 'vs/platform/extensionManagement/node/extensionManagementUtil'; -import { IExtensionManifest, ExtensionType } from 'vs/platform/extensions/common/extensions'; +import { IExtensionManifest, ExtensionType, isLanguagePackExtension } from 'vs/platform/extensions/common/extensions'; import { isUIExtension } from 'vs/platform/extensions/node/extensionsUtil'; import { CancellationToken } from 'vs/base/common/cancellation'; +import { LocalizationsService } from 'vs/platform/localizations/node/localizations'; const notFound = (id: string) => localize('notFound', "Extension '{0}' not found.", id); const notInstalled = (id: string) => localize('notInstalled', "Extension '{0}' is not installed.", id); @@ -69,6 +69,7 @@ export class Main { constructor( private readonly remote: boolean, + @IInstantiationService private readonly instantiationService: IInstantiationService, @IEnvironmentService private readonly environmentService: IEnvironmentService, @IConfigurationService private readonly configurationService: IConfigurationService, @IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService, @@ -105,18 +106,25 @@ export class Main { private async installExtensions(extensions: string[], force: boolean): Promise { const failed: string[] = []; + const installedExtensionsManifests: IExtensionManifest[] = []; for (const extension of extensions) { try { - await this.installExtension(extension, force); + const manifest = await this.installExtension(extension, force); + if (manifest) { + installedExtensionsManifests.push(manifest); + } } catch (err) { console.error(err.message || err.stack || err); failed.push(extension); } } + if (installedExtensionsManifests.some(manifest => isLanguagePackExtension(manifest))) { + await this.updateLocalizationsCache(); + } return failed.length ? Promise.reject(localize('installation failed', "Failed Installing Extensions: {0}", failed.join(', '))) : Promise.resolve(); } - private async installExtension(extension: string, force: boolean): Promise { + private async installExtension(extension: string, force: boolean): Promise { if (/\.vsix$/i.test(extension)) { extension = path.isAbsolute(extension) ? extension : path.join(process.cwd(), extension); @@ -128,8 +136,9 @@ export class Main { const valid = await this.validate(manifest, force); if (valid) { - return this.extensionManagementService.install(URI.file(extension)).then(() => { + return this.extensionManagementService.install(URI.file(extension)).then(id => { console.log(localize('successVsixInstall', "Extension '{0}' was successfully installed!", getBaseLabel(extension))); + return manifest; }, error => { if (isPromiseCanceledError(error)) { console.log(localize('cancelVsixInstall', "Cancelled installing Extension '{0}'.", getBaseLabel(extension))); @@ -169,28 +178,23 @@ export class Main { const [installedExtension] = installed.filter(e => areSameExtensions(e.identifier, { id })); if (installedExtension) { - if (extension.version !== installedExtension.manifest.version) { - if (version || force) { - console.log(localize('updateMessage', "Updating the Extension '{0}' to the version {1}", id, extension.version)); - return this.installFromGallery(id, extension); - } else { - console.log(localize('forceUpdate', "Extension '{0}' v{1} is already installed, but a newer version {2} is available in the marketplace. Use '--force' option to update to newer version.", id, installedExtension.manifest.version, extension.version)); - return Promise.resolve(null); - } - } else { + if (extension.version === installedExtension.manifest.version) { console.log(localize('alreadyInstalled', "Extension '{0}' is already installed.", version ? `${id}@${version}` : id)); return Promise.resolve(null); } + if (!version && !force) { + console.log(localize('forceUpdate', "Extension '{0}' v{1} is already installed, but a newer version {2} is available in the marketplace. Use '--force' option to update to newer version.", id, installedExtension.manifest.version, extension.version)); + return Promise.resolve(null); + } + console.log(localize('updateMessage', "Updating the Extension '{0}' to the version {1}", id, extension.version)); } else { console.log(localize('foundExtension', "Found '{0}' in the marketplace.", id)); - return this.installFromGallery(id, extension); } - + await this.installFromGallery(id, extension); + return manifest; })); } - - private async validate(manifest: IExtensionManifest, force: boolean): Promise { if (!manifest) { throw new Error('Invalid vsix'); @@ -223,7 +227,7 @@ export class Main { } } - private uninstallExtension(extensions: string[]): Promise { + private async uninstallExtension(extensions: string[]): Promise { async function getExtensionId(extensionDescription: string): Promise { if (!/\.vsix$/i.test(extensionDescription)) { return extensionDescription; @@ -234,22 +238,29 @@ export class Main { return getId(manifest); } - return sequence(extensions.map(extension => () => { - return getExtensionId(extension).then(id => { - return this.extensionManagementService.getInstalled(ExtensionType.User).then(installed => { - const [extension] = installed.filter(e => areSameExtensions(e.identifier, { id })); - - if (!extension) { - return Promise.reject(new Error(`${notInstalled(id)}\n${useId}`)); - } + const uninstalledExtensions: ILocalExtension[] = []; + for (const extension of extensions) { + const id = await getExtensionId(extension); + const installed = await this.extensionManagementService.getInstalled(ExtensionType.User); + const [extensionToUninstall] = installed.filter(e => areSameExtensions(e.identifier, { id })); + if (!extensionToUninstall) { + return Promise.reject(new Error(`${notInstalled(id)}\n${useId}`)); + } + console.log(localize('uninstalling', "Uninstalling {0}...", id)); + await this.extensionManagementService.uninstall(extensionToUninstall, true); + uninstalledExtensions.push(extensionToUninstall); + console.log(localize('successUninstall', "Extension '{0}' was successfully uninstalled!", id)); + } - console.log(localize('uninstalling', "Uninstalling {0}...", id)); + if (uninstalledExtensions.some(e => isLanguagePackExtension(e.manifest))) { + await this.updateLocalizationsCache(); + } + } - return this.extensionManagementService.uninstall(extension, true) - .then(() => console.log(localize('successUninstall', "Extension '{0}' was successfully uninstalled!", id))); - }); - }); - })); + private async updateLocalizationsCache(): Promise { + const localizationService = this.instantiationService.createInstance(LocalizationsService); + await localizationService.update(); + localizationService.dispose(); } } diff --git a/src/vs/platform/localizations/node/localizations.ts b/src/vs/platform/localizations/node/localizations.ts index d1d106dcfa7..ac7cafcbb5c 100644 --- a/src/vs/platform/localizations/node/localizations.ts +++ b/src/vs/platform/localizations/node/localizations.ts @@ -51,8 +51,6 @@ export class LocalizationsService extends Disposable implements ILocalizationsSe this._register(extensionManagementService.onDidInstallExtension(({ local }) => this.onDidInstallExtension(local))); this._register(extensionManagementService.onDidUninstallExtension(({ identifier }) => this.onDidUninstallExtension(identifier))); - - this.extensionManagementService.getInstalled().then(installed => this.cache.update(installed)); } getLanguageIds(type: LanguageType): Promise { @@ -69,7 +67,7 @@ export class LocalizationsService extends Disposable implements ILocalizationsSe private onDidInstallExtension(extension: ILocalExtension | undefined): void { if (extension && extension.manifest && extension.manifest.contributes && extension.manifest.contributes.localizations && extension.manifest.contributes.localizations.length) { this.logService.debug('Adding language packs from the extension', extension.identifier.id); - this.update(); + this.update().then(changed => { if (changed) { this._onDidLanguagesChange.fire(); } }); } } @@ -78,19 +76,15 @@ export class LocalizationsService extends Disposable implements ILocalizationsSe .then(languagePacks => { if (Object.keys(languagePacks).some(language => languagePacks[language] && languagePacks[language].extensions.some(e => areSameExtensions(e.extensionIdentifier, identifier)))) { this.logService.debug('Removing language packs from the extension', identifier.id); - this.update(); + this.update().then(changed => { if (changed) { this._onDidLanguagesChange.fire(); } }); } }); } - private update(): void { - Promise.all([this.cache.getLanguagePacks(), this.extensionManagementService.getInstalled()]) + update(): Promise { + return Promise.all([this.cache.getLanguagePacks(), this.extensionManagementService.getInstalled()]) .then(([current, installed]) => this.cache.update(installed) - .then(updated => { - if (!equals(Object.keys(current), Object.keys(updated))) { - this._onDidLanguagesChange.fire(); - } - })); + .then(updated => !equals(Object.keys(current), Object.keys(updated)))); } } -- GitLab