Skip to content

Commit fff7426

Browse files
authored
support skipping builtin extension (#308825)
1 parent 1ec46de commit fff7426

File tree

4 files changed

+36
-6
lines changed

4 files changed

+36
-6
lines changed

src/vs/platform/environment/common/environment.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export interface IEnvironmentService {
7171
debugExtensionHost: IExtensionHostDebugParams;
7272
isExtensionDevelopment: boolean;
7373
disableExtensions: boolean | string[];
74+
skipBuiltinExtensions?: readonly string[];
7475
enableExtensions?: readonly string[];
7576
extensionDevelopmentLocationURI?: URI[];
7677
extensionDevelopmentKind?: ExtensionKind[];

src/vs/platform/environment/common/environmentService.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,14 @@ export abstract class AbstractNativeEnvironmentService implements INativeEnviron
221221
return false;
222222
}
223223

224+
get skipBuiltinExtensions(): readonly string[] {
225+
const value = env['VSCODE_SKIP_BUILTIN_EXTENSIONS'];
226+
if (!value) {
227+
return [];
228+
}
229+
return value.split(',').map(id => id.trim()).filter(id => id);
230+
}
231+
224232
@memoize
225233
get debugExtensionHost(): IExtensionHostDebugParams { return parseExtensionHostDebugPort(this.args, this.isBuilt); }
226234
get debugRenderer(): boolean { return !!this.args.debugRenderer; }

src/vs/platform/extensionManagement/common/extensionsScannerService.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,18 @@ interface IBuiltInExtensionControl {
107107
[name: string]: 'marketplace' | 'disabled' | string;
108108
}
109109

110+
function getProductBuiltInExtensionsEnabledWithAutoUpdates(productService: IProductService, environmentService: IEnvironmentService): Set<string> {
111+
const result = new Set<string>();
112+
for (const id of productService.builtInExtensionsEnabledWithAutoUpdates) {
113+
const toLowerCaseId = id.toLowerCase();
114+
if (environmentService.skipBuiltinExtensions?.some(skipId => skipId.toLowerCase() === toLowerCaseId)) {
115+
continue;
116+
}
117+
result.add(toLowerCaseId);
118+
}
119+
return result;
120+
}
121+
110122
export type SystemExtensionsScanOptions = {
111123
readonly checkControlFile?: boolean;
112124
readonly language?: string;
@@ -205,7 +217,14 @@ export abstract class AbstractExtensionsScannerService extends Disposable implem
205217
promises.push(this.scanDefaultSystemExtensions(scanOptions.language));
206218
promises.push(this.scanDevSystemExtensions(scanOptions.language, !!scanOptions.checkControlFile));
207219
const [defaultSystemExtensions, devSystemExtensions] = await Promise.all(promises);
208-
return this.applyScanOptions([...defaultSystemExtensions, ...devSystemExtensions], ExtensionType.System, { pickLatest: false });
220+
let allSystemExtensions = [...defaultSystemExtensions, ...devSystemExtensions];
221+
222+
if (this.environmentService.skipBuiltinExtensions?.length) {
223+
const skipSet = new Set(this.environmentService.skipBuiltinExtensions.map(id => id.toLowerCase()));
224+
allSystemExtensions = allSystemExtensions.filter(ext => !skipSet.has(ext.identifier.id.toLowerCase()));
225+
}
226+
227+
return this.applyScanOptions(allSystemExtensions, ExtensionType.System, { pickLatest: false });
209228
}
210229

211230
async scanUserExtensions(scanOptions: UserExtensionsScanOptions): Promise<IScannedExtension[]> {
@@ -394,14 +413,14 @@ export abstract class AbstractExtensionsScannerService extends Disposable implem
394413
result.set(extension.identifier.id, extension);
395414
}
396415
});
416+
const productBuiltInExtensionsEnabledWithAutoUpdates = getProductBuiltInExtensionsEnabledWithAutoUpdates(this.productService, this.environmentService);
397417
user?.forEach((extension) => {
398418
const existing = result.get(extension.identifier.id);
399419
if (!existing && system && extension.type === ExtensionType.System) {
400420
this.logService.debug(`Skipping obsolete system extension ${extension.location.path}.`);
401421
return;
402422
}
403-
const isBuiltinExtensionEnabledWithAutoUpdates = this.productService.builtInExtensionsEnabledWithAutoUpdates?.some(id => id.toLowerCase() === extension.identifier.id.toLowerCase());
404-
if (isBuiltinExtensionEnabledWithAutoUpdates && !extension.forceAutoUpdate) {
423+
if (productBuiltInExtensionsEnabledWithAutoUpdates.has(extension.identifier.id.toLowerCase()) && !extension.forceAutoUpdate) {
405424
this.logService.info(`Skipping user installed builtin extension ${extension.identifier.id} with version ${extension.manifest.version} because it is not allowed to in the current product quality ${this.productService.quality}`);
406425
return;
407426
}
@@ -570,18 +589,20 @@ class ExtensionsScanner extends Disposable {
570589

571590
private readonly extensionsEnabledWithApiProposalVersion: string[];
572591
private readonly productQuality: string | undefined;
592+
private readonly productBuiltInExtensionsEnabledWithAutoUpdates: Set<string>;
573593

574594
constructor(
575595
@IExtensionsProfileScannerService protected readonly extensionsProfileScannerService: IExtensionsProfileScannerService,
576596
@IUriIdentityService protected readonly uriIdentityService: IUriIdentityService,
577597
@IFileService protected readonly fileService: IFileService,
578-
@IProductService private readonly productService: IProductService,
598+
@IProductService productService: IProductService,
579599
@IEnvironmentService private readonly environmentService: IEnvironmentService,
580600
@ILogService protected readonly logService: ILogService
581601
) {
582602
super();
583603
this.extensionsEnabledWithApiProposalVersion = productService.extensionsEnabledWithApiProposalVersion?.map(id => id.toLowerCase()) ?? [];
584604
this.productQuality = productService.quality;
605+
this.productBuiltInExtensionsEnabledWithAutoUpdates = getProductBuiltInExtensionsEnabledWithAutoUpdates(productService, environmentService);
585606
}
586607

587608
async scanExtensions(input: ExtensionScannerInput): Promise<IRelaxedScannedExtension[]> {
@@ -720,7 +741,7 @@ class ExtensionsScanner extends Disposable {
720741
isValid,
721742
validations,
722743
preRelease: !!metadata?.preRelease,
723-
forceAutoUpdate: this.productService.builtInExtensionsEnabledWithAutoUpdates.some(builtinExtensionId => builtinExtensionId.toLowerCase() === id.toLowerCase()) && this.productQuality === 'stable',
744+
forceAutoUpdate: this.productBuiltInExtensionsEnabledWithAutoUpdates.has(id.toLowerCase()) && this.productQuality === 'stable',
724745
};
725746
if (input.validate) {
726747
extension = this.validate(extension, input);

src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench
136136
});
137137
}
138138

139-
if (!this.environmentService.isSessionsWindow) {
139+
if (!this.environmentService.isSessionsWindow && !this.environmentService.skipBuiltinExtensions?.some(id => id.toLowerCase() === this._chatExtensionId)) {
140140
const builtinChatExtensionEnablementMigrationKey = 'builtinChatExtensionEnablementMigration';
141141
const builtinChatExtensionEnablementMigration = this.storageService.getBoolean(builtinChatExtensionEnablementMigrationKey, StorageScope.PROFILE) === true;
142142
if (!builtinChatExtensionEnablementMigration) {

0 commit comments

Comments
 (0)