mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Merge from vscode 10492ba146318412cbee8b76a8c630f226914734
This commit is contained in:
@@ -935,8 +935,6 @@ export async function resolveMarketplaceHeaders(version: string, environmentServ
|
||||
'User-Agent': `VSCode ${version}`
|
||||
};
|
||||
const uuid = await getServiceMachineId(environmentService, fileService, storageService);
|
||||
if (uuid) {
|
||||
headers['X-Market-User-Id'] = uuid;
|
||||
}
|
||||
headers['X-Market-User-Id'] = uuid;
|
||||
return headers;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IExtensionManifest, IExtension, ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExeBasedExtensionTip } from 'vs/platform/product/common/productService';
|
||||
|
||||
export const EXTENSION_IDENTIFIER_PATTERN = '^([a-z0-9A-Z][a-z0-9\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\-A-Z]*)$';
|
||||
export const EXTENSION_IDENTIFIER_REGEX = new RegExp(EXTENSION_IDENTIFIER_PATTERN);
|
||||
@@ -225,6 +226,20 @@ export interface IGlobalExtensionEnablementService {
|
||||
|
||||
}
|
||||
|
||||
export type IExecutableBasedExtensionTip = { extensionId: string } & Omit<Omit<IExeBasedExtensionTip, 'recommendations'>, 'important'>;
|
||||
export type IWorkspaceTips = { readonly remoteSet: string[]; readonly recommendations: string[]; };
|
||||
|
||||
export const IExtensionTipsService = createDecorator<IExtensionTipsService>('IExtensionTipsService');
|
||||
export interface IExtensionTipsService {
|
||||
_serviceBrand: undefined;
|
||||
|
||||
getImportantExecutableBasedTips(): Promise<IExecutableBasedExtensionTip[]>;
|
||||
getOtherExecutableBasedTips(): Promise<IExecutableBasedExtensionTip[]>;
|
||||
getAllWorkspacesTips(): Promise<IWorkspaceTips[]>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const ExtensionsLabel = localize('extensions', "Extensions");
|
||||
export const ExtensionsChannelId = 'extensions';
|
||||
export const PreferencesLabel = localize('preferences', "Preferences");
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata, IReportedExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata, IReportedExtension, IExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IURITransformer, DefaultURITransformer, transformAndReviveIncomingURIs } from 'vs/base/common/uriIpc';
|
||||
@@ -130,3 +130,23 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer
|
||||
return Promise.resolve(this.channel.call('getExtensionsReport'));
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtensionTipsChannel implements IServerChannel {
|
||||
|
||||
constructor(private service: IExtensionTipsService) {
|
||||
}
|
||||
|
||||
listen(context: any, event: string): Event<any> {
|
||||
throw new Error('Invalid listen');
|
||||
}
|
||||
|
||||
call(context: any, command: string, args?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'getImportantExecutableBasedTips': return this.service.getImportantExecutableBasedTips();
|
||||
case 'getOtherExecutableBasedTips': return this.service.getOtherExecutableBasedTips();
|
||||
case 'getAllWorkspacesTips': return this.service.getAllWorkspacesTips();
|
||||
}
|
||||
|
||||
throw new Error('Invalid call');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,25 +120,4 @@ export function getMaliciousExtensionsSet(report: IReportedExtension[]): Set<str
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export interface IBuiltInExtension {
|
||||
name: string;
|
||||
version: string;
|
||||
repo: string;
|
||||
forQualities?: ReadonlyArray<string>;
|
||||
metadata: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the built-in extension JSON data and filters it down to the
|
||||
* extensions built into this product quality.
|
||||
*/
|
||||
export function parseBuiltInExtensions(rawJson: string, productQuality: string | undefined) {
|
||||
const parsed: IBuiltInExtension[] = JSON.parse(rawJson);
|
||||
if (!productQuality) {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
return parsed.filter(ext => ext.forQualities?.indexOf?.(productQuality) !== -1);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import { join } from 'vs/base/common/path';
|
||||
import { Limiter } from 'vs/base/common/async';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { INativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { rimraf } from 'vs/base/node/pfs';
|
||||
|
||||
export class ExtensionsLifecycle extends Disposable {
|
||||
@@ -20,7 +20,7 @@ export class ExtensionsLifecycle extends Disposable {
|
||||
private processesLimiter: Limiter<void> = new Limiter(5); // Run max 5 processes in parallel
|
||||
|
||||
constructor(
|
||||
private environmentService: IEnvironmentService,
|
||||
private environmentService: INativeEnvironmentService,
|
||||
private logService: ILogService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -21,9 +21,10 @@ import {
|
||||
INSTALL_ERROR_MALICIOUS,
|
||||
INSTALL_ERROR_INCOMPATIBLE
|
||||
} from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { areSameExtensions, getGalleryExtensionId, groupByExtension, getMaliciousExtensionsSet, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, ExtensionIdentifierWithVersion, parseBuiltInExtensions } 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 { INativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { Limiter, createCancelablePromise, CancelablePromise, Queue } from 'vs/base/common/async';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import * as semver from 'semver-umd';
|
||||
@@ -45,7 +46,6 @@ 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 } from 'vs/platform/extensions/common/extensions';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
|
||||
const ERROR_SCANNING_SYS_EXTENSIONS = 'scanningSystem';
|
||||
const ERROR_SCANNING_USER_EXTENSIONS = 'scanningUser';
|
||||
@@ -128,12 +128,11 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
onDidUninstallExtension: Event<DidUninstallExtensionEvent> = this._onDidUninstallExtension.event;
|
||||
|
||||
constructor(
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IEnvironmentService private readonly environmentService: INativeEnvironmentService,
|
||||
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@optional(IDownloadService) private downloadService: IDownloadService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
) {
|
||||
super();
|
||||
this.systemExtensionsPath = environmentService.builtinExtensionsPath;
|
||||
@@ -772,6 +771,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
// Scan other system extensions during development
|
||||
const devSystemExtensionsPromise = this.getDevSystemExtensionsList()
|
||||
.then(devSystemExtensionsList => {
|
||||
console.log(devSystemExtensionsList);
|
||||
if (devSystemExtensionsList.length) {
|
||||
return this.scanExtensions(this.devSystemExtensionsPath, ExtensionType.System)
|
||||
.then(result => {
|
||||
@@ -963,17 +963,8 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
||||
return this._devSystemExtensionsPath;
|
||||
}
|
||||
|
||||
private _devSystemExtensionsFilePath: string | null = null;
|
||||
private get devSystemExtensionsFilePath(): string {
|
||||
if (!this._devSystemExtensionsFilePath) {
|
||||
this._devSystemExtensionsFilePath = path.normalize(path.join(getPathFromAmdModule(require, ''), '..', 'build', 'builtInExtensions.json'));
|
||||
}
|
||||
return this._devSystemExtensionsFilePath;
|
||||
}
|
||||
|
||||
private getDevSystemExtensionsList(): Promise<string[]> {
|
||||
return pfs.readFile(this.devSystemExtensionsFilePath, 'utf8')
|
||||
.then(data => parseBuiltInExtensions(data, this.productService.quality).map(ext => ext.name));
|
||||
return Promise.resolve(product.builtInExtensions ? product.builtInExtensions.map(e => e.name) : []);
|
||||
}
|
||||
|
||||
private toNonCancellablePromise<T>(promise: Promise<T>): Promise<T> {
|
||||
|
||||
122
src/vs/platform/extensionManagement/node/extensionTipsService.ts
Normal file
122
src/vs/platform/extensionManagement/node/extensionTipsService.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { join, } from 'vs/base/common/path';
|
||||
import { IProductService, IExeBasedExtensionTip } from 'vs/platform/product/common/productService';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { env as processEnv } from 'vs/base/common/process';
|
||||
import { INativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { IExtensionTipsService, IExecutableBasedExtensionTip, IWorkspaceTips } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IStringDictionary, forEach } from 'vs/base/common/collections';
|
||||
import { IRequestService, asJson } from 'vs/platform/request/common/request';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class ExtensionTipsService implements IExtensionTipsService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private readonly allImportantExecutableTips: IStringDictionary<IExeBasedExtensionTip> = {};
|
||||
private readonly allOtherExecutableTips: IStringDictionary<IExeBasedExtensionTip> = {};
|
||||
|
||||
constructor(
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IRequestService private readonly requestService: IRequestService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
) {
|
||||
if (this.productService.exeBasedExtensionTips) {
|
||||
forEach(this.productService.exeBasedExtensionTips, ({ key, value }) => {
|
||||
if (value.important) {
|
||||
this.allImportantExecutableTips[key] = value;
|
||||
} else {
|
||||
this.allOtherExecutableTips[key] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getAllWorkspacesTips(): Promise<IWorkspaceTips[]> {
|
||||
return this.fetchWorkspacesTips();
|
||||
}
|
||||
|
||||
getImportantExecutableBasedTips(): Promise<IExecutableBasedExtensionTip[]> {
|
||||
return this.getValidExecutableBasedExtensionTips(this.allImportantExecutableTips);
|
||||
}
|
||||
|
||||
getOtherExecutableBasedTips(): Promise<IExecutableBasedExtensionTip[]> {
|
||||
return this.getValidExecutableBasedExtensionTips(this.allOtherExecutableTips);
|
||||
}
|
||||
|
||||
private async getValidExecutableBasedExtensionTips(executableTips: IStringDictionary<IExeBasedExtensionTip>): Promise<IExecutableBasedExtensionTip[]> {
|
||||
const result: IExecutableBasedExtensionTip[] = [];
|
||||
|
||||
const checkedExecutables: Map<string, boolean> = new Map<string, boolean>();
|
||||
for (const exeName of Object.keys(executableTips)) {
|
||||
const extensionTip = executableTips[exeName];
|
||||
if (!isNonEmptyArray(extensionTip?.recommendations)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const exePaths: string[] = [];
|
||||
if (isWindows) {
|
||||
if (extensionTip.windowsPath) {
|
||||
exePaths.push(extensionTip.windowsPath.replace('%USERPROFILE%', processEnv['USERPROFILE']!)
|
||||
.replace('%ProgramFiles(x86)%', processEnv['ProgramFiles(x86)']!)
|
||||
.replace('%ProgramFiles%', processEnv['ProgramFiles']!)
|
||||
.replace('%APPDATA%', processEnv['APPDATA']!)
|
||||
.replace('%WINDIR%', processEnv['WINDIR']!));
|
||||
}
|
||||
} else {
|
||||
exePaths.push(join('/usr/local/bin', exeName));
|
||||
exePaths.push(join((this.environmentService as INativeEnvironmentService).userHome.fsPath, exeName));
|
||||
}
|
||||
|
||||
for (const exePath of exePaths) {
|
||||
let exists = checkedExecutables.get(exePath);
|
||||
if (exists === undefined) {
|
||||
exists = await this.fileService.exists(URI.file(exePath));
|
||||
checkedExecutables.set(exePath, exists);
|
||||
}
|
||||
if (exists) {
|
||||
extensionTip.recommendations.forEach(recommendation => result.push({
|
||||
extensionId: recommendation,
|
||||
friendlyName: extensionTip.friendlyName,
|
||||
exeFriendlyName: extensionTip.exeFriendlyName,
|
||||
windowsPath: extensionTip.windowsPath,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async fetchWorkspacesTips(): Promise<IWorkspaceTips[]> {
|
||||
if (!this.productService.extensionsGallery?.recommendationsUrl) {
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const context = await this.requestService.request({ type: 'GET', url: this.productService.extensionsGallery?.recommendationsUrl }, CancellationToken.None);
|
||||
if (context.res.statusCode !== 200) {
|
||||
return [];
|
||||
}
|
||||
const result = await asJson<{ workspaceRecommendations?: IWorkspaceTips[] }>(context);
|
||||
if (!result) {
|
||||
return [];
|
||||
}
|
||||
return result.workspaceRecommendations || [];
|
||||
} catch (error) {
|
||||
this.logService.error(error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { INativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { IExtensionManagementService, DidInstallExtensionEvent, DidUninstallExtensionEvent } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { MANIFEST_CACHE_FOLDER, USER_MANIFEST_CACHE_FILE } from 'vs/platform/extensions/common/extensions';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
@@ -15,7 +15,7 @@ export class ExtensionsManifestCache extends Disposable {
|
||||
private extensionsManifestCache = join(this.environmentService.userDataPath, MANIFEST_CACHE_FOLDER, USER_MANIFEST_CACHE_FILE);
|
||||
|
||||
constructor(
|
||||
private readonly environmentService: IEnvironmentService,
|
||||
private readonly environmentService: INativeEnvironmentService,
|
||||
extensionsManagementService: IExtensionManagementService
|
||||
) {
|
||||
super();
|
||||
|
||||
Reference in New Issue
Block a user