Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79 (#14050)

* Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79

* Fix breaks

* Extension management fixes

* Fix breaks in windows bundling

* Fix/skip failing tests

* Update distro

* Add clear to nuget.config

* Add hygiene task

* Bump distro

* Fix hygiene issue

* Add build to hygiene exclusion

* Update distro

* Update hygiene

* Hygiene exclusions

* Update tsconfig

* Bump distro for server breaks

* Update build config

* Update darwin path

* Add done calls to notebook tests

* Skip failing tests

* Disable smoke tests
This commit is contained in:
Karl Burtram
2021-02-09 16:15:05 -08:00
committed by GitHub
parent 6f192f9af5
commit ce612a3d96
1929 changed files with 68012 additions and 34564 deletions

View File

@@ -18,13 +18,15 @@ import {
InstallOperation,
INSTALL_ERROR_MALICIOUS,
INSTALL_ERROR_INCOMPATIBLE,
ExtensionManagementError
ExtensionManagementError,
InstallOptions,
UninstallOptions
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { areSameExtensions, getGalleryExtensionId, getMaliciousExtensionsSet, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, ExtensionIdentifierWithVersion } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { createCancelablePromise, CancelablePromise } from 'vs/base/common/async';
import { Event, Emitter } from 'vs/base/common/event';
import * as semver from 'semver-umd';
import * as semver from 'vs/base/common/semver/semver';
import { URI } from 'vs/base/common/uri';
import product from 'vs/platform/product/common/product';
import { isMacintosh } from 'vs/base/common/platform';
@@ -33,7 +35,7 @@ import { ExtensionsManifestCache } from 'vs/platform/extensionManagement/node/ex
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator';
import { tmpdir } from 'os';
import { joinPath } from 'vs/base/common/resources';
import { generateUuid } from 'vs/base/common/uuid';
import { IDownloadService } from 'vs/platform/download/common/download';
import { optional, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -42,7 +44,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { getManifest } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
import { IExtensionManifest, ExtensionType } from 'vs/platform/extensions/common/extensions';
import { ExtensionsDownloader } from 'vs/platform/extensionManagement/node/extensionDownloader';
import { ExtensionsScanner, IMetadata } from 'vs/platform/extensionManagement/node/extensionsScanner';
import { ExtensionsScanner, ILocalExtensionManifest, IMetadata } from 'vs/platform/extensionManagement/node/extensionsScanner';
import { ExtensionsLifecycle } from 'vs/platform/extensionManagement/node/extensionLifecycle';
const INSTALL_ERROR_UNSET_UNINSTALLED = 'unsetUninstalled';
@@ -82,7 +84,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
onDidUninstallExtension: Event<DidUninstallExtensionEvent> = this._onDidUninstallExtension.event;
constructor(
@IEnvironmentService environmentService: INativeEnvironmentService,
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
@ILogService private readonly logService: ILogService,
@optional(IDownloadService) private downloadService: IDownloadService,
@@ -106,7 +108,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
async zip(extension: ILocalExtension): Promise<URI> {
this.logService.trace('ExtensionManagementService#zip', extension.identifier.id);
const files = await this.collectFiles(extension);
const location = await zip(path.join(tmpdir(), generateUuid()), files);
const location = await zip(joinPath(this.environmentService.tmpDir, generateUuid()).fsPath, files);
return URI.file(location);
}
@@ -147,10 +149,9 @@ export class ExtensionManagementService extends Disposable implements IExtension
return files.map(f => (<IFile>{ path: `extension/${path.relative(extension.location.fsPath, f)}`, localPath: f }));
}
async install(vsix: URI, isMachineScoped?: boolean): Promise<ILocalExtension> {
async install(vsix: URI, options: InstallOptions = {}): Promise<ILocalExtension> {
// {{SQL CARBON EDIT}}
let startTime = new Date().getTime();
this.logService.trace('ExtensionManagementService#install', vsix.toString());
return createCancelablePromise(async token => {
@@ -172,7 +173,8 @@ export class ExtensionManagementService extends Disposable implements IExtension
const installedExtensions = await this.getInstalled(ExtensionType.User);
const existing = installedExtensions.find(i => areSameExtensions(identifier, i.identifier));
if (existing) {
isMachineScoped = isMachineScoped || existing.isMachineScoped;
options.isMachineScoped = options.isMachineScoped || existing.isMachineScoped;
options.isBuiltin = options.isBuiltin || existing.isBuiltin;
// operation = InstallOperation.Update; {{ SQL CARBON EDIT }}
if (identifierWithVersion.equals(new ExtensionIdentifierWithVersion(existing.identifier, existing.manifest.version))) {
try {
@@ -201,6 +203,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
// {{SQL CARBON EDIT}}
// Until there's a gallery for SQL Ops Studio, skip retrieving the metadata from the gallery
let isMachineScoped = options.isMachineScoped;
return this.installExtension({ zipPath, identifierWithVersion, metadata: { isMachineScoped } }, token)
.then(
local => {
@@ -234,7 +237,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
throw new Error('Download service is not available');
}
const downloadedLocation = URI.file(path.join(tmpdir(), generateUuid()));
const downloadedLocation = joinPath(this.environmentService.tmpDir, generateUuid());
await this.downloadService.download(vsix, downloadedLocation);
return downloadedLocation;
}
@@ -244,7 +247,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
try {
const local = await this.installExtension({ zipPath, identifierWithVersion, metadata }, token);
try {
await this.installDependenciesAndPackExtensions(local, undefined);
await this.installDependenciesAndPackExtensions(local, undefined, options);
} catch (error) {
if (isNonEmptyArray(local.manifest.extensionDependencies)) {
this.logService.warn(`Cannot install dependencies of extension:`, local.identifier.id, error.message);
@@ -253,10 +256,10 @@ export class ExtensionManagementService extends Disposable implements IExtension
this.logService.warn(`Cannot install packed extensions of extension:`, local.identifier.id, error.message);
}
}
this._onDidInstallExtension.fire({ identifier: identifierWithVersion.identifier, zipPath, local, operation });
this._onDidInstallExtension.fire({ identifier: identifierWithVersion, zipPath, local, operation });
return local;
} catch (error) {
this._onDidInstallExtension.fire({ identifier: identifierWithVersion.identifier, zipPath, operation, error });
this._onDidInstallExtension.fire({ identifier: identifierWithVersion, zipPath, operation, error });
throw error;
}
}*/
@@ -265,7 +268,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
return true;
}
async installFromGallery(extension: IGalleryExtension, isMachineScoped?: boolean): Promise<ILocalExtension> {
async installFromGallery(extension: IGalleryExtension, options: InstallOptions = {}): Promise<ILocalExtension> {
if (!this.galleryService.isEnabled()) {
throw new Error(nls.localize('MarketPlaceDisabled', "Marketplace is not enabled"));
}
@@ -285,7 +288,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
const key = new ExtensionIdentifierWithVersion(extension.identifier, extension.version).key();
let cancellablePromise = this.installingExtensions.get(key);
if (!cancellablePromise) {
cancellablePromise = createCancelablePromise(token => this.doInstallFromGallery(extension, !!isMachineScoped, token));
cancellablePromise = createCancelablePromise(token => this.doInstallFromGallery(extension, options, token));
this.installingExtensions.set(key, cancellablePromise);
cancellablePromise.finally(() => this.installingExtensions.delete(key));
}
@@ -293,7 +296,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
return cancellablePromise;
}
private async doInstallFromGallery(extension: IGalleryExtension, isMachineScoped: boolean, token: CancellationToken): Promise<ILocalExtension> {
private async doInstallFromGallery(extension: IGalleryExtension, options: InstallOptions, token: CancellationToken): Promise<ILocalExtension> {
const startTime = new Date().getTime();
let operation: InstallOperation = InstallOperation.Install;
this.logService.info('Installing extension:', extension.identifier.id);
@@ -307,16 +310,19 @@ export class ExtensionManagementService extends Disposable implements IExtension
}
const installableExtension = await this.downloadInstallableExtension(extension, operation);
installableExtension.metadata.isMachineScoped = isMachineScoped || existingExtension?.isMachineScoped;
installableExtension.metadata.isMachineScoped = options.isMachineScoped || existingExtension?.isMachineScoped;
installableExtension.metadata.isBuiltin = options.isBuiltin || existingExtension?.isBuiltin;
const local = await this.installExtension(installableExtension, token);
try { await this.extensionsDownloader.delete(URI.file(installableExtension.zipPath)); } catch (error) { /* Ignore */ }
try {
await this.installDependenciesAndPackExtensions(local, existingExtension);
} catch (error) {
try { await this.uninstall(local); } catch (error) { /* Ignore */ }
throw error;
if (!options.donotIncludePackAndDependencies) {
try {
await this.installDependenciesAndPackExtensions(local, existingExtension, options);
} catch (error) {
try { await this.uninstall(local); } catch (error) { /* Ignore */ }
throw error;
}
}
if (existingExtension && semver.neq(existingExtension.manifest.version, extension.version)) {
@@ -412,7 +418,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
try {
const local = await this.unsetUninstalledAndGetLocal(installableExtension.identifierWithVersion);
if (local) {
return local;
return installableExtension.metadata ? this.extensionsScanner.saveMetadataForLocalExtension(local, installableExtension.metadata) : local;
}
} catch (e) {
if (isMacintosh) {
@@ -430,26 +436,25 @@ export class ExtensionManagementService extends Disposable implements IExtension
return null;
}
this.logService.trace('Removing the extension from uninstalled list:', identifierWithVersion.identifier.id);
this.logService.trace('Removing the extension from uninstalled list:', identifierWithVersion.id);
// If the same version of extension is marked as uninstalled, remove it from there and return the local.
await this.unsetUninstalled(identifierWithVersion);
this.logService.info('Removed the extension from uninstalled list:', identifierWithVersion.identifier.id);
this.logService.info('Removed the extension from uninstalled list:', identifierWithVersion.id);
const installed = await this.getInstalled(ExtensionType.User);
return installed.find(i => new ExtensionIdentifierWithVersion(i.identifier, i.manifest.version).equals(identifierWithVersion)) || null;
}
private async extractAndInstall({ zipPath, identifierWithVersion, metadata }: InstallableExtension, token: CancellationToken): Promise<ILocalExtension> {
const { identifier } = identifierWithVersion;
let local = await this.extensionsScanner.extractUserExtension(identifierWithVersion, zipPath, token);
this.logService.info('Installation completed.', identifier.id);
this.logService.info('Installation completed.', identifierWithVersion.id);
if (metadata) {
local = await this.extensionsScanner.saveMetadataForLocalExtension(local, metadata);
}
return local;
}
private async installDependenciesAndPackExtensions(installed: ILocalExtension, existing: ILocalExtension | undefined): Promise<void> {
private async installDependenciesAndPackExtensions(installed: ILocalExtension, existing: ILocalExtension | undefined, options: InstallOptions): Promise<void> {
if (!this.galleryService.isEnabled()) {
return;
}
@@ -472,7 +477,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
const galleryResult = await this.galleryService.query({ names, pageSize: dependenciesAndPackExtensions.length }, CancellationToken.None);
const extensionsToInstall = galleryResult.firstPage;
try {
await Promise.all(extensionsToInstall.map(e => this.installFromGallery(e)));
await Promise.all(extensionsToInstall.map(e => this.installFromGallery(e, options)));
} catch (error) {
try { await this.rollback(extensionsToInstall); } catch (e) { /* ignore */ }
throw error;
@@ -487,7 +492,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
await Promise.all(extensionsToUninstall.map(local => this.uninstall(local)));
}
async uninstall(extension: ILocalExtension): Promise<void> {
async uninstall(extension: ILocalExtension, options: UninstallOptions = {}): Promise<void> {
this.logService.trace('ExtensionManagementService#uninstall', extension.identifier.id);
const installed = await this.getInstalled(ExtensionType.User);
const extensionToUninstall = installed.find(e => areSameExtensions(e.identifier, extension.identifier));
@@ -496,7 +501,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
}
try {
await this.checkForDependenciesAndUninstall(extensionToUninstall, installed);
await this.checkForDependenciesAndUninstall(extensionToUninstall, installed, options);
} catch (error) {
throw this.joinErrors(error);
}
@@ -504,7 +509,14 @@ export class ExtensionManagementService extends Disposable implements IExtension
async updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): Promise<ILocalExtension> {
this.logService.trace('ExtensionManagementService#updateMetadata', local.identifier.id);
local = await this.extensionsScanner.saveMetadataForLocalExtension(local, { ...metadata, isMachineScoped: local.isMachineScoped });
local = await this.extensionsScanner.saveMetadataForLocalExtension(local, { ...((<ILocalExtensionManifest>local.manifest).__metadata || {}), ...metadata });
this.manifestCache.invalidate();
return local;
}
async updateExtensionScope(local: ILocalExtension, isMachineScoped: boolean): Promise<ILocalExtension> {
this.logService.trace('ExtensionManagementService#updateExtensionScope', local.identifier.id);
local = await this.extensionsScanner.saveMetadataForLocalExtension(local, { ...((<ILocalExtensionManifest>local.manifest).__metadata || {}), isMachineScoped });
this.manifestCache.invalidate();
return local;
}
@@ -543,15 +555,11 @@ export class ExtensionManagementService extends Disposable implements IExtension
}, new Error(''));
}
private async checkForDependenciesAndUninstall(extension: ILocalExtension, installed: ILocalExtension[]): Promise<void> {
private async checkForDependenciesAndUninstall(extension: ILocalExtension, installed: ILocalExtension[], options: UninstallOptions): Promise<void> {
try {
await this.preUninstallExtension(extension);
const packedExtensions = this.getAllPackExtensionsToUninstall(extension, installed);
if (packedExtensions.length) {
await this.uninstallExtensions(extension, packedExtensions, installed);
} else {
await this.uninstallExtensions(extension, [], installed);
}
const packedExtensions = options.donotIncludePack ? [] : this.getAllPackExtensionsToUninstall(extension, installed);
await this.uninstallExtensions(extension, packedExtensions, installed, options);
} catch (error) {
await this.postUninstallExtension(extension, new ExtensionManagementError(error instanceof Error ? error.message : error, INSTALL_ERROR_LOCAL));
throw error;
@@ -559,10 +567,12 @@ export class ExtensionManagementService extends Disposable implements IExtension
await this.postUninstallExtension(extension);
}
private async uninstallExtensions(extension: ILocalExtension, otherExtensionsToUninstall: ILocalExtension[], installed: ILocalExtension[]): Promise<void> {
private async uninstallExtensions(extension: ILocalExtension, otherExtensionsToUninstall: ILocalExtension[], installed: ILocalExtension[], options: UninstallOptions): Promise<void> {
const extensionsToUninstall = [extension, ...otherExtensionsToUninstall];
for (const e of extensionsToUninstall) {
this.checkForDependents(e, extensionsToUninstall, installed, extension);
if (!options.donotCheckDependents) {
for (const e of extensionsToUninstall) {
this.checkForDependents(e, extensionsToUninstall, installed, extension);
}
}
await Promise.all([this.uninstallExtension(extension), ...otherExtensionsToUninstall.map(d => this.doUninstall(d))]);
}
@@ -613,7 +623,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
checked.push(extension);
const extensionsPack = extension.manifest.extensionPack ? extension.manifest.extensionPack : [];
if (extensionsPack.length) {
const packedExtensions = installed.filter(i => extensionsPack.some(id => areSameExtensions({ id }, i.identifier)));
const packedExtensions = installed.filter(i => !i.isBuiltin && extensionsPack.some(id => areSameExtensions({ id }, i.identifier)));
const packOfPackedExtensions: ILocalExtension[] = [];
for (const packedExtension of packedExtensions) {
packOfPackedExtensions.push(...this.getAllPackExtensionsToUninstall(packedExtension, installed, checked));