Update VS Code to 1.41.0
This commit is contained in:
@ -1,23 +1,26 @@
|
||||
import * as path from "path";
|
||||
import { VSBuffer } from "vs/base/common/buffer";
|
||||
import { VSBuffer, VSBufferReadableStream } from "vs/base/common/buffer";
|
||||
import { Emitter, Event } from "vs/base/common/event";
|
||||
import { IDisposable } from "vs/base/common/lifecycle";
|
||||
import { OS } from "vs/base/common/platform";
|
||||
import { ReadableStreamEventPayload } from "vs/base/common/stream";
|
||||
import { URI, UriComponents } from "vs/base/common/uri";
|
||||
import { transformOutgoingURIs } from "vs/base/common/uriIpc";
|
||||
import { IServerChannel } from "vs/base/parts/ipc/common/ipc";
|
||||
import { IDiagnosticInfo } from "vs/platform/diagnostics/common/diagnostics";
|
||||
import { IEnvironmentService } from "vs/platform/environment/common/environment";
|
||||
import { ExtensionIdentifier, IExtensionDescription } from "vs/platform/extensions/common/extensions";
|
||||
import { FileDeleteOptions, FileOpenOptions, FileOverwriteOptions, FileType, IStat, IWatchOptions } from "vs/platform/files/common/files";
|
||||
import { FileDeleteOptions, FileOpenOptions, FileOverwriteOptions, FileReadStreamOptions, FileType, FileWriteOptions, IStat, IWatchOptions } from "vs/platform/files/common/files";
|
||||
import { createReadStream } from "vs/platform/files/common/io";
|
||||
import { DiskFileSystemProvider } from "vs/platform/files/node/diskFileSystemProvider";
|
||||
import { ILogService } from "vs/platform/log/common/log";
|
||||
import product from "vs/platform/product/common/product";
|
||||
import { IRemoteAgentEnvironment } from "vs/platform/remote/common/remoteAgentEnvironment";
|
||||
import { IRemoteAgentEnvironment, RemoteAgentConnectionContext } from "vs/platform/remote/common/remoteAgentEnvironment";
|
||||
import { ITelemetryService } from "vs/platform/telemetry/common/telemetry";
|
||||
import { INodeProxyService } from "vs/server/src/common/nodeProxy";
|
||||
import { getTranslations } from "vs/server/src/node/nls";
|
||||
import { getUriTransformer, localRequire } from "vs/server/src/node/util";
|
||||
import { IFileChangeDto } from "vs/workbench/api/common/extHost.protocol";
|
||||
import { ExtensionScanner, ExtensionScannerInput } from "vs/workbench/services/extensions/node/extensionPoints";
|
||||
|
||||
/**
|
||||
@ -42,7 +45,7 @@ class Watcher extends DiskFileSystemProvider {
|
||||
}
|
||||
}
|
||||
|
||||
export class FileProviderChannel implements IServerChannel, IDisposable {
|
||||
export class FileProviderChannel implements IServerChannel<RemoteAgentConnectionContext>, IDisposable {
|
||||
private readonly provider: DiskFileSystemProvider;
|
||||
private readonly watchers = new Map<string, Watcher>();
|
||||
|
||||
@ -53,48 +56,67 @@ export class FileProviderChannel implements IServerChannel, IDisposable {
|
||||
this.provider = new DiskFileSystemProvider(this.logService);
|
||||
}
|
||||
|
||||
public listen(context: any, event: string, args?: any): Event<any> {
|
||||
public listen(context: RemoteAgentConnectionContext, event: string, args?: any): Event<any> {
|
||||
switch (event) {
|
||||
// This is where the actual file changes are sent. The watch method just
|
||||
// adds things that will fire here. That means we have to split up
|
||||
// watchers based on the session otherwise sessions would get events for
|
||||
// other sessions. There is also no point in having the watcher unless
|
||||
// something is listening. I'm not sure there is a different way to
|
||||
// dispose, anyway.
|
||||
case "filechange":
|
||||
const session = args[0];
|
||||
const emitter = new Emitter({
|
||||
onFirstListenerAdd: () => {
|
||||
const provider = new Watcher(this.logService);
|
||||
this.watchers.set(session, provider);
|
||||
const transformer = getUriTransformer(context.remoteAuthority);
|
||||
provider.onDidChangeFile((events) => {
|
||||
emitter.fire(events.map((event) => ({
|
||||
...event,
|
||||
resource: transformer.transformOutgoing(event.resource),
|
||||
})));
|
||||
});
|
||||
provider.onDidErrorOccur((event) => emitter.fire(event));
|
||||
},
|
||||
onLastListenerRemove: () => {
|
||||
this.watchers.get(session)!.dispose();
|
||||
this.watchers.delete(session);
|
||||
},
|
||||
});
|
||||
|
||||
return emitter.event;
|
||||
case "filechange": return this.filechange(context, args[0]);
|
||||
case "readFileStream": return this.readFileStream(args[0], args[1]);
|
||||
}
|
||||
|
||||
throw new Error(`Invalid listen "${event}"`);
|
||||
}
|
||||
|
||||
private filechange(context: RemoteAgentConnectionContext, session: string): Event<IFileChangeDto[]> {
|
||||
const emitter = new Emitter<IFileChangeDto[]>({
|
||||
onFirstListenerAdd: () => {
|
||||
const provider = new Watcher(this.logService);
|
||||
this.watchers.set(session, provider);
|
||||
const transformer = getUriTransformer(context.remoteAuthority);
|
||||
provider.onDidChangeFile((events) => {
|
||||
emitter.fire(events.map((event) => ({
|
||||
...event,
|
||||
resource: transformer.transformOutgoing(event.resource),
|
||||
})));
|
||||
});
|
||||
provider.onDidErrorOccur((event) => this.logService.error(event));
|
||||
},
|
||||
onLastListenerRemove: () => {
|
||||
this.watchers.get(session)!.dispose();
|
||||
this.watchers.delete(session);
|
||||
},
|
||||
});
|
||||
|
||||
return emitter.event;
|
||||
}
|
||||
|
||||
private readFileStream(resource: UriComponents, opts: FileReadStreamOptions): Event<ReadableStreamEventPayload<VSBuffer>> {
|
||||
let fileStream: VSBufferReadableStream | undefined;
|
||||
const emitter = new Emitter<ReadableStreamEventPayload<VSBuffer>>({
|
||||
onFirstListenerAdd: () => {
|
||||
if (!fileStream) {
|
||||
fileStream = createReadStream(this.provider, this.transform(resource), {
|
||||
...opts,
|
||||
bufferSize: 64 * 1024, // From DiskFileSystemProvider
|
||||
});
|
||||
fileStream.on("data", (data) => emitter.fire(data));
|
||||
fileStream.on("error", (error) => emitter.fire(error));
|
||||
fileStream.on("end", () => emitter.fire("end"));
|
||||
}
|
||||
},
|
||||
onLastListenerRemove: () => fileStream && fileStream.destroy(),
|
||||
});
|
||||
|
||||
return emitter.event;
|
||||
}
|
||||
|
||||
public call(_: unknown, command: string, args?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case "stat": return this.stat(args[0]);
|
||||
case "open": return this.open(args[0], args[1]);
|
||||
case "close": return this.close(args[0]);
|
||||
case "read": return this.read(args[0], args[1], args[2]);
|
||||
case "readFile": return this.readFile(args[0]);
|
||||
case "write": return this.write(args[0], args[1], args[2], args[3], args[4]);
|
||||
case "writeFile": return this.writeFile(args[0], args[1], args[2]);
|
||||
case "delete": return this.delete(args[0], args[1]);
|
||||
case "mkdir": return this.mkdir(args[0]);
|
||||
case "readdir": return this.readdir(args[0]);
|
||||
@ -130,10 +152,18 @@ export class FileProviderChannel implements IServerChannel, IDisposable {
|
||||
return [buffer, bytesRead];
|
||||
}
|
||||
|
||||
private async readFile(resource: UriComponents): Promise<VSBuffer> {
|
||||
return VSBuffer.wrap(await this.provider.readFile(this.transform(resource)));
|
||||
}
|
||||
|
||||
private write(fd: number, pos: number, buffer: VSBuffer, offset: number, length: number): Promise<number> {
|
||||
return this.provider.write(fd, pos, buffer.buffer, offset, length);
|
||||
}
|
||||
|
||||
private writeFile(resource: UriComponents, buffer: VSBuffer, opts: FileWriteOptions): Promise<void> {
|
||||
return this.provider.writeFile(this.transform(resource), buffer.buffer, opts);
|
||||
}
|
||||
|
||||
private async delete(resource: UriComponents, opts: FileDeleteOptions): Promise<void> {
|
||||
return this.provider.delete(this.transform(resource), opts);
|
||||
}
|
||||
|
@ -3,14 +3,81 @@ import * as https from "https";
|
||||
import * as http from "http";
|
||||
import * as os from "os";
|
||||
|
||||
export class TelemetryClient implements appInsights.TelemetryClient {
|
||||
class Channel {
|
||||
public get _sender() {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
public get _buffer() {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public setUseDiskRetryCaching(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
public send(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
public triggerSend(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
}
|
||||
|
||||
export class TelemetryClient {
|
||||
public context: any = undefined;
|
||||
public commonProperties: any = undefined;
|
||||
public config: any = {};
|
||||
|
||||
public channel = {
|
||||
setUseDiskRetryCaching: (): void => undefined,
|
||||
};
|
||||
public channel: any = new Channel();
|
||||
|
||||
public trackEvent(options: appInsights.EventTelemetry): void {
|
||||
public addTelemetryProcessor(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public clearTelemetryProcessors(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public runTelemetryProcessors(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public trackTrace(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public trackMetric(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public trackException(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public trackRequest(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public trackDependency(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public track(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public trackNodeHttpRequestSync(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public trackNodeHttpRequest(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public trackNodeHttpDependency(): void {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
public trackEvent(options: appInsights.Contracts.EventTelemetry): void {
|
||||
if (!options.properties) {
|
||||
options.properties = {};
|
||||
}
|
||||
@ -43,13 +110,13 @@ export class TelemetryClient implements appInsights.TelemetryClient {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
request.on("error", () => { /* We don't care. */ });
|
||||
request.on("error", () => { /* We don"t care. */ });
|
||||
request.write(JSON.stringify(options));
|
||||
request.end();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
public flush(options: appInsights.FlushOptions): void {
|
||||
public flush(options: { callback: (v: string) => void }): void {
|
||||
if (options.callback) {
|
||||
options.callback("");
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ const extractTar = async (tarPath: string, targetPath: string, options: IExtract
|
||||
return fail(new Error(nls.localize("invalid file", "Error extracting {0}. Invalid file.", fileName)));
|
||||
}
|
||||
|
||||
await mkdirp(targetDirName, undefined, token);
|
||||
await mkdirp(targetDirName, undefined);
|
||||
|
||||
const fstream = fs.createWriteStream(targetFileName, { mode: header.mode });
|
||||
fstream.once("close", () => next());
|
||||
|
@ -17,7 +17,7 @@ import { generateUuid } from "vs/base/common/uuid";
|
||||
import { getMachineId } from 'vs/base/node/id';
|
||||
import { NLSConfiguration } from "vs/base/node/languagePacks";
|
||||
import { mkdirp, rimraf } from "vs/base/node/pfs";
|
||||
import { ClientConnectionEvent, IPCServer } from "vs/base/parts/ipc/common/ipc";
|
||||
import { ClientConnectionEvent, IPCServer, IServerChannel } from "vs/base/parts/ipc/common/ipc";
|
||||
import { createChannelReceiver } from "vs/base/parts/ipc/node/ipc";
|
||||
import { LogsDataCleaner } from "vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner";
|
||||
import { IConfigurationService } from "vs/platform/configuration/common/configuration";
|
||||
@ -43,6 +43,7 @@ import { SpdLogService } from "vs/platform/log/node/spdlogService";
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from "vs/platform/product/common/productService";
|
||||
import { ConnectionType, ConnectionTypeRequest } from "vs/platform/remote/common/remoteAgentConnection";
|
||||
import { RemoteAgentConnectionContext } from "vs/platform/remote/common/remoteAgentEnvironment";
|
||||
import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from "vs/platform/remote/common/remoteAgentFileSystemChannel";
|
||||
import { IRequestService } from "vs/platform/request/common/request";
|
||||
import { RequestChannel } from "vs/platform/request/common/requestIpc";
|
||||
@ -295,13 +296,6 @@ export abstract class Server {
|
||||
|
||||
switch (base) {
|
||||
case "/":
|
||||
switch (requestPath) {
|
||||
case "/favicon.ico":
|
||||
case "/manifest.json":
|
||||
const response = await this.getResource(this.serverRoot, "media", requestPath);
|
||||
response.cache = true;
|
||||
return response;
|
||||
}
|
||||
if (!this.authenticate(request)) {
|
||||
return { redirect: "/login" };
|
||||
}
|
||||
@ -485,7 +479,7 @@ interface Settings {
|
||||
export class MainServer extends Server {
|
||||
public readonly _onDidClientConnect = new Emitter<ClientConnectionEvent>();
|
||||
public readonly onDidClientConnect = this._onDidClientConnect.event;
|
||||
private readonly ipc = new IPCServer(this.onDidClientConnect);
|
||||
private readonly ipc = new IPCServer<RemoteAgentConnectionContext>(this.onDidClientConnect);
|
||||
|
||||
private readonly maxExtraOfflineConnections = 0;
|
||||
private readonly connections = new Map<ConnectionType, Map<string, Connection>>();
|
||||
@ -750,7 +744,7 @@ export class MainServer extends Server {
|
||||
if (!environmentService.args["disable-telemetry"]) {
|
||||
this.services.set(ITelemetryService, new SyncDescriptor(TelemetryService, [{
|
||||
appender: combinedAppender(
|
||||
new AppInsightsAppender("code-server", null, () => new TelemetryClient(), logService),
|
||||
new AppInsightsAppender("code-server", null, () => new TelemetryClient() as any, logService),
|
||||
new LogAppender(logService),
|
||||
),
|
||||
commonProperties: resolveCommonProperties(
|
||||
@ -781,7 +775,7 @@ export class MainServer extends Server {
|
||||
this.ipc.registerChannel("request", new RequestChannel(this.services.get(IRequestService) as IRequestService));
|
||||
this.ipc.registerChannel("telemetry", new TelemetryChannel(telemetryService));
|
||||
this.ipc.registerChannel("nodeProxy", new NodeProxyChannel(this.services.get(INodeProxyService) as INodeProxyService));
|
||||
this.ipc.registerChannel("localizations", createChannelReceiver(this.services.get(ILocalizationsService) as ILocalizationsService));
|
||||
this.ipc.registerChannel("localizations", <IServerChannel<any>>createChannelReceiver(this.services.get(ILocalizationsService) as ILocalizationsService));
|
||||
this.ipc.registerChannel("update", new UpdateChannel(instantiationService.createInstance(UpdateService)));
|
||||
this.ipc.registerChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME, new FileProviderChannel(environmentService, logService));
|
||||
resolve(new ErrorTelemetry(telemetryService));
|
||||
|
@ -1,9 +1,7 @@
|
||||
import * as cp from "child_process";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
import { Stream } from "stream";
|
||||
import * as util from "util";
|
||||
import { toVSBufferReadableStream } from "vs/base/common/buffer";
|
||||
import { CancellationToken } from "vs/base/common/cancellation";
|
||||
import { URI } from "vs/base/common/uri";
|
||||
import * as pfs from "vs/base/node/pfs";
|
||||
@ -18,7 +16,6 @@ import { AbstractUpdateService } from "vs/platform/update/electron-main/abstract
|
||||
import { ipcMain } from "vs/server/src/node/ipc";
|
||||
import { extract } from "vs/server/src/node/marketplace";
|
||||
import { tmpdir } from "vs/server/src/node/util";
|
||||
import * as zlib from "zlib";
|
||||
|
||||
interface IUpdate {
|
||||
name: string;
|
||||
@ -103,15 +100,7 @@ export class UpdateService extends AbstractUpdateService {
|
||||
const extractPath = path.join(tmpdir, state.update.version);
|
||||
try {
|
||||
await pfs.mkdirp(tmpdir);
|
||||
const context = await this.requestService.request({ url }, CancellationToken.None);
|
||||
// Decompress the gzip as we download. If the gzip encoding is set then
|
||||
// the request service already does this.
|
||||
// HACK: This uses knowledge of the internals of the request service.
|
||||
if (target !== "darwin" && context.res.headers["content-encoding"] !== "gzip") {
|
||||
const stream = (context.res as any as Stream);
|
||||
stream.removeAllListeners();
|
||||
context.stream = toVSBufferReadableStream(stream.pipe(zlib.createGunzip()));
|
||||
}
|
||||
const context = await this.requestService.request({ url }, CancellationToken.None, true);
|
||||
await this.fileService.writeFile(URI.file(downloadPath), context.stream);
|
||||
await extract(downloadPath, extractPath, undefined, CancellationToken.None);
|
||||
const newBinary = path.join(extractPath, releaseName, "code-server");
|
||||
|
Reference in New Issue
Block a user