UNPKG

@codingame/monaco-vscode-extensions-service-override

Version:

VSCode public API plugged on the monaco editor - extensions service-override

399 lines (396 loc) 19.5 kB
import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js'; import { CancellationToken } from 'vscode/vscode/vs/base/common/cancellation'; import { getErrorMessage, isCancellationError } from 'vscode/vscode/vs/base/common/errors'; import { Schemas } from 'vscode/vscode/vs/base/common/network'; import { basename } from 'vscode/vscode/vs/base/common/resources'; import { semverExports } from 'vscode/external/vscode-semver/semver.js'; import { URI } from 'vscode/vscode/vs/base/common/uri'; import { localize } from 'vscode/vscode/vs/nls'; import { InstallOperation, EXTENSION_IDENTIFIER_REGEX } from 'vscode/vscode/vs/platform/extensionManagement/common/extensionManagement'; import { IExtensionManagementService, IExtensionGalleryService } from 'vscode/vscode/vs/platform/extensionManagement/common/extensionManagement.service'; import { getIdAndVersion, areSameExtensions, getGalleryExtensionId, getExtensionId } from 'vscode/vscode/vs/platform/extensionManagement/common/extensionManagementUtil'; import { ExtensionType, EXTENSION_CATEGORIES } from 'vscode/vscode/vs/platform/extensions/common/extensions'; const notFound = (id) => ( localize(9800, "Extension '{0}' not found.", id)); const useId = ( localize( 9801, "Make sure you use the full extension ID, including the publisher, e.g.: {0}", 'ms-dotnettools.csharp' )); let ExtensionManagementCLI = class ExtensionManagementCLI { constructor(logger, extensionManagementService, extensionGalleryService) { this.logger = logger; this.extensionManagementService = extensionManagementService; this.extensionGalleryService = extensionGalleryService; } get location() { return undefined; } async listExtensions(showVersions, category, profileLocation) { let extensions = await this.extensionManagementService.getInstalled(ExtensionType.User, profileLocation); const categories = ( (EXTENSION_CATEGORIES.map(c => c.toLowerCase()))); if (category && category !== '') { if (categories.indexOf(category.toLowerCase()) < 0) { this.logger.info('Invalid category please enter a valid category. To list valid categories run --category without a category specified'); return; } extensions = extensions.filter(e => { if (e.manifest.categories) { const lowerCaseCategories = ( (e.manifest.categories.map(c => c.toLowerCase()))); return lowerCaseCategories.indexOf(category.toLowerCase()) > -1; } return false; }); } else if (category === '') { this.logger.info('Possible Categories: '); categories.forEach(category => { this.logger.info(category); }); return; } if (this.location) { this.logger.info(( localize(9802, "Extensions installed on {0}:", this.location))); } extensions = extensions.sort((e1, e2) => e1.identifier.id.localeCompare(e2.identifier.id)); let lastId = undefined; for (const extension of extensions) { if (lastId !== extension.identifier.id) { lastId = extension.identifier.id; this.logger.info(showVersions ? `${lastId}@${extension.manifest.version}` : lastId); } } } async installExtensions(extensions, builtinExtensions, installOptions, force) { const failed = []; try { if (extensions.length) { this.logger.info(this.location ? ( localize(9803, "Installing extensions on {0}...", this.location)) : ( localize(9804, "Installing extensions..."))); } const installVSIXInfos = []; const installExtensionInfos = []; const addInstallExtensionInfo = (id, version, isBuiltin) => { installExtensionInfos.push({ id, version: version !== 'prerelease' ? version : undefined, installOptions: { ...installOptions, isBuiltin, installPreReleaseVersion: version === 'prerelease' || installOptions.installPreReleaseVersion } }); }; for (const extension of extensions) { if (extension instanceof URI) { installVSIXInfos.push({ vsix: extension, installOptions }); } else { const [id, version] = getIdAndVersion(extension); addInstallExtensionInfo(id, version, false); } } for (const extension of builtinExtensions) { if (extension instanceof URI) { installVSIXInfos.push({ vsix: extension, installOptions: { ...installOptions, isBuiltin: true, donotIncludePackAndDependencies: true } }); } else { const [id, version] = getIdAndVersion(extension); addInstallExtensionInfo(id, version, true); } } const installed = await this.extensionManagementService.getInstalled(undefined, installOptions.profileLocation); if (installVSIXInfos.length) { await Promise.all(( (installVSIXInfos.map(async ({ vsix, installOptions }) => { try { await this.installVSIX(vsix, installOptions, force, installed); } catch (err) { this.logger.error(err); failed.push(( (vsix.toString()))); } })))); } if (installExtensionInfos.length) { const failedGalleryExtensions = await this.installGalleryExtensions(installExtensionInfos, installed, force); failed.push(...failedGalleryExtensions); } } catch (error) { this.logger.error(( localize(9805, "Error while installing extensions: {0}", getErrorMessage(error)))); throw error; } if (failed.length) { throw ( (new Error(localize(9806, "Failed Installing Extensions: {0}", failed.join(', '))))); } } async updateExtensions(profileLocation) { const installedExtensions = await this.extensionManagementService.getInstalled(ExtensionType.User, profileLocation); const installedExtensionsQuery = []; for (const extension of installedExtensions) { if (!!extension.identifier.uuid) { installedExtensionsQuery.push({ ...extension.identifier, preRelease: extension.preRelease }); } } this.logger.trace(( localize( 9807, "Fetching latest versions for {0} extensions", installedExtensionsQuery.length ))); const availableVersions = await this.extensionGalleryService.getExtensions(installedExtensionsQuery, { compatible: true }, CancellationToken.None); const extensionsToUpdate = []; for (const newVersion of availableVersions) { for (const oldVersion of installedExtensions) { if (areSameExtensions(oldVersion.identifier, newVersion.identifier) && semverExports.gt(newVersion.version, oldVersion.manifest.version)) { extensionsToUpdate.push({ extension: newVersion, options: { operation: InstallOperation.Update, installPreReleaseVersion: oldVersion.preRelease, profileLocation, isApplicationScoped: oldVersion.isApplicationScoped } }); } } } if (!extensionsToUpdate.length) { this.logger.info(( localize(9808, "No extension to update"))); return; } this.logger.info(( localize( 9809, "Updating extensions: {0}", ( (extensionsToUpdate.map(ext => ext.extension.identifier.id))).join(', ') ))); const installationResult = await this.extensionManagementService.installGalleryExtensions(extensionsToUpdate); for (const extensionResult of installationResult) { if (extensionResult.error) { this.logger.error(( localize( 9810, "Error while updating extension {0}: {1}", extensionResult.identifier.id, getErrorMessage(extensionResult.error) ))); } else { this.logger.info(( localize( 9811, "Extension '{0}' v{1} was successfully updated.", extensionResult.identifier.id, extensionResult.local?.manifest.version ))); } } } async installGalleryExtensions(installExtensionInfos, installed, force) { installExtensionInfos = installExtensionInfos.filter(({ id, version }) => { const installedExtension = installed.find(i => areSameExtensions(i.identifier, { id })); if (installedExtension) { if (!force && (!version || (version === 'prerelease' && installedExtension.preRelease))) { this.logger.info(( localize( 9812, "Extension '{0}' v{1} is already installed. Use '--force' option to update to latest version or provide '@<version>' to install a specific version, for example: '{2}@1.2.3'.", id, installedExtension.manifest.version, id ))); return false; } if (version && installedExtension.manifest.version === version) { this.logger.info(( localize(9813, "Extension '{0}' is already installed.", `${id}@${version}`))); return false; } } return true; }); if (!installExtensionInfos.length) { return []; } const failed = []; const extensionsToInstall = []; const galleryExtensions = await this.getGalleryExtensions(installExtensionInfos); await Promise.all(( (installExtensionInfos.map(async ({ id, version, installOptions }) => { const gallery = galleryExtensions.get(id.toLowerCase()); if (!gallery) { this.logger.error(`${notFound(version ? `${id}@${version}` : id)}\n${useId}`); failed.push(id); return; } try { const manifest = await this.extensionGalleryService.getManifest(gallery, CancellationToken.None); if (manifest && !this.validateExtensionKind(manifest)) { return; } } catch (err) { this.logger.error(err.message || err.stack || err); failed.push(id); return; } const installedExtension = installed.find(e => areSameExtensions(e.identifier, gallery.identifier)); if (installedExtension) { if (gallery.version === installedExtension.manifest.version) { this.logger.info(( localize( 9813, "Extension '{0}' is already installed.", version ? `${id}@${version}` : id ))); return; } this.logger.info(( localize( 9814, "Updating the extension '{0}' to the version {1}", id, gallery.version ))); } if (installOptions.isBuiltin) { this.logger.info(version ? ( localize(9815, "Installing builtin extension '{0}' v{1}...", id, version)) : ( localize(9816, "Installing builtin extension '{0}'...", id))); } else { this.logger.info(version ? ( localize(9817, "Installing extension '{0}' v{1}...", id, version)) : ( localize(9818, "Installing extension '{0}'...", id))); } extensionsToInstall.push({ extension: gallery, options: { ...installOptions, installGivenVersion: !!version, isApplicationScoped: installOptions.isApplicationScoped || installedExtension?.isApplicationScoped }, }); })))); if (extensionsToInstall.length) { const installationResult = await this.extensionManagementService.installGalleryExtensions(extensionsToInstall); for (const extensionResult of installationResult) { if (extensionResult.error) { this.logger.error(( localize( 9819, "Error while installing extension {0}: {1}", extensionResult.identifier.id, getErrorMessage(extensionResult.error) ))); failed.push(extensionResult.identifier.id); } else { this.logger.info(( localize( 9820, "Extension '{0}' v{1} was successfully installed.", extensionResult.identifier.id, extensionResult.local?.manifest.version ))); } } } return failed; } async installVSIX(vsix, installOptions, force, installedExtensions) { const manifest = await this.extensionManagementService.getManifest(vsix); if (!manifest) { throw ( (new Error('Invalid vsix'))); } const valid = await this.validateVSIX(manifest, force, installOptions.profileLocation, installedExtensions); if (valid) { try { await this.extensionManagementService.install(vsix, { ...installOptions, installGivenVersion: true }); this.logger.info(( localize(9821, "Extension '{0}' was successfully installed.", basename(vsix)))); } catch (error) { if (isCancellationError(error)) { this.logger.info(( localize(9822, "Cancelled installing extension '{0}'.", basename(vsix)))); } else { throw error; } } } } async getGalleryExtensions(extensions) { const galleryExtensions = ( (new Map())); const preRelease = ( (extensions.some(e => e.installOptions.installPreReleaseVersion))); const targetPlatform = await this.extensionManagementService.getTargetPlatform(); const extensionInfos = []; for (const extension of extensions) { if (EXTENSION_IDENTIFIER_REGEX.test(extension.id)) { extensionInfos.push({ ...extension, preRelease }); } } if (extensionInfos.length) { const result = await this.extensionGalleryService.getExtensions(extensionInfos, { targetPlatform }, CancellationToken.None); for (const extension of result) { galleryExtensions.set(extension.identifier.id.toLowerCase(), extension); } } return galleryExtensions; } validateExtensionKind(_manifest) { return true; } async validateVSIX(manifest, force, profileLocation, installedExtensions) { if (!force) { const extensionIdentifier = { id: getGalleryExtensionId(manifest.publisher, manifest.name) }; const newer = installedExtensions.find(local => areSameExtensions(extensionIdentifier, local.identifier) && semverExports.gt(local.manifest.version, manifest.version)); if (newer) { this.logger.info(( localize( 9823, "A newer version of extension '{0}' v{1} is already installed. Use '--force' option to downgrade to older version.", newer.identifier.id, newer.manifest.version, manifest.version ))); return false; } } return this.validateExtensionKind(manifest); } async uninstallExtensions(extensions, force, profileLocation) { const getId = async (extensionDescription) => { if (extensionDescription instanceof URI) { const manifest = await this.extensionManagementService.getManifest(extensionDescription); return getExtensionId(manifest.publisher, manifest.name); } return extensionDescription; }; for (const extension of extensions) { const id = await getId(extension); const installed = await this.extensionManagementService.getInstalled(undefined, profileLocation); const extensionsToUninstall = installed.filter(e => areSameExtensions(e.identifier, { id })); if (!extensionsToUninstall.length) { throw ( (new Error(`${this.notInstalled(id)}\n${useId}`))); } if (( (extensionsToUninstall.some(e => e.type === ExtensionType.System)))) { this.logger.info(( localize( 9824, "Extension '{0}' is a Built-in extension and cannot be uninstalled", id ))); return; } if (!force && ( (extensionsToUninstall.some(e => e.isBuiltin)))) { this.logger.info(( localize( 9825, "Extension '{0}' is marked as a Built-in extension by user. Please use '--force' option to uninstall it.", id ))); return; } this.logger.info(( localize(9826, "Uninstalling {0}...", id))); for (const extensionToUninstall of extensionsToUninstall) { await this.extensionManagementService.uninstall(extensionToUninstall, { profileLocation }); } if (this.location) { this.logger.info(( localize( 9827, "Extension '{0}' was successfully uninstalled from {1}!", id, this.location ))); } else { this.logger.info(( localize(9828, "Extension '{0}' was successfully uninstalled!", id))); } } } async locateExtension(extensions) { const installed = await this.extensionManagementService.getInstalled(); extensions.forEach(e => { installed.forEach(i => { if (i.identifier.id === e) { if (i.location.scheme === Schemas.file) { this.logger.info(i.location.fsPath); return; } } }); }); } notInstalled(id) { return this.location ? ( localize(9829, "Extension '{0}' is not installed on {1}.", id, this.location)) : ( localize(9830, "Extension '{0}' is not installed.", id)); } }; ExtensionManagementCLI = ( (__decorate([ ( (__param(1, IExtensionManagementService))), ( (__param(2, IExtensionGalleryService))) ], ExtensionManagementCLI))); export { ExtensionManagementCLI };