Merge from vscode b12f623603e2fc1c5b3037115fa37c1a6acc4165 (#6760)

This commit is contained in:
Anthony Dresser
2019-08-15 02:19:31 -07:00
committed by GitHub
parent 4966ed8b42
commit 58bfba4b47
161 changed files with 2072 additions and 1317 deletions

View File

@@ -79,10 +79,10 @@ export function toExtensionDescription(local: ILocalExtension): IExtensionDescri
const promptDownloadManually = (extension: IGalleryExtension | undefined, message: string, error: Error,
instantiationService: IInstantiationService, notificationService: INotificationService, openerService: IOpenerService, productService: IProductService) => {
if (!extension || error.name === INSTALL_ERROR_INCOMPATIBLE || error.name === INSTALL_ERROR_MALICIOUS || !productService.extensionsGallery) {
if (!extension || error.name === INSTALL_ERROR_INCOMPATIBLE || error.name === INSTALL_ERROR_MALICIOUS || !productService.productConfiguration.extensionsGallery) {
return Promise.reject(error);
} else {
const downloadUrl = `${productService.extensionsGallery.serviceUrl}/publishers/${extension.publisher}/vsextensions/${extension.name}/${extension.version}/vspackage`;
const downloadUrl = `${productService.productConfiguration.extensionsGallery.serviceUrl}/publishers/${extension.publisher}/vsextensions/${extension.name}/${extension.version}/vspackage`;
notificationService.prompt(Severity.Error, message, [{
label: localize('download', "Download Manually"),
run: () => openerService.open(URI.parse(downloadUrl)).then(() => {

View File

@@ -435,7 +435,7 @@ export class ExtensionsListView extends ViewletPanel {
// {{SQL CARBON EDIT}}
if (this.productService) {
let promiseRecommendedExtensionsByScenario: Promise<IPagedModel<IExtension>> | undefined;
Object.keys(this.productService.recommendedExtensionsByScenario).forEach(scenarioType => {
Object.keys(this.productService.productConfiguration.recommendedExtensionsByScenario).forEach(scenarioType => {
let re = new RegExp('@' + scenarioType, 'i');
if (re.test(query.value)) {
promiseRecommendedExtensionsByScenario = this.getRecommendedExtensionsByScenario(token, scenarioType);
@@ -944,7 +944,7 @@ export class ServerExtensionsView extends ExtensionsListView {
@IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionManagementServerService extensionManagementServerService: IExtensionManagementServerService,
@IProductService productService: IProductService,
@IContextKeyService contextKeyService: IContextKeyService,
@IContextKeyService contextKeyService: IContextKeyService
) {
options.server = server;
super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService, extensionManagementServerService, productService, contextKeyService);
@@ -960,7 +960,7 @@ export class ServerExtensionsView extends ExtensionsListView {
}
getActions(): IAction[] {
if (this.extensionManagementServerService.localExtensionManagementServer === this.server) {
if (this.extensionManagementServerService.remoteExtensionManagementServer && this.extensionManagementServerService.localExtensionManagementServer === this.server) {
const installLocalExtensionsInRemoteAction = this._register(this.instantiationService.createInstance(InstallLocalExtensionsInRemoteAction, false));
installLocalExtensionsInRemoteAction.class = 'octicon octicon-cloud-download';
return [installLocalExtensionsInRemoteAction];

View File

@@ -118,20 +118,19 @@ class Extension implements IExtension {
}
get url(): string | undefined {
if (!this.productService.extensionsGallery || !this.gallery) {
if (!this.productService.productConfiguration.extensionsGallery || !this.gallery) {
return undefined;
}
return this.productService.extensionsGallery.itemUrl && `${this.productService.extensionsGallery.itemUrl}?itemName=${this.publisher}.${this.name}`; // {{SQL CARBON EDIT}} add check for itemurl
return `${this.productService.productConfiguration.extensionsGallery.itemUrl}?itemName=${this.publisher}.${this.name}`;
}
// {{SQL CARBON EDIT}}
get downloadPage(): string {
if (!this.productService.extensionsGallery) {
if (!this.productService.productConfiguration.extensionsGallery) {
return null;
}
// {{SQL CARBON EDIT}}
return this.gallery && this.gallery.assets && this.gallery.assets.downloadPage && this.gallery.assets.downloadPage.uri;
}
@@ -632,7 +631,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
text = text.replace(extensionRegex, (m, ext) => {
// Get curated keywords
const lookup = this.productService.extensionKeywords || {};
const lookup = this.productService.productConfiguration.extensionKeywords || {};
const keywords = lookup[ext] || [];
// Get mode name
@@ -832,9 +831,9 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
// This is the execution path for install/update extension from marketplace.
// Check both the vscode version and azure data studio version
// The check is added here because we want to fail fast instead of downloading the VSIX and then fail.
if (gallery.properties.engine && (!isEngineValid(gallery.properties.engine, this.productService.vscodeVersion)
|| (gallery.properties.azDataEngine && !isEngineValid(gallery.properties.azDataEngine, this.productService.version)))) {
return Promise.reject(new Error(nls.localize('incompatible2', "Unable to install version '{2}' of extension '{0}' as it is not compatible with Azure Data Studio '{1}'.", extension.gallery!.identifier.id, this.productService.version, gallery.version)));
if (gallery.properties.engine && (!isEngineValid(gallery.properties.engine, this.productService.productConfiguration.vscodeVersion)
|| (gallery.properties.azDataEngine && !isEngineValid(gallery.properties.azDataEngine, this.productService.productConfiguration.version)))) {
return Promise.reject(new Error(nls.localize('incompatible2', "Unable to install version '{2}' of extension '{0}' as it is not compatible with Azure Data Studio '{1}'.", extension.gallery!.identifier.id, this.productService.productConfiguration.version, gallery.version)));
}
return this.installWithProgress(async () => {
@@ -1077,7 +1076,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
get allowedBadgeProviders(): string[] {
if (!this._extensionAllowedBadgeProviders) {
this._extensionAllowedBadgeProviders = (this.productService.extensionAllowedBadgeProviders || []).map(s => s.toLowerCase());
this._extensionAllowedBadgeProviders = (this.productService.productConfiguration.extensionAllowedBadgeProviders || []).map(s => s.toLowerCase());
}
return this._extensionAllowedBadgeProviders;
}

View File

@@ -14,7 +14,6 @@ import { IExtensionTipsService, ExtensionRecommendationReason, IExtensionsConfig
import { IModelService } from 'vs/editor/common/services/modelService';
import { ITextModel } from 'vs/editor/common/model';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import product from 'vs/platform/product/node/product';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
// {{SQL CARBON EDIT}}
import { ShowRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction, InstallRecommendedExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
@@ -28,13 +27,11 @@ import { IFileService } from 'vs/platform/files/common/files';
import { IExtensionsConfiguration, ConfigurationKey, ShowRecommendationsOnlyOnDemandKey, IExtensionsViewlet, IExtensionsWorkbenchService, EXTENSIONS_CONFIG, ExtensionsPolicyKey, ExtensionsPolicy } from 'vs/workbench/contrib/extensions/common/extensions';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import * as pfs from 'vs/base/node/pfs';
import * as os from 'os';
import { flatten, distinct, shuffle, coalesce } from 'vs/base/common/arrays';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { guessMimeTypes, MIME_UNKNOWN } from 'vs/base/common/mime';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { getHashedRemotesFromUri } from 'vs/workbench/contrib/stats/electron-browser/workspaceStats';
import { IRequestService, asJson } from 'vs/platform/request/common/request';
import { isNumber } from 'vs/base/common/types';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
@@ -47,11 +44,11 @@ import { IExperimentService, ExperimentActionType, ExperimentState } from 'vs/wo
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { extname } from 'vs/base/common/resources';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IExeBasedExtensionTip } from 'vs/platform/product/common/product';
import { IExeBasedExtensionTip, IProductService } from 'vs/platform/product/common/product';
import { timeout } from 'vs/base/common/async';
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry'; // {{SQL CARBON EDIT}}
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys'; // {{SQL CARBON EDIT}}
import { IWorkspaceStatsService } from 'vs/workbench/contrib/stats/common/workspaceStats';
const milliSecondsInADay = 1000 * 60 * 60 * 24;
const choiceNever = localize('neverShowAgain', "Don't Show Again");
@@ -117,8 +114,9 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@IExtensionsWorkbenchService private readonly extensionWorkbenchService: IExtensionsWorkbenchService,
@IExperimentService private readonly experimentService: IExperimentService,
@ITextFileService private readonly textFileService: ITextFileService,
@IAdsTelemetryService private readonly adsTelemetryService: IAdsTelemetryService
@IAdsTelemetryService private readonly adsTelemetryService: IAdsTelemetryService, // {{SQL CARBON EDIT}}
@IWorkspaceStatsService private readonly workspaceStatsService: IWorkspaceStatsService,
@IProductService private readonly productService: IProductService
) {
super();
@@ -128,8 +126,8 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
return;
}
if (product.extensionsGallery && product.extensionsGallery.recommendationsUrl) {
this._extensionsRecommendationsUrl = product.extensionsGallery.recommendationsUrl;
if (this.productService.productConfiguration.extensionsGallery && this.productService.productConfiguration.extensionsGallery.recommendationsUrl) {
this._extensionsRecommendationsUrl = this.productService.productConfiguration.extensionsGallery.recommendationsUrl;
}
this.sessionSeed = +new Date();
@@ -258,7 +256,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
}
getKeymapRecommendations(): IExtensionRecommendation[] {
return (product.keymapExtensionTips || [])
return (this.productService.productConfiguration.keymapExtensionTips || [])
.filter(extensionId => this.isExtensionAllowedToBeRecommended(extensionId))
.map(extensionId => (<IExtensionRecommendation>{ extensionId, sources: ['application'] }));
}
@@ -615,10 +613,10 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
return Object.keys(this._fileBasedRecommendations)
.sort((a, b) => {
if (this._fileBasedRecommendations[a].recommendedTime === this._fileBasedRecommendations[b].recommendedTime) {
if (!product.extensionImportantTips || caseInsensitiveGet(product.extensionImportantTips, a)) {
if (!this.productService.productConfiguration.extensionImportantTips || caseInsensitiveGet(this.productService.productConfiguration.extensionImportantTips, a)) {
return -1;
}
if (caseInsensitiveGet(product.extensionImportantTips, b)) {
if (caseInsensitiveGet(this.productService.productConfiguration.extensionImportantTips, b)) {
return 1;
}
}
@@ -629,13 +627,13 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
}
/**
* Parse all file based recommendations from product.extensionTips
* Retire existing recommendations if they are older than a week or are not part of product.extensionTips anymore
* Parse all file based recommendations from this.productService.productConfiguration.extensionTips
* Retire existing recommendations if they are older than a week or are not part of this.productService.productConfiguration.extensionTips anymore
*/
private fetchFileBasedRecommendations() {
const extensionTips = product.extensionTips;
const extensionTips = this.productService.productConfiguration.extensionTips;
// {{SQL CARBON EDIT}}
this._recommendations = product.recommendedExtensions;
this._recommendations = this.productService.productConfiguration.recommendedExtensions;
if (!extensionTips) {
return;
}
@@ -652,7 +650,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
}
});
forEach(product.extensionImportantTips, entry => {
forEach(this.productService.productConfiguration.extensionImportantTips, entry => {
let { key: id, value } = entry;
const { pattern } = value;
let ids = this._availableRecommendations[pattern];
@@ -714,7 +712,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
let { key: pattern, value: ids } = entry;
if (match(pattern, model.uri.toString())) {
for (let id of ids) {
if (caseInsensitiveGet(product.extensionImportantTips, id)) {
if (caseInsensitiveGet(this.productService.productConfiguration.extensionImportantTips, id)) {
recommendationsToSuggest.push(id);
}
const filedBasedRecommendation = this._fileBasedRecommendations[id.toLowerCase()] || { recommendedTime: now, sources: [] };
@@ -768,7 +766,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
}
const id = recommendationsToSuggest[0];
const entry = caseInsensitiveGet(product.extensionImportantTips, id);
const entry = caseInsensitiveGet(this.productService.productConfiguration.extensionImportantTips, id);
if (!entry) {
return false;
}
@@ -994,14 +992,14 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
}
/**
* If user has any of the tools listed in product.exeBasedExtensionTips, fetch corresponding recommendations
* If user has any of the tools listed in this.productService.productConfiguration.exeBasedExtensionTips, fetch corresponding recommendations
*/
private fetchExecutableRecommendations(important: boolean): Promise<void> {
const homeDir = os.homedir();
let foundExecutables: Set<string> = new Set<string>();
let findExecutable = (exeName: string, tip: IExeBasedExtensionTip, path: string) => {
return pfs.fileExists(path).then(exists => {
return this.fileService.exists(URI.file(path)).then(exists => {
if (exists && !foundExecutables.has(exeName)) {
foundExecutables.add(exeName);
(tip['recommendations'] || []).forEach(extensionId => {
@@ -1018,7 +1016,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
let promises: Promise<void>[] = [];
// Loop through recommended extensions
forEach(product.exeBasedExtensionTips, entry => {
forEach(this.productService.productConfiguration.exeBasedExtensionTips, entry => {
if (typeof entry.value !== 'object' || !Array.isArray(entry.value['recommendations'])) {
return;
}
@@ -1090,7 +1088,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
const storageKey = 'extensionsAssistant/dynamicWorkspaceRecommendations';
const workspaceUri = this.contextService.getWorkspace().folders[0].uri;
return Promise.all([getHashedRemotesFromUri(workspaceUri, this.fileService, this.textFileService, false), getHashedRemotesFromUri(workspaceUri, this.fileService, this.textFileService, true)]).then(([hashedRemotes1, hashedRemotes2]) => {
return Promise.all([this.workspaceStatsService.getHashedRemotesFromUri(workspaceUri, false), this.workspaceStatsService.getHashedRemotesFromUri(workspaceUri, true)]).then(([hashedRemotes1, hashedRemotes2]) => {
const hashedRemotes = (hashedRemotes1 || []).concat(hashedRemotes2 || []);
if (!hashedRemotes.length) {
return undefined;
@@ -1248,7 +1246,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
return Promise.reject(new Error(localize('scenarioTypeUndefined', 'The scenario type for extension recommendations must be provided.')));
}
return Promise.resolve((product.recommendedExtensionsByScenario[scenarioType] || [])
return Promise.resolve((this.productService.productConfiguration.recommendedExtensionsByScenario[scenarioType] || [])
.filter(extensionId => this.isExtensionAllowedToBeRecommended(extensionId))
.map(extensionId => (<IExtensionRecommendation>{ extensionId, sources: ['application'] })));
}

View File

@@ -52,6 +52,7 @@ import { NullLogService } from 'vs/platform/log/common/log';
import { Schemas } from 'vs/base/common/network';
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
import { IFileService } from 'vs/platform/files/common/files';
import { IProductService } from 'vs/platform/product/common/product';
const mockExtensionGallery: IGalleryExtension[] = [
aGalleryExtension('MockExtension1', {

View File

@@ -35,8 +35,7 @@ import { URLService } from 'vs/platform/url/common/urlService';
import { URI } from 'vs/base/common/uri';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { SinonStub } from 'sinon';
import { IExperimentService, ExperimentState, ExperimentActionType } from 'vs/workbench/contrib/experiments/common/experimentService';
import { ExperimentService } from 'vs/workbench/contrib/experiments/electron-browser/experimentService';
import { IExperimentService, ExperimentState, ExperimentActionType, ExperimentService } from 'vs/workbench/contrib/experiments/common/experimentService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
import { ExtensionIdentifier, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions';