Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)

* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973

* disable strict null check
This commit is contained in:
Anthony Dresser
2019-07-15 22:35:46 -07:00
committed by GitHub
parent f720ec642f
commit 0b7e7ddbf9
2406 changed files with 59140 additions and 35464 deletions

View File

@@ -21,7 +21,7 @@ import {
INSTALL_ERROR_MALICIOUS,
INSTALL_ERROR_INCOMPATIBLE
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { areSameExtensions, getGalleryExtensionId, groupByExtension, getMaliciousExtensionsSet, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { areSameExtensions, getGalleryExtensionId, groupByExtension, getMaliciousExtensionsSet, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, ExtensionIdentifierWithVersion } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { localizeManifest } from '../common/extensionNls';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { Limiter, createCancelablePromise, CancelablePromise, Queue } from 'vs/base/common/async';
@@ -35,7 +35,7 @@ import { ExtensionsManifestCache } from 'vs/platform/extensionManagement/node/ex
import { ExtensionsLifecycle } from 'vs/platform/extensionManagement/node/extensionLifecycle';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { isEngineValid } from 'vs/platform/extensions/node/extensionValidator';
import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator';
import { tmpdir } from 'os';
import { generateUuid } from 'vs/base/common/uuid';
import { IDownloadService } from 'vs/platform/download/common/download';
@@ -44,7 +44,7 @@ import { Schemas } from 'vs/base/common/network';
import { CancellationToken } from 'vs/base/common/cancellation';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { getManifest } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
import { IExtensionManifest, ExtensionType, ExtensionIdentifierWithVersion } from 'vs/platform/extensions/common/extensions';
import { IExtensionManifest, ExtensionType } from 'vs/platform/extensions/common/extensions';
// {{SQL CARBON EDIT}
import product from 'vs/platform/product/node/product';
@@ -112,21 +112,21 @@ export class ExtensionManagementService extends Disposable implements IExtension
private uninstalledFileLimiter: Queue<any>;
private reportedExtensions: Promise<IReportedExtension[]> | undefined;
private lastReportTimestamp = 0;
private readonly installingExtensions: Map<string, CancelablePromise<void>> = new Map<string, CancelablePromise<void>>();
private readonly installingExtensions: Map<string, CancelablePromise<ILocalExtension>> = new Map<string, CancelablePromise<ILocalExtension>>();
private readonly uninstallingExtensions: Map<string, CancelablePromise<void>> = new Map<string, CancelablePromise<void>>();
private readonly manifestCache: ExtensionsManifestCache;
private readonly extensionLifecycle: ExtensionsLifecycle;
private readonly _onInstallExtension = new Emitter<InstallExtensionEvent>();
private readonly _onInstallExtension = this._register(new Emitter<InstallExtensionEvent>());
readonly onInstallExtension: Event<InstallExtensionEvent> = this._onInstallExtension.event;
private readonly _onDidInstallExtension = new Emitter<DidInstallExtensionEvent>();
private readonly _onDidInstallExtension = this._register(new Emitter<DidInstallExtensionEvent>());
readonly onDidInstallExtension: Event<DidInstallExtensionEvent> = this._onDidInstallExtension.event;
private readonly _onUninstallExtension = new Emitter<IExtensionIdentifier>();
private readonly _onUninstallExtension = this._register(new Emitter<IExtensionIdentifier>());
readonly onUninstallExtension: Event<IExtensionIdentifier> = this._onUninstallExtension.event;
private _onDidUninstallExtension = new Emitter<DidUninstallExtensionEvent>();
private _onDidUninstallExtension = this._register(new Emitter<DidUninstallExtensionEvent>());
onDidUninstallExtension: Event<DidUninstallExtensionEvent> = this._onDidUninstallExtension.event;
constructor(
@@ -161,7 +161,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
unzip(zipLocation: URI, type: ExtensionType): Promise<IExtensionIdentifier> {
this.logService.trace('ExtensionManagementService#unzip', zipLocation.toString());
return this.install(zipLocation, type);
return this.install(zipLocation, type).then(local => local.identifier);
}
private collectFiles(extension: ILocalExtension): Promise<IFile[]> {
@@ -190,7 +190,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
}
install(vsix: URI, type: ExtensionType = ExtensionType.User): Promise<IExtensionIdentifier> {
install(vsix: URI, type: ExtensionType = ExtensionType.User): Promise<ILocalExtension> {
// {{SQL CARBON EDIT}}
let startTime = new Date().getTime();
@@ -232,20 +232,20 @@ export class ExtensionManagementService extends Disposable implements IExtension
local => {
this.reportTelemetry(this.getTelemetryEvent(InstallOperation.Install), getLocalExtensionTelemetryData(local), new Date().getTime() - startTime, void 0);
this._onDidInstallExtension.fire({ identifier, zipPath, local, operation: InstallOperation.Install });
return identifier;
return local;
},
error => { this._onDidInstallExtension.fire({ identifier, zipPath, error, operation: InstallOperation.Install }); return Promise.reject(error); }
);
// return this.getMetadata(getGalleryExtensionId(manifest.publisher, manifest.name))
// .then(
// metadata => this.installFromZipPath(identifierWithVersion, zipPath, metadata, type, operation, token),
// () => this.installFromZipPath(identifierWithVersion, zipPath, null, type, operation, token))
// .then(
// () => { this.logService.info('Successfully installed the extension:', identifier.id); return identifier; },
// e => {
// this.logService.error('Failed to install the extension:', identifier.id, e.message);
// return Promise.reject(e);
// });
// () => this.installFromZipPath(identifierWithVersion, zipPath, null, type, operation, token))
// .then(
// local => { this.logService.info('Successfully installed the extension:', identifier.id); return local; },
// e => {
// this.logService.error('Failed to install the extension:', identifier.id, e.message);
// return Promise.reject(e);
// });
// {{SQL CARBON EDIT}} - End
});
});
@@ -284,12 +284,12 @@ export class ExtensionManagementService extends Disposable implements IExtension
));
}
async installFromGallery(extension: IGalleryExtension): Promise<void> {
async installFromGallery(extension: IGalleryExtension): Promise<ILocalExtension> {
if (!this.galleryService.isEnabled()) {
return Promise.reject(new Error(nls.localize('MarketPlaceDisabled', "Marketplace is not enabled")));
}
const startTime = new Date().getTime();
this.logService.info('Installing extension:', extension.identifier.id);
this._onInstallExtension.fire({ identifier: extension.identifier, gallery: extension });
const onDidInstallExtensionSuccess = (extension: IGalleryExtension, operation: InstallOperation, local: ILocalExtension) => {
this.logService.info(`Extensions installed successfully:`, extension.identifier.id);
this._onDidInstallExtension.fire({ identifier: extension.identifier, gallery: extension, local, operation });
@@ -317,8 +317,11 @@ export class ExtensionManagementService extends Disposable implements IExtension
let cancellablePromise = this.installingExtensions.get(key);
if (!cancellablePromise) {
this.logService.info('Installing extension:', extension.identifier.id);
this._onInstallExtension.fire({ identifier: extension.identifier, gallery: extension });
let operation: InstallOperation = InstallOperation.Install;
let cancellationToken: CancellationToken, successCallback: (a?: any) => void, errorCallback: (e?: any) => any | null;
let cancellationToken: CancellationToken, successCallback: (local: ILocalExtension) => void, errorCallback: (e?: any) => any | null;
cancellablePromise = createCancelablePromise(token => { cancellationToken = token; return new Promise((c, e) => { successCallback = c; errorCallback = e; }); });
this.installingExtensions.set(key, cancellablePromise);
try {
@@ -340,7 +343,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
}
this.installingExtensions.delete(key);
onDidInstallExtensionSuccess(extension, operation, local);
successCallback(null);
successCallback(local);
},
error => {
this.installingExtensions.delete(key);
@@ -367,7 +370,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
const compatibleExtension = await this.galleryService.getCompatibleExtension(extension);
if (!compatibleExtension) {
return Promise.reject(new ExtensionManagementError(nls.localize('notFoundCompatibleDependency', "Unable to install because, the extension '{0}' compatible with current version '{1}' of VS Code is not found.", extension.identifier.id, pkg.version), INSTALL_ERROR_INCOMPATIBLE));
return Promise.reject(new ExtensionManagementError(nls.localize('notFoundCompatibleDependency', "Unable to install '{0}' extension because it is not compatible with the current version of VS Code (version {1}).", extension.identifier.id, pkg.version), INSTALL_ERROR_INCOMPATIBLE));
}
return compatibleExtension;
@@ -408,9 +411,10 @@ export class ExtensionManagementService extends Disposable implements IExtension
};
this.logService.trace('Started downloading extension:', extension.identifier.id);
return this.galleryService.download(extension, operation)
return this.galleryService.download(extension, URI.file(tmpdir()), operation)
.then(
zipPath => {
zip => {
const zipPath = zip.fsPath;
this.logService.info('Downloaded extension:', extension.identifier.id, zipPath);
return getManifest(zipPath)
.then(
@@ -470,7 +474,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
}
this.logService.info('Installation completed.', identifier.id);
if (metadata) {
local.metadata = metadata;
this.setMetadata(local, metadata);
return this.saveMetadataForLocalExtension(local);
}
return local;
@@ -500,12 +504,12 @@ export class ExtensionManagementService extends Disposable implements IExtension
e => Promise.reject(new ExtensionManagementError(this.joinErrors(e).message, INSTALL_ERROR_DELETING)));
}
private rename(identfier: IExtensionIdentifier, extractPath: string, renamePath: string, retryUntil: number): Promise<void> {
private rename(identifier: IExtensionIdentifier, extractPath: string, renamePath: string, retryUntil: number): Promise<void> {
return pfs.rename(extractPath, renamePath)
.then(undefined, error => {
if (isWindows && error && error.code === 'EPERM' && Date.now() < retryUntil) {
this.logService.info(`Failed renaming ${extractPath} to ${renamePath} with 'EPERM' error. Trying again...`, identfier.id);
return this.rename(identfier, extractPath, renamePath, retryUntil);
this.logService.info(`Failed renaming ${extractPath} to ${renamePath} with 'EPERM' error. Trying again...`, identifier.id);
return this.rename(identifier, extractPath, renamePath, retryUntil);
}
return Promise.reject(new ExtensionManagementError(error.message || nls.localize('renameError', "Unknown error while renaming {0} to {1}", extractPath, renamePath), error.code || INSTALL_ERROR_RENAMING));
});
@@ -743,7 +747,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
this.logService.trace('Started scanning system extensions');
const systemExtensionsPromise = this.scanExtensions(this.systemExtensionsPath, ExtensionType.System)
.then(result => {
this.logService.info('Scanned system extensions:', result.length);
this.logService.trace('Scanned system extensions:', result.length);
return result;
});
if (this.environmentService.isBuilt) {
@@ -756,7 +760,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
if (devSystemExtensionsList.length) {
return this.scanExtensions(this.devSystemExtensionsPath, ExtensionType.System)
.then(result => {
this.logService.info('Scanned dev system extensions:', result.length);
this.logService.trace('Scanned dev system extensions:', result.length);
return result.filter(r => devSystemExtensionsList.some(id => areSameExtensions(r.identifier, { id })));
});
} else {
@@ -776,7 +780,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
const byExtension: ILocalExtension[][] = groupByExtension(extensions, e => e.identifier);
extensions = byExtension.map(p => p.sort((a, b) => semver.rcompare(a.manifest.version, b.manifest.version))[0]);
}
this.logService.info('Scanned user extensions:', extensions.length);
this.logService.trace('Scanned user extensions:', extensions.length);
return extensions;
});
}
@@ -800,25 +804,44 @@ export class ExtensionManagementService extends Disposable implements IExtension
const readmeUrl = readme ? URI.file(path.join(extensionPath, readme)) : null;
const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0];
const changelogUrl = changelog ? URI.file(path.join(extensionPath, changelog)) : null;
const identifier = { id: getGalleryExtensionId(manifest.publisher, manifest.name), uuid: metadata ? metadata.id : null };
return <ILocalExtension>{ type, identifier, manifest, metadata, location: URI.file(extensionPath), readmeUrl, changelogUrl };
const identifier = { id: getGalleryExtensionId(manifest.publisher, manifest.name) };
const local = <ILocalExtension>{ type, identifier, manifest, metadata, location: URI.file(extensionPath), readmeUrl, changelogUrl };
if (metadata) {
this.setMetadata(local, metadata);
}
return local;
}))
.then(undefined, () => null);
}
removeDeprecatedExtensions(): Promise<any> {
return this.removeUninstalledExtensions()
.then(() => this.removeOutdatedExtensions());
private setMetadata(local: ILocalExtension, metadata: IGalleryMetadata): void {
local.metadata = metadata;
local.identifier.uuid = metadata.id;
}
private removeUninstalledExtensions(): Promise<void> {
return this.getUninstalledExtensions()
.then(uninstalled => this.scanExtensions(this.extensionsPath, ExtensionType.User) // All user extensions
.then(extensions => {
const toRemove: ILocalExtension[] = extensions.filter(e => uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]);
return Promise.all(toRemove.map(e => this.extensionLifecycle.postUninstall(e).then(() => this.removeUninstalledExtension(e))));
})
).then(() => undefined);
async removeDeprecatedExtensions(): Promise<void> {
await this.removeUninstalledExtensions();
await this.removeOutdatedExtensions();
}
private async removeUninstalledExtensions(): Promise<void> {
const uninstalled = await this.getUninstalledExtensions();
const extensions = await this.scanExtensions(this.extensionsPath, ExtensionType.User); // All user extensions
const installed: Set<string> = new Set<string>();
for (const e of extensions) {
if (!uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]) {
installed.add(e.identifier.id.toLowerCase());
}
}
const byExtension: ILocalExtension[][] = groupByExtension(extensions, e => e.identifier);
await Promise.all(byExtension.map(async e => {
const latest = e.sort((a, b) => semver.rcompare(a.manifest.version, b.manifest.version))[0];
if (!installed.has(latest.identifier.id.toLowerCase())) {
await this.extensionLifecycle.postUninstall(latest);
}
}));
const toRemove: ILocalExtension[] = extensions.filter(e => uninstalled[new ExtensionIdentifierWithVersion(e.identifier, e.manifest.version).key()]);
await Promise.all(toRemove.map(e => this.removeUninstalledExtension(e)));
}
private removeOutdatedExtensions(): Promise<void> {
@@ -845,8 +868,8 @@ export class ExtensionManagementService extends Disposable implements IExtension
return pfs.rimraf(extension.location.fsPath).then(() => this.logService.info('Deleted from disk', extension.identifier.id, extension.location.fsPath));
}
private isUninstalled(identfier: ExtensionIdentifierWithVersion): Promise<boolean> {
return this.filterUninstalled(identfier).then(uninstalled => uninstalled.length === 1);
private isUninstalled(identifier: ExtensionIdentifierWithVersion): Promise<boolean> {
return this.filterUninstalled(identifier).then(uninstalled => uninstalled.length === 1);
}
private filterUninstalled(...identifiers: ExtensionIdentifierWithVersion[]): Promise<string[]> {