mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode cfbd1999769f4f08dce29629fb92fdc0fac53829
This commit is contained in:
@@ -12,11 +12,11 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
|
||||
interface IScannedBuiltinExtension {
|
||||
extensionPath: string,
|
||||
packageJSON: IExtensionManifest,
|
||||
packageNLSPath?: string,
|
||||
readmePath?: string,
|
||||
changelogPath?: string,
|
||||
extensionPath: string;
|
||||
packageJSON: IExtensionManifest;
|
||||
packageNLS?: any;
|
||||
readmePath?: string;
|
||||
changelogPath?: string;
|
||||
}
|
||||
|
||||
export class BuiltinExtensionsScannerService implements IBuiltinExtensionsScannerService {
|
||||
@@ -54,7 +54,7 @@ export class BuiltinExtensionsScannerService implements IBuiltinExtensionsScanne
|
||||
location: uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.extensionPath),
|
||||
type: ExtensionType.System,
|
||||
packageJSON: e.packageJSON,
|
||||
packageNLSUrl: e.packageNLSPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.packageNLSPath) : undefined,
|
||||
packageNLS: e.packageNLS,
|
||||
readmeUrl: e.readmePath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.readmePath) : undefined,
|
||||
changelogUrl: e.changelogPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.changelogPath) : undefined,
|
||||
}));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IExtension, IScannedExtension, ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtension, IScannedExtension, ExtensionType, ITranslatedScannedExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionManagementService, IGalleryExtension, IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkspace, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
@@ -128,6 +128,7 @@ export interface IExtensionRecommendationsService {
|
||||
|
||||
getAllRecommendationsWithReason(): IStringDictionary<IExtensionRecommendationReson>;
|
||||
getFileBasedRecommendations(): IExtensionRecommendation[];
|
||||
getImportantRecommendations(): Promise<IExtensionRecommendation[]>;
|
||||
getConfigBasedRecommendations(): Promise<IExtensionRecommendation[]>;
|
||||
getOtherRecommendations(): Promise<IExtensionRecommendation[]>;
|
||||
getWorkspaceRecommendations(): Promise<IExtensionRecommendation[]>;
|
||||
@@ -145,6 +146,7 @@ export const IWebExtensionsScannerService = createDecorator<IWebExtensionsScanne
|
||||
export interface IWebExtensionsScannerService {
|
||||
readonly _serviceBrand: undefined;
|
||||
scanExtensions(type?: ExtensionType): Promise<IScannedExtension[]>;
|
||||
scanAndTranslateExtensions(type?: ExtensionType): Promise<ITranslatedScannedExtension[]>;
|
||||
addExtension(galleryExtension: IGalleryExtension): Promise<IScannedExtension>;
|
||||
removeExtension(identifier: IExtensionIdentifier, version?: string): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -3,13 +3,10 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ExtensionType, IExtensionIdentifier, IExtensionManifest, IScannedExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtensionType, IExtensionIdentifier, IExtensionManifest, ITranslatedScannedExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, DidUninstallExtensionEvent, IGalleryExtension, IReportedExtension, IGalleryMetadata, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IRequestService, isSuccess, asText } from 'vs/platform/request/common/request';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
@@ -33,14 +30,13 @@ export class WebExtensionManagementService extends Disposable implements IExtens
|
||||
|
||||
constructor(
|
||||
@IWebExtensionsScannerService private readonly webExtensionsScannerService: IWebExtensionsScannerService,
|
||||
@IRequestService private readonly requestService: IRequestService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async getInstalled(type?: ExtensionType): Promise<ILocalExtension[]> {
|
||||
const extensions = await this.webExtensionsScannerService.scanExtensions(type);
|
||||
const extensions = await this.webExtensionsScannerService.scanAndTranslateExtensions(type);
|
||||
return Promise.all(extensions.map(e => this.toLocalExtension(e)));
|
||||
}
|
||||
|
||||
@@ -83,23 +79,11 @@ export class WebExtensionManagementService extends Disposable implements IExtens
|
||||
return userExtensions.find(e => areSameExtensions(e.identifier, identifier));
|
||||
}
|
||||
|
||||
private async toLocalExtension(scannedExtension: IScannedExtension): Promise<ILocalExtension> {
|
||||
let manifest = scannedExtension.packageJSON;
|
||||
if (scannedExtension.packageNLSUrl) {
|
||||
try {
|
||||
const context = await this.requestService.request({ type: 'GET', url: scannedExtension.packageNLSUrl.toString() }, CancellationToken.None);
|
||||
if (isSuccess(context)) {
|
||||
const content = await asText(context);
|
||||
if (content) {
|
||||
manifest = localizeManifest(manifest, JSON.parse(content));
|
||||
}
|
||||
}
|
||||
} catch (error) { /* ignore */ }
|
||||
}
|
||||
private async toLocalExtension(scannedExtension: ITranslatedScannedExtension): Promise<ILocalExtension> {
|
||||
return <ILocalExtension>{
|
||||
type: scannedExtension.type,
|
||||
identifier: scannedExtension.identifier,
|
||||
manifest,
|
||||
manifest: scannedExtension.packageJSON,
|
||||
location: scannedExtension.location,
|
||||
isMachineScoped: false,
|
||||
publisherId: null,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as semver from 'semver-umd';
|
||||
import { IBuiltinExtensionsScannerService, IScannedExtension, ExtensionType, IExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { IBuiltinExtensionsScannerService, IScannedExtension, ExtensionType, IExtensionIdentifier, ITranslatedScannedExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
@@ -21,6 +21,9 @@ import { IGalleryExtension } from 'vs/platform/extensionManagement/common/extens
|
||||
import { groupByExtension, areSameExtensions, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IStaticExtension } from 'vs/workbench/workbench.web.api';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls';
|
||||
|
||||
interface IUserExtension {
|
||||
identifier: IExtensionIdentifier;
|
||||
@@ -44,7 +47,7 @@ const AssetTypeWebResource = 'Microsoft.VisualStudio.Code.WebResources';
|
||||
|
||||
function getExtensionLocation(assetUri: URI): URI { return joinPath(assetUri, AssetTypeWebResource, 'extension'); }
|
||||
|
||||
export class WebExtensionsScannerService implements IWebExtensionsScannerService {
|
||||
export class WebExtensionsScannerService extends Disposable implements IWebExtensionsScannerService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
@@ -53,6 +56,8 @@ export class WebExtensionsScannerService implements IWebExtensionsScannerService
|
||||
private readonly extensionsResource: URI | undefined = undefined;
|
||||
private readonly userExtensionsResourceLimiter: Queue<IUserExtension[]> = new Queue<IUserExtension[]>();
|
||||
|
||||
private userExtensionsPromise: Promise<IScannedExtension[]> | undefined;
|
||||
|
||||
constructor(
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
|
||||
@IBuiltinExtensionsScannerService private readonly builtinExtensionsScannerService: IBuiltinExtensionsScannerService,
|
||||
@@ -61,22 +66,48 @@ export class WebExtensionsScannerService implements IWebExtensionsScannerService
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
) {
|
||||
super();
|
||||
if (isWeb) {
|
||||
this.extensionsResource = joinPath(environmentService.userRoamingDataHome, 'extensions.json');
|
||||
this.systemExtensionsPromise = this.builtinExtensionsScannerService.scanBuiltinExtensions();
|
||||
this.systemExtensionsPromise = this.readSystemExtensions();
|
||||
this.defaultExtensionsPromise = this.readDefaultExtensions();
|
||||
if (this.extensionsResource) {
|
||||
this._register(Event.filter(this.fileService.onDidFilesChange, e => e.contains(this.extensionsResource!))(() => this.userExtensionsPromise = undefined));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async readDefaultExtensions(): Promise<IScannedExtension[]> {
|
||||
private async readSystemExtensions(): Promise<IScannedExtension[]> {
|
||||
const extensions = await this.builtinExtensionsScannerService.scanBuiltinExtensions();
|
||||
return extensions.concat(this.getStaticExtensions(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* All extensions defined via `staticExtensions`
|
||||
*/
|
||||
private getStaticExtensions(builtin: boolean): IScannedExtension[] {
|
||||
const staticExtensions = this.environmentService.options && Array.isArray(this.environmentService.options.staticExtensions) ? this.environmentService.options.staticExtensions : [];
|
||||
return (
|
||||
staticExtensions
|
||||
.filter(e => Boolean(e.isBuiltin) === builtin)
|
||||
.map(e => ({
|
||||
identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) },
|
||||
location: e.extensionLocation,
|
||||
type: ExtensionType.System,
|
||||
packageJSON: e.packageJSON,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
private async readDefaultExtensions(): Promise<IScannedExtension[]> {
|
||||
const defaultUserWebExtensions = await this.readDefaultUserWebExtensions();
|
||||
return [...staticExtensions, ...defaultUserWebExtensions].map<IScannedExtension>(e => ({
|
||||
const extensions = defaultUserWebExtensions.map(e => ({
|
||||
identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) },
|
||||
location: e.extensionLocation,
|
||||
type: ExtensionType.User,
|
||||
packageJSON: e.packageJSON,
|
||||
}));
|
||||
return extensions.concat(this.getStaticExtensions(false));
|
||||
}
|
||||
|
||||
private async readDefaultUserWebExtensions(): Promise<IStaticExtension[]> {
|
||||
@@ -113,12 +144,52 @@ export class WebExtensionsScannerService implements IWebExtensionsScannerService
|
||||
if (type === undefined || type === ExtensionType.User) {
|
||||
const staticExtensions = await this.defaultExtensionsPromise;
|
||||
extensions.push(...staticExtensions);
|
||||
const userExtensions = await this.scanUserExtensions();
|
||||
if (!this.userExtensionsPromise) {
|
||||
this.userExtensionsPromise = this.scanUserExtensions();
|
||||
}
|
||||
const userExtensions = await this.userExtensionsPromise;
|
||||
extensions.push(...userExtensions);
|
||||
}
|
||||
return extensions;
|
||||
}
|
||||
|
||||
async scanAndTranslateExtensions(type?: ExtensionType): Promise<ITranslatedScannedExtension[]> {
|
||||
const extensions = await this.scanExtensions(type);
|
||||
return Promise.all(extensions.map((ext) => this._translateScannedExtension(ext)));
|
||||
}
|
||||
|
||||
private async _translateScannedExtension(scannedExtension: IScannedExtension): Promise<ITranslatedScannedExtension> {
|
||||
let manifest = scannedExtension.packageJSON;
|
||||
if (scannedExtension.packageNLS) {
|
||||
// package.nls.json is inlined
|
||||
try {
|
||||
manifest = localizeManifest(manifest, scannedExtension.packageNLS);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
/* ignore */
|
||||
}
|
||||
} else if (scannedExtension.packageNLSUrl) {
|
||||
// package.nls.json needs to be fetched
|
||||
try {
|
||||
const context = await this.requestService.request({ type: 'GET', url: scannedExtension.packageNLSUrl.toString() }, CancellationToken.None);
|
||||
if (isSuccess(context)) {
|
||||
const content = await asText(context);
|
||||
if (content) {
|
||||
manifest = localizeManifest(manifest, JSON.parse(content));
|
||||
}
|
||||
}
|
||||
} catch (error) { /* ignore */ }
|
||||
}
|
||||
return {
|
||||
identifier: scannedExtension.identifier,
|
||||
location: scannedExtension.location,
|
||||
type: scannedExtension.type,
|
||||
packageJSON: manifest,
|
||||
readmeUrl: scannedExtension.readmeUrl,
|
||||
changelogUrl: scannedExtension.changelogUrl
|
||||
};
|
||||
}
|
||||
|
||||
async addExtension(galleryExtension: IGalleryExtension): Promise<IScannedExtension> {
|
||||
if (!galleryExtension.assetTypes.some(type => type.startsWith(AssetTypeWebResource))) {
|
||||
throw new Error(`Missing ${AssetTypeWebResource} asset type`);
|
||||
@@ -149,7 +220,7 @@ export class WebExtensionsScannerService implements IWebExtensionsScannerService
|
||||
|
||||
async removeExtension(identifier: IExtensionIdentifier, version?: string): Promise<void> {
|
||||
let userExtensions = await this.readUserExtensions();
|
||||
userExtensions = userExtensions.filter(extension => !(areSameExtensions(extension.identifier, identifier) && version ? extension.version === version : true));
|
||||
userExtensions = userExtensions.filter(extension => !(areSameExtensions(extension.identifier, identifier) && (version ? extension.version === version : true)));
|
||||
await this.writeUserExtensions(userExtensions);
|
||||
}
|
||||
|
||||
@@ -226,6 +297,7 @@ export class WebExtensionsScannerService implements IWebExtensionsScannerService
|
||||
packageNLSUri: e.packageNLSUri?.toJSON(),
|
||||
}));
|
||||
await this.fileService.writeFile(this.extensionsResource!, VSBuffer.fromString(JSON.stringify(storedUserExtensions)));
|
||||
this.userExtensionsPromise = undefined;
|
||||
return userExtensions;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ suite('ExtensionEnablementService Test', () => {
|
||||
assert.ok(!testObject.canChangeEnablement(extension));
|
||||
});
|
||||
|
||||
test('test extension is disabled when disabled in enviroment', async () => {
|
||||
test('test extension is disabled when disabled in environment', async () => {
|
||||
const extension = aLocalExtension('pub.a');
|
||||
instantiationService.stub(IWorkbenchEnvironmentService, { disableExtensions: ['pub.a'] } as IWorkbenchEnvironmentService);
|
||||
instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event, getInstalled: () => Promise.resolve([extension, aLocalExtension('pub.b')]) } as IExtensionManagementService);
|
||||
|
||||
Reference in New Issue
Block a user