Merge from vscode e1d3dd53d17fb1529a002e4d6fb066db0a0bd385 (#6460)

* Merge from vscode e1d3dd53d17fb1529a002e4d6fb066db0a0bd385

* fix servers icon

* fix tests
This commit is contained in:
Anthony Dresser
2019-07-22 18:28:21 -07:00
committed by GitHub
parent f2afacd8b2
commit 15fc7a077a
91 changed files with 2562 additions and 972 deletions

View File

@@ -7,6 +7,7 @@ import { IServerChannel, IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IReloadSessionEvent, ICloseSessionEvent, IAttachSessionEvent, ILogToSessionEvent, ITerminateSessionEvent, IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
import { Event, Emitter } from 'vs/base/common/event';
import { IRemoteConsoleLog } from 'vs/base/common/console';
import { Disposable } from 'vs/base/common/lifecycle';
export class ExtensionHostDebugBroadcastChannel<TContext> implements IServerChannel<TContext> {
@@ -51,11 +52,13 @@ export class ExtensionHostDebugBroadcastChannel<TContext> implements IServerChan
}
}
export class ExtensionHostDebugChannelClient implements IExtensionHostDebugService {
export class ExtensionHostDebugChannelClient extends Disposable implements IExtensionHostDebugService {
_serviceBrand: any;
constructor(private channel: IChannel) { }
constructor(private channel: IChannel) {
super();
}
reload(sessionId: string): void {
this.channel.call('reload', [sessionId]);

View File

@@ -13,6 +13,6 @@ export interface IDownloadService {
_serviceBrand: any;
download(uri: URI, to?: string, cancellationToken?: CancellationToken): Promise<string>;
download(uri: URI, to: URI, cancellationToken?: CancellationToken): Promise<void>;
}

View File

@@ -0,0 +1,42 @@
/*---------------------------------------------------------------------------------------------
* 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 { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { Event } from 'vs/base/common/event';
import { IDownloadService } from 'vs/platform/download/common/download';
import { IURITransformer } from 'vs/base/common/uriIpc';
export class DownloadServiceChannel implements IServerChannel {
constructor(private readonly service: IDownloadService) { }
listen(_: unknown, event: string, arg?: any): Event<any> {
throw new Error('Invalid listen');
}
call(context: any, command: string, args?: any): Promise<any> {
switch (command) {
case 'download': return this.service.download(URI.revive(args[0]), URI.revive(args[1]));
}
throw new Error('Invalid call');
}
}
export class DownloadServiceChannelClient implements IDownloadService {
_serviceBrand: any;
constructor(private channel: IChannel, private getUriTransformer: () => IURITransformer | null) { }
async download(from: URI, to: URI): Promise<void> {
const uriTransfomer = this.getUriTransformer();
if (uriTransfomer) {
from = uriTransfomer.transformOutgoingURI(from);
to = uriTransfomer.transformOutgoingURI(to);
}
await this.channel.call('download', [from, to]);
}
}

View File

@@ -5,14 +5,10 @@
import { IDownloadService } from 'vs/platform/download/common/download';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { copy } from 'vs/base/node/pfs';
import { IRequestService, asText } from 'vs/platform/request/common/request';
import { CancellationToken } from 'vs/base/common/cancellation';
import { join } from 'vs/base/common/path';
import { tmpdir } from 'os';
import { generateUuid } from 'vs/base/common/uuid';
import { IFileService } from 'vs/platform/files/common/files';
import { Schemas } from 'vs/base/common/network';
export class DownloadService implements IDownloadService {
@@ -23,18 +19,18 @@ export class DownloadService implements IDownloadService {
@IFileService private readonly fileService: IFileService
) { }
download(uri: URI, target: string = join(tmpdir(), generateUuid()), cancellationToken: CancellationToken = CancellationToken.None): Promise<string> {
if (uri.scheme === Schemas.file) {
return copy(uri.fsPath, target).then(() => target);
async download(resource: URI, target: URI, cancellationToken: CancellationToken = CancellationToken.None): Promise<void> {
if (resource.scheme === Schemas.file) {
await this.fileService.copy(resource, target);
return;
}
const options = { type: 'GET', url: resource.toString() };
const context = await this.requestService.request(options, cancellationToken);
if (context.res.statusCode === 200) {
await this.fileService.writeFile(target, context.stream);
} else {
const message = await asText(context);
return Promise.reject(new Error(`Expected 200, got back ${context.res.statusCode} instead.\n\n${message}`));
}
const options = { type: 'GET', url: uri.toString() };
return this.requestService.request(options, cancellationToken)
.then(context => {
if (context.res.statusCode === 200) {
return this.fileService.writeFile(URI.file(target), context.stream).then(() => target);
}
return asText(context)
.then(message => Promise.reject(new Error(`Expected 200, got back ${context.res.statusCode} instead.\n\n${message}`)));
});
}
}

View File

@@ -1,76 +0,0 @@
/*---------------------------------------------------------------------------------------------
* 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 * as path from 'vs/base/common/path';
import * as fs from 'fs';
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc';
import { Event, Emitter } from 'vs/base/common/event';
import { IDownloadService } from 'vs/platform/download/common/download';
import { mkdirp } from 'vs/base/node/pfs';
import { IURITransformer } from 'vs/base/common/uriIpc';
import { tmpdir } from 'os';
import { generateUuid } from 'vs/base/common/uuid';
type UploadResponse = Buffer | string | undefined;
function upload(uri: URI): Event<UploadResponse> {
const stream = new Emitter<UploadResponse>();
const readstream = fs.createReadStream(uri.fsPath);
readstream.on('data', data => stream.fire(data));
readstream.on('error', error => stream.fire(error.toString()));
readstream.on('close', () => stream.fire(undefined));
return stream.event;
}
export class DownloadServiceChannel implements IServerChannel {
constructor() { }
listen(_: unknown, event: string, arg?: any): Event<any> {
switch (event) {
case 'upload': return Event.buffer(upload(URI.revive(arg)));
}
throw new Error(`Event not found: ${event}`);
}
call(_: unknown, command: string): Promise<any> {
throw new Error(`Call not found: ${command}`);
}
}
export class DownloadServiceChannelClient implements IDownloadService {
_serviceBrand: any;
constructor(private channel: IChannel, private getUriTransformer: () => IURITransformer) { }
download(from: URI, to: string = path.join(tmpdir(), generateUuid())): Promise<string> {
from = this.getUriTransformer().transformOutgoingURI(from);
const dirName = path.dirname(to);
let out: fs.WriteStream;
return new Promise<string>((c, e) => {
return mkdirp(dirName)
.then(() => {
out = fs.createWriteStream(to);
out.once('close', () => c(to));
out.once('error', e);
const uploadStream = this.channel.listen<UploadResponse>('upload', from);
const disposable = uploadStream(result => {
if (result === undefined) {
disposable.dispose();
out.end(() => c(to));
} else if (Buffer.isBuffer(result)) {
out.write(result);
} else if (typeof result === 'string') {
disposable.dispose();
out.end(() => e(result));
}
});
});
});
}
}

View File

@@ -26,6 +26,7 @@ import { URI } from 'vs/base/common/uri';
import { joinPath } from 'vs/base/common/resources';
import { VSBuffer } from 'vs/base/common/buffer';
import { IProductService } from 'vs/platform/product/common/product';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
interface IRawGalleryExtensionFile {
assetType: string;
@@ -388,11 +389,12 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
@IConfigurationService private configurationService: IConfigurationService,
@IFileService private readonly fileService: IFileService,
@IProductService private readonly productService: IProductService,
@IStorageService private readonly storageService: IStorageService,
) {
const config = productService.extensionsGallery;
this.extensionsGalleryUrl = config && config.serviceUrl;
this.extensionsControlUrl = config && config.controlUrl;
this.commonHeadersPromise = resolveMarketplaceHeaders(productService.version, this.environmentService, this.fileService);
this.commonHeadersPromise = resolveMarketplaceHeaders(productService.version, this.environmentService, this.fileService, this.storageService);
}
private api(path = ''): string {
@@ -944,7 +946,7 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
}
}
export async function resolveMarketplaceHeaders(version: string, environmentService: IEnvironmentService, fileService: IFileService): Promise<{ [key: string]: string; }> {
export async function resolveMarketplaceHeaders(version: string, environmentService: IEnvironmentService, fileService: IFileService, storageService?: IStorageService): Promise<{ [key: string]: string; }> {
const headers: IHeaders = {
'X-Market-Client-Id': `VSCode ${version}`,
'User-Agent': `VSCode ${version}`
@@ -967,8 +969,20 @@ export async function resolveMarketplaceHeaders(version: string, environmentServ
//noop
}
}
}
if (storageService) {
uuid = storageService.get('marketplace.userid', StorageScope.GLOBAL) || null;
if (!uuid) {
uuid = generateUuid();
storageService.store('marketplace.userid', uuid, StorageScope.GLOBAL);
}
}
if (uuid) {
headers['X-Market-User-Id'] = uuid;
}
return headers;
}

View File

@@ -261,7 +261,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
throw new Error('Download service is not available');
}
const downloadedLocation = path.join(tmpdir(), generateUuid());
return this.downloadService.download(vsix, downloadedLocation).then(() => URI.file(downloadedLocation));
return this.downloadService.download(vsix, URI.file(downloadedLocation)).then(() => URI.file(downloadedLocation));
}
private installFromZipPath(identifierWithVersion: ExtensionIdentifierWithVersion, zipPath: string, metadata: IGalleryMetadata | null, type: ExtensionType, operation: InstallOperation, token: CancellationToken): Promise<ILocalExtension> {

View File

@@ -256,7 +256,7 @@ function sleep(seconds: number): Promise<void> {
});
}
export const enum PersistenConnectionEventType {
export const enum PersistentConnectionEventType {
ConnectionLost,
ReconnectionWait,
ReconnectionRunning,
@@ -264,22 +264,22 @@ export const enum PersistenConnectionEventType {
ConnectionGain
}
export class ConnectionLostEvent {
public readonly type = PersistenConnectionEventType.ConnectionLost;
public readonly type = PersistentConnectionEventType.ConnectionLost;
}
export class ReconnectionWaitEvent {
public readonly type = PersistenConnectionEventType.ReconnectionWait;
public readonly type = PersistentConnectionEventType.ReconnectionWait;
constructor(
public readonly durationSeconds: number
) { }
}
export class ReconnectionRunningEvent {
public readonly type = PersistenConnectionEventType.ReconnectionRunning;
public readonly type = PersistentConnectionEventType.ReconnectionRunning;
}
export class ConnectionGainEvent {
public readonly type = PersistenConnectionEventType.ConnectionGain;
public readonly type = PersistentConnectionEventType.ConnectionGain;
}
export class ReconnectionPermanentFailureEvent {
public readonly type = PersistenConnectionEventType.ReconnectionPermanentFailure;
public readonly type = PersistentConnectionEventType.ReconnectionPermanentFailure;
}
export type PersistenConnectionEvent = ConnectionGainEvent | ConnectionLostEvent | ReconnectionWaitEvent | ReconnectionRunningEvent | ReconnectionPermanentFailureEvent;