Merge vscode source through 1.62 release (#19981)

* Build breaks 1

* Build breaks

* Build breaks

* Build breaks

* More build breaks

* Build breaks (#2512)

* Runtime breaks

* Build breaks

* Fix dialog location break

* Update typescript

* Fix ASAR break issue

* Unit test breaks

* Update distro

* Fix breaks in ADO builds (#2513)

* Bump to node 16

* Fix hygiene errors

* Bump distro

* Remove reference to node type

* Delete vscode specific extension

* Bump to node 16 in CI yaml

* Skip integration tests in CI builds (while fixing)

* yarn.lock update

* Bump moment dependency in remote yarn

* Fix drop-down chevron style

* Bump to node 16

* Remove playwrite from ci.yaml

* Skip building build scripts in hygine check
This commit is contained in:
Karl Burtram
2022-07-11 14:09:32 -07:00
committed by GitHub
parent fa0fcef303
commit 26455e9113
1876 changed files with 72050 additions and 37997 deletions

View File

@@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import { Promises as FSPromises } from 'vs/base/node/pfs';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { IExtensionGalleryService, IGalleryExtension, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionGalleryService, IGalleryExtension, InstallOperation, TargetPlatform } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionIdentifierWithVersion, groupByExtension } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IFileService, IFileStatWithMetadata } from 'vs/platform/files/common/files';
import { ILogService } from 'vs/platform/log/common/log';
@@ -72,7 +72,8 @@ export class ExtensionsDownloader extends Disposable {
}
async delete(location: URI): Promise<void> {
// noop as caching is enabled always
await this.cleanUpPromise;
await this.fileService.del(location);
}
private async rename(from: URI, to: URI, retryUntil: number): Promise<void> {
@@ -123,7 +124,7 @@ export class ExtensionsDownloader extends Disposable {
}
private getName(extension: IGalleryExtension): string {
return this.cache ? new ExtensionIdentifierWithVersion(extension.identifier, extension.version).key().toLowerCase() : generateUuid();
return this.cache ? `${new ExtensionIdentifierWithVersion(extension.identifier, extension.version).key().toLowerCase()}${extension.properties.targetPlatform !== TargetPlatform.UNDEFINED ? `-${extension.properties.targetPlatform}` : ''}` : generateUuid();
}
private parse(name: string): ExtensionIdentifierWithVersion | null {

View File

@@ -6,9 +6,11 @@
import { extensionsWorkbenchServiceIncompatible } from 'sql/base/common/locConstants';
import { CancellationToken } from 'vs/base/common/cancellation';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { getErrorMessage } from 'vs/base/common/errors';
import { Schemas } from 'vs/base/common/network';
import * as path from 'vs/base/common/path';
import { isMacintosh } from 'vs/base/common/platform';
import { isLinux, isMacintosh, platform } from 'vs/base/common/platform';
import { arch } from 'vs/base/common/process';
import { joinPath } from 'vs/base/common/resources';
import * as semver from 'vs/base/common/semver/semver';
import { URI } from 'vs/base/common/uri';
@@ -18,11 +20,10 @@ import { IFile, zip } from 'vs/base/node/zip';
import * as nls from 'vs/nls';
import { IDownloadService } from 'vs/platform/download/common/download';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { AbstractExtensionManagementService, AbstractExtensionTask, IInstallExtensionTask, INSTALL_ERROR_VALIDATING, IUninstallExtensionTask, joinErrors, UninstallExtensionTaskOptions } from 'vs/platform/extensionManagement/common/abstractExtensionManagementService';
import { AbstractExtensionManagementService, AbstractExtensionTask, IInstallExtensionTask, IUninstallExtensionTask, joinErrors, UninstallExtensionTaskOptions } from 'vs/platform/extensionManagement/common/abstractExtensionManagementService';
import {
ExtensionManagementError, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallOperation, InstallOptions,
InstallVSIXOptions,
INSTALL_ERROR_INCOMPATIBLE
ExtensionManagementError, ExtensionManagementErrorCode, getTargetPlatform, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallOperation, InstallOptions,
InstallVSIXOptions, TargetPlatform
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { areSameExtensions, ExtensionIdentifierWithVersion, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ExtensionsDownloader } from 'vs/platform/extensionManagement/node/extensionDownloader';
@@ -34,14 +35,11 @@ import { ExtensionsWatcher } from 'vs/platform/extensionManagement/node/extensio
import { ExtensionType, IExtensionManifest } from 'vs/platform/extensions/common/extensions';
import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator';
import { IFileService } from 'vs/platform/files/common/files';
import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILogService } from 'vs/platform/log/common/log';
import product from 'vs/platform/product/common/product';
import { IProductService } from 'vs/platform/product/common/productService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
const INSTALL_ERROR_UNSET_UNINSTALLED = 'unsetUninstalled';
const INSTALL_ERROR_DOWNLOADING = 'downloading';
interface InstallableExtension {
zipPath: string;
identifierWithVersion: ExtensionIdentifierWithVersion;
@@ -59,11 +57,12 @@ export class ExtensionManagementService extends AbstractExtensionManagementServi
@ITelemetryService telemetryService: ITelemetryService,
@ILogService logService: ILogService,
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
@optional(IDownloadService) private downloadService: IDownloadService,
@IDownloadService private downloadService: IDownloadService,
@IInstantiationService instantiationService: IInstantiationService,
@IFileService fileService: IFileService,
@IFileService private readonly fileService: IFileService,
@IProductService productService: IProductService
) {
super(galleryService, telemetryService, logService);
super(galleryService, telemetryService, logService, productService);
const extensionLifecycle = this._register(instantiationService.createInstance(ExtensionsLifecycle));
this.extensionsScanner = this._register(instantiationService.createInstance(ExtensionsScanner, extension => extensionLifecycle.postUninstall(extension)));
this.manifestCache = this._register(new ExtensionsManifestCache(environmentService, this));
@@ -78,6 +77,39 @@ export class ExtensionManagementService extends AbstractExtensionManagementServi
}));
}
private _targetPlatformPromise: Promise<TargetPlatform> | undefined;
getTargetPlatform(): Promise<TargetPlatform> {
if (!this._targetPlatformPromise) {
this._targetPlatformPromise = (async () => {
const isAlpineLinux = await this.isAlpineLinux();
const targetPlatform = getTargetPlatform(isAlpineLinux ? 'alpine' : platform, arch);
this.logService.debug('ExtensionManagementService#TargetPlatform:', targetPlatform);
return targetPlatform;
})();
}
return this._targetPlatformPromise;
}
private async isAlpineLinux(): Promise<boolean> {
if (!isLinux) {
return false;
}
let content: string | undefined;
try {
const fileContent = await this.fileService.readFile(URI.file('/etc/os-release'));
content = fileContent.value.toString();
} catch (error) {
try {
const fileContent = await this.fileService.readFile(URI.file('/usr/lib/os-release'));
content = fileContent.value.toString();
} catch (error) {
/* Ignore */
this.logService.debug(`Error while getting the os-release file.`, getErrorMessage(error));
}
}
return !!content && (content.match(/^ID=([^\u001b\r\n]*)/m) || [])[1] === 'alpine';
}
async zip(extension: ILocalExtension): Promise<URI> {
this.logService.trace('ExtensionManagementService#zip', extension.identifier.id);
const files = await this.collectFiles(extension);
@@ -101,10 +133,6 @@ export class ExtensionManagementService extends AbstractExtensionManagementServi
return this.extensionsScanner.scanExtensions(type);
}
async canInstall(extension: IGalleryExtension): Promise<boolean> {
return true;
}
async install(vsix: URI, options: InstallVSIXOptions = {}): Promise<ILocalExtension> {
this.logService.trace('ExtensionManagementService#install', vsix.toString());
@@ -112,15 +140,15 @@ export class ExtensionManagementService extends AbstractExtensionManagementServi
const manifest = await getManifest(path.resolve(downloadLocation.fsPath));
// {{SQL CARBON EDIT}} Do our own engine checks
const id = getGalleryExtensionId(manifest.publisher, manifest.name);
if (manifest.engines?.vscode && !isEngineValid(manifest.engines.vscode, product.vscodeVersion, product.date)) {
throw new Error(nls.localize('incompatible', "Unable to install extension '{0}' as it is not compatible with the current VS Code engine version '{1}'.", id, product.vscodeVersion));
if (manifest.engines?.vscode && !isEngineValid(manifest.engines.vscode, this.productService.vscodeVersion, this.productService.date)) {
throw new Error(nls.localize('incompatible', "Unable to install extension '{0}' as it is not compatible with the current VS Code engine version '{1}'.", id, this.productService.vscodeVersion));
}
if (manifest.engines?.azdata && !isEngineValid(manifest.engines.azdata, product.version, product.date)) {
throw new ExtensionManagementError(extensionsWorkbenchServiceIncompatible(id, manifest.version, product.version, manifest.engines.azdata), INSTALL_ERROR_INCOMPATIBLE);
if (manifest.engines?.azdata && !isEngineValid(manifest.engines.azdata, this.productService.version, this.productService.date)) {
throw new ExtensionManagementError(extensionsWorkbenchServiceIncompatible(id, manifest.version, this.productService.version, manifest.engines.azdata), ExtensionManagementErrorCode.Incompatible);
}
/*
if (manifest.engines && manifest.engines.vscode && !isEngineValid(manifest.engines.vscode, product.version, product.date)) {
throw new Error(nls.localize('incompatible', "Unable to install extension '{0}' as it is not compatible with VS Code '{1}'.", getGalleryExtensionId(manifest.publisher, manifest.name), product.version));
if (manifest.engines && manifest.engines.vscode && !isEngineValid(manifest.engines.vscode, this.productService.version, this.productService.date)) {
throw new Error(nls.localize('incompatible', "Unable to install extension '{0}' as it is not compatible with VS Code '{1}'.", getGalleryExtensionId(manifest.publisher, manifest.name), this.productService.version));
}
*/
@@ -149,10 +177,6 @@ export class ExtensionManagementService extends AbstractExtensionManagementServi
if (vsix.scheme === Schemas.file) {
return vsix;
}
if (!this.downloadService) {
throw new Error('Download service is not available');
}
const downloadedLocation = joinPath(this.environmentService.tmpDir, generateUuid());
await this.downloadService.download(vsix, downloadedLocation);
return downloadedLocation;
@@ -215,9 +239,9 @@ abstract class AbstractInstallExtensionTask extends AbstractExtensionTask<ILocal
}
} catch (e) {
if (isMacintosh) {
throw new ExtensionManagementError(nls.localize('quitCode', "Unable to install the extension. Please Quit and Start VS Code before reinstalling."), INSTALL_ERROR_UNSET_UNINSTALLED);
throw new ExtensionManagementError(nls.localize('quitCode', "Unable to install the extension. Please Quit and Start VS Code before reinstalling."), ExtensionManagementErrorCode.Internal);
} else {
throw new ExtensionManagementError(nls.localize('exitCode', "Unable to install the extension. Please Exit and Start VS Code before reinstalling."), INSTALL_ERROR_UNSET_UNINSTALLED);
throw new ExtensionManagementError(nls.localize('exitCode', "Unable to install the extension. Please Exit and Start VS Code before reinstalling."), ExtensionManagementErrorCode.Internal);
}
}
return this.extract(installableExtension, token);
@@ -243,11 +267,8 @@ abstract class AbstractInstallExtensionTask extends AbstractExtensionTask<ILocal
}
private async extract({ zipPath, identifierWithVersion, metadata }: InstallableExtension, token: CancellationToken): Promise<ILocalExtension> {
let local = await this.extensionsScanner.extractUserExtension(identifierWithVersion, zipPath, token);
let local = await this.extensionsScanner.extractUserExtension(identifierWithVersion, zipPath, metadata, token);
this.logService.info('Extracting completed.', identifierWithVersion.id);
if (metadata) {
local = await this.extensionsScanner.saveMetadataForLocalExtension(local, metadata);
}
return local;
}
@@ -276,12 +297,25 @@ class InstallGalleryExtensionTask extends AbstractInstallExtensionTask {
installableExtension.metadata.isMachineScoped = this.options.isMachineScoped || existingExtension?.isMachineScoped;
installableExtension.metadata.isBuiltin = this.options.isBuiltin || existingExtension?.isBuiltin;
const local = await this.installExtension(installableExtension, token);
if (existingExtension && semver.neq(existingExtension.manifest.version, this.gallery.version)) {
await this.extensionsScanner.setUninstalled(existingExtension);
try {
const local = await this.installExtension(installableExtension, token);
if (existingExtension && semver.neq(existingExtension.manifest.version, this.gallery.version)) {
await this.extensionsScanner.setUninstalled(existingExtension);
}
return local;
} catch (error) {
await this.deleteDownloadedVSIX(installableExtension.zipPath);
throw error;
}
}
private async deleteDownloadedVSIX(vsix: string): Promise<void> {
try {
await this.extensionsDownloader.delete(URI.file(vsix));
} catch (error) {
/* Ignore */
this.logService.warn('Error while deleting the downloaded vsix', vsix.toString(), getErrorMessage(error));
}
try { await this.extensionsDownloader.delete(URI.file(installableExtension.zipPath)); } catch (error) { /* Ignore */ }
return local;
}
private async downloadInstallableExtension(extension: IGalleryExtension, operation: InstallOperation): Promise<Required<InstallableExtension>> {
@@ -297,14 +331,15 @@ class InstallGalleryExtensionTask extends AbstractInstallExtensionTask {
zipPath = (await this.extensionsDownloader.downloadExtension(extension, operation)).fsPath;
this.logService.info('Downloaded extension:', extension.identifier.id, zipPath);
} catch (error) {
throw new ExtensionManagementError(joinErrors(error).message, INSTALL_ERROR_DOWNLOADING);
throw new ExtensionManagementError(joinErrors(error).message, ExtensionManagementErrorCode.Download);
}
try {
const manifest = await getManifest(zipPath);
return (<Required<InstallableExtension>>{ zipPath, identifierWithVersion: new ExtensionIdentifierWithVersion(extension.identifier, manifest.version), metadata });
} catch (error) {
throw new ExtensionManagementError(joinErrors(error).message, INSTALL_ERROR_VALIDATING);
await this.deleteDownloadedVSIX(zipPath);
throw new ExtensionManagementError(joinErrors(error).message, ExtensionManagementErrorCode.Invalid);
}
}
}
@@ -327,10 +362,10 @@ class InstallVSIXTask extends AbstractInstallExtensionTask {
const installedExtensions = await this.extensionsScanner.scanExtensions(ExtensionType.User);
const existing = installedExtensions.find(i => areSameExtensions(this.identifier, i.identifier));
const metadata = await this.getMetadata(this.identifier.id, token);
metadata.isMachineScoped = this.options.isMachineScoped || existing?.isMachineScoped;
metadata.isBuiltin = this.options.isBuiltin || existing?.isBuiltin;
if (existing) {
metadata.isMachineScoped = this.options.isMachineScoped || existing.isMachineScoped;
metadata.isBuiltin = this.options.isBuiltin || existing.isBuiltin;
this._operation = InstallOperation.Update;
if (identifierWithVersion.equals(new ExtensionIdentifierWithVersion(existing.identifier, existing.manifest.version))) {
try {

View File

@@ -19,7 +19,7 @@ import * as pfs from 'vs/base/node/pfs';
import { extract, ExtractError } from 'vs/base/node/zip';
import { localize } from 'vs/nls';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { ExtensionManagementError, IGalleryMetadata, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionManagementError, ExtensionManagementErrorCode, IGalleryMetadata, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { areSameExtensions, ExtensionIdentifierWithVersion, getGalleryExtensionId, groupByExtension } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls';
import { ExtensionType, IExtensionIdentifier, IExtensionManifest } from 'vs/platform/extensions/common/extensions';
@@ -28,12 +28,6 @@ import { ILogService } from 'vs/platform/log/common/log';
import { IProductService } from 'vs/platform/product/common/productService';
import { CancellationToken } from 'vscode';
const ERROR_SCANNING_SYS_EXTENSIONS = 'scanningSystem';
const ERROR_SCANNING_USER_EXTENSIONS = 'scanningUser';
const INSTALL_ERROR_EXTRACTING = 'extracting';
const INSTALL_ERROR_DELETING = 'deleting';
const INSTALL_ERROR_RENAMING = 'renaming';
export type IMetadata = Partial<IGalleryMetadata & { isMachineScoped: boolean; isBuiltin: boolean; }>;
type IStoredMetadata = IMetadata & { installedTimestamp: number | undefined };
export type ILocalExtensionManifest = IExtensionManifest & { __metadata?: IMetadata };
@@ -69,11 +63,11 @@ export class ExtensionsScanner extends Disposable {
const promises: Promise<ILocalExtension[]>[] = [];
if (type === null || type === ExtensionType.System) {
promises.push(this.scanSystemExtensions().then(null, e => Promise.reject(new ExtensionManagementError(this.joinErrors(e).message, ERROR_SCANNING_SYS_EXTENSIONS))));
promises.push(this.scanSystemExtensions().then(null, e => Promise.reject(new ExtensionManagementError(this.joinErrors(e).message, ExtensionManagementErrorCode.Internal))));
}
if (type === null || type === ExtensionType.User) {
promises.push(this.scanUserExtensions(true).then(null, e => Promise.reject(new ExtensionManagementError(this.joinErrors(e).message, ERROR_SCANNING_USER_EXTENSIONS))));
promises.push(this.scanUserExtensions(true).then(null, e => Promise.reject(new ExtensionManagementError(this.joinErrors(e).message, ExtensionManagementErrorCode.Internal))));
}
try {
@@ -100,7 +94,7 @@ export class ExtensionsScanner extends Disposable {
return this.scanExtensionsInDir(this.extensionsPath, ExtensionType.User);
}
async extractUserExtension(identifierWithVersion: ExtensionIdentifierWithVersion, zipPath: string, token: CancellationToken): Promise<ILocalExtension> {
async extractUserExtension(identifierWithVersion: ExtensionIdentifierWithVersion, zipPath: string, metadata: IMetadata | undefined, token: CancellationToken): Promise<ILocalExtension> {
const folderName = identifierWithVersion.key();
const tempPath = path.join(this.extensionsPath, `.${generateUuid()}`);
const extensionPath = path.join(this.extensionsPath, folderName);
@@ -111,7 +105,7 @@ export class ExtensionsScanner extends Disposable {
try {
await pfs.Promises.rm(extensionPath);
} catch (e) { /* ignore */ }
throw new ExtensionManagementError(localize('errorDeleting', "Unable to delete the existing folder '{0}' while installing the extension '{1}'. Please delete the folder manually and try again", extensionPath, identifierWithVersion.id), INSTALL_ERROR_DELETING);
throw new ExtensionManagementError(localize('errorDeleting', "Unable to delete the existing folder '{0}' while installing the extension '{1}'. Please delete the folder manually and try again", extensionPath, identifierWithVersion.id), ExtensionManagementErrorCode.Delete);
}
await this.extractAtLocation(identifierWithVersion, zipPath, tempPath, token);
@@ -119,7 +113,7 @@ export class ExtensionsScanner extends Disposable {
if (!local) {
throw new Error(localize('cannot read', "Cannot read the extension from {0}", tempPath));
}
await this.storeMetadata(local, { installedTimestamp: Date.now() });
await this.storeMetadata(local, { ...metadata, installedTimestamp: Date.now() });
try {
await this.rename(identifierWithVersion, tempPath, extensionPath, Date.now() + (2 * 60 * 1000) /* Retry for 2 minutes */);
@@ -236,7 +230,7 @@ export class ExtensionsScanner extends Disposable {
try {
await pfs.Promises.rm(location);
} catch (e) {
throw new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_DELETING);
throw new ExtensionManagementError(this.joinErrors(e).message, ExtensionManagementErrorCode.Delete);
}
try {
@@ -244,7 +238,15 @@ export class ExtensionsScanner extends Disposable {
this.logService.info(`Extracted extension to ${location}:`, identifier.id);
} catch (e) {
try { await pfs.Promises.rm(location); } catch (e) { /* Ignore */ }
throw new ExtensionManagementError(e.message, e instanceof ExtractError && e.type ? e.type : INSTALL_ERROR_EXTRACTING);
let errorCode = ExtensionManagementErrorCode.Extract;
if (e instanceof ExtractError) {
if (e.type === 'CorruptZip') {
errorCode = ExtensionManagementErrorCode.CorruptZip;
} else if (e.type === 'Incomplete') {
errorCode = ExtensionManagementErrorCode.IncompleteZip;
}
}
throw new ExtensionManagementError(e.message, errorCode);
}
}
@@ -256,7 +258,7 @@ export class ExtensionsScanner extends Disposable {
this.logService.info(`Failed renaming ${extractPath} to ${renamePath} with 'EPERM' error. Trying again...`, identifier.id);
return this.rename(identifier, extractPath, renamePath, retryUntil);
}
throw new ExtensionManagementError(error.message || localize('renameError', "Unknown error while renaming {0} to {1}", extractPath, renamePath), error.code || INSTALL_ERROR_RENAMING);
throw new ExtensionManagementError(error.message || localize('renameError', "Unknown error while renaming {0} to {1}", extractPath, renamePath), error.code || ExtensionManagementErrorCode.Rename);
}
}