Archived
1
0

Update VS Code to 1.41.0

This commit is contained in:
Asher
2019-12-16 16:52:29 -06:00
parent 44c4722edf
commit e6d1f2a7c8
15 changed files with 337 additions and 350 deletions

View File

@ -21,7 +21,7 @@ import { ITelemetryService } from "vs/platform/telemetry/common/telemetry";
import { IThemeService } from "vs/platform/theme/common/themeService";
import { IWorkspaceContextService } from "vs/platform/workspace/common/workspace";
import * as extHostTypes from "vs/workbench/api/common/extHostTypes";
import { CustomTreeView, CustomTreeViewPanel } from "vs/workbench/browser/parts/views/customView";
import { CustomTreeView, CustomTreeViewPane } from "vs/workbench/browser/parts/views/customView";
import { ViewContainerViewlet } from "vs/workbench/browser/parts/views/viewsViewlet";
import { Extensions as ViewletExtensions, ShowViewletAction, ViewletDescriptor, ViewletRegistry } from "vs/workbench/browser/viewlet";
import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from "vs/workbench/common/actions";
@ -120,11 +120,11 @@ export const coderApi = (serviceCollection: ServiceCollection): CoderApi => {
}
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(
new ViewletDescriptor(CustomViewlet as any, id, containerName, cssClass, undefined, URI.parse(icon)),
ViewletDescriptor.create(CustomViewlet as any, id, containerName, cssClass, undefined, URI.parse(icon)),
);
Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions).registerWorkbenchAction(
new SyncActionDescriptor(OpenCustomViewletAction as any, id, localize("showViewlet", "Show {0}", containerName)),
SyncActionDescriptor.create(OpenCustomViewletAction as any, id, localize("showViewlet", "Show {0}", containerName)),
"View: Show {0}",
localize("view", "View"),
);
@ -137,7 +137,7 @@ export const coderApi = (serviceCollection: ServiceCollection): CoderApi => {
Registry.as<IViewsRegistry>(ViewsExtensions.ViewsRegistry).registerViews([{
id: viewId,
name: viewName,
ctorDescriptor: { ctor: CustomTreeViewPanel },
ctorDescriptor: { ctor: CustomTreeViewPane },
treeView: getService(IInstantiationService).createInstance(CustomTreeView as any, viewId, container),
}] as ITreeViewDescriptor[], container);
},
@ -286,8 +286,8 @@ class StatusBarEntry implements vscode.StatusBarItem {
private _id: number;
private entry: IStatusBarEntry;
private visible: boolean;
private disposed: boolean;
private visible?: boolean;
private disposed?: boolean;
private statusId: string;
private statusName: string;
private accessor?: IStatusbarEntryAccessor;

View File

@ -1,5 +1,5 @@
import { Emitter } from "vs/base/common/event";
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator } from "vs/platform/instantiation/common/instantiation";
import { ExtHostNodeProxyShape, MainContext, MainThreadNodeProxyShape } from "vs/workbench/api/common/extHost.protocol";
import { IExtHostRpcService } from "vs/workbench/api/common/extHostRpcService";
@ -43,4 +43,4 @@ export class ExtHostNodeProxy implements ExtHostNodeProxyShape {
}
export interface IExtHostNodeProxy extends ExtHostNodeProxy { }
export const IExtHostNodeProxy = createDecorator<IExtHostNodeProxy>('IExtHostNodeProxy');
export const IExtHostNodeProxy = createDecorator<IExtHostNodeProxy>("IExtHostNodeProxy");

View File

@ -4,9 +4,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'self' 'unsafe-inline'; script-src 'unsafe-inline'; manifest-src 'self'; img-src 'self';">
<title>Authenticate: code-server</title>
<link rel="icon" href="./favicon.ico" type="image/x-icon" />
<link rel="manifest" href="./manifest.json">
<link rel="icon" href="./static/out/vs/server/src/media/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="./static/out/vs/server/src/media/manifest.json" crossorigin="use-credentials">
<link rel="apple-touch-icon" href="./static/out/vs/server/src/media/code-server.png" />
<meta name="apple-mobile-web-app-capable" content="yes">
<link href="./static/out/vs/server/src/media/login.css" rel="stylesheet">
</head>
<body>

View File

@ -7,23 +7,6 @@
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<!-- Content Security Policy -->
<meta
http-equiv="Content-Security-Policy"
content="
default-src 'self';
img-src 'self' https: data: blob:;
media-src 'none';
script-src 'self' 'unsafe-eval' https: 'sha256-bpJydy1E+3Mx9MyBtkOIA3yyzM2wdyIz115+Sgq21+0=' 'sha256-meDZW3XhN5JmdjFUrWGhTouRKBiWYtXHltaKnqn/WMo=';
child-src 'self';
frame-src 'self';
worker-src 'self';
style-src 'self' 'unsafe-inline';
connect-src 'self' ws: wss: https:;
font-src 'self' blob:;
manifest-src 'self';
">
<!-- Workbench Configuration -->
<meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONFIGURATION}}">
@ -36,15 +19,14 @@
<meta id="vscode-remote-nls-configuration" data-settings="{{NLS_CONFIGURATION}}">
<!-- Workbench Icon/Manifest/CSS -->
<link rel="icon" href="./favicon.ico" type="image/x-icon" />
<link rel="manifest" href="./manifest.json" crossorigin="use-credentials">
<link rel="apple-touch-icon" href="./static-{{COMMIT}}/out/vs/server/src/media/code-server.png" />
<link rel="icon" href="./static-{{COMMIT}}/out/vs/server/src/media/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="./static-{{COMMIT}}/out/vs/server/src/media/manifest.json" crossorigin="use-credentials">
<link data-name="vs/workbench/workbench.web.api" rel="stylesheet" href="./static-{{COMMIT}}/out/vs/workbench/workbench.web.api.css">
<link rel="apple-touch-icon" href="./static-{{COMMIT}}/out/vs/server/src/media/code-server.png" />
<meta name="apple-mobile-web-app-capable" content="yes">
<!-- Prefetch to avoid waterfall -->
<link rel="prefetch" href="./static-{{COMMIT}}/node_modules/semver-umd/lib/semver-umd.js">
<link rel="prefetch" href="./static-{{COMMIT}}/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js">
</head>
<body aria-label="">
@ -90,8 +72,8 @@
'xterm': `${staticBase}/node_modules/xterm/lib/xterm.js`,
'xterm-addon-search': `${staticBase}/node_modules/xterm-addon-search/lib/xterm-addon-search.js`,
'xterm-addon-web-links': `${staticBase}/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`,
'xterm-addon-webgl': `${staticBase}/node_modules/xterm-addon-webgl/lib/xterm-addon-webgl.js`,
'semver-umd': `${staticBase}/node_modules/semver-umd/lib/semver-umd.js`,
'@microsoft/applicationinsights-web': `${staticBase}/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js`,
},
'vs/nls': nlsConfig,
};

View File

@ -7,23 +7,6 @@
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<!-- Content Security Policy -->
<meta
http-equiv="Content-Security-Policy"
content="
default-src 'self';
img-src 'self' https: data: blob:;
media-src 'none';
script-src 'self' https://az416426.vo.msecnd.net 'unsafe-eval' https: 'unsafe-inline';
child-src 'self';
frame-src 'self' https://*.vscode-webview-test.com;
worker-src 'self';
style-src 'self' 'unsafe-inline';
connect-src 'self' ws: wss: https:;
font-src 'self' blob:;
manifest-src 'self';
">
<!-- Workbench Configuration -->
<meta id="vscode-workbench-web-configuration" data-settings="{{WORKBENCH_WEB_CONFIGURATION}}">
@ -36,8 +19,8 @@
<meta id="vscode-remote-nls-configuration" data-settings="{{NLS_CONFIGURATION}}">
<!-- Workbench Icon/Manifest/CSS -->
<link rel="icon" href="./favicon.ico" type="image/x-icon" />
<link rel="manifest" href="./manifest.json" crossorigin="use-credentials">
<link rel="icon" href="./static/out/vs/server/src/media/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="./static/out/vs/server/src/media/manifest.json" crossorigin="use-credentials">
</head>
<body aria-label="">
@ -58,8 +41,8 @@
'xterm': `${staticBase}/node_modules/xterm/lib/xterm.js`,
'xterm-addon-search': `${staticBase}/node_modules/xterm-addon-search/lib/xterm-addon-search.js`,
'xterm-addon-web-links': `${staticBase}/node_modules/xterm-addon-web-links/lib/xterm-addon-web-links.js`,
'xterm-addon-webgl': `${staticBase}/node_modules/xterm-addon-webgl/lib/xterm-addon-webgl.js`,
'semver-umd': `${staticBase}/node_modules/semver-umd/lib/semver-umd.js`,
'@microsoft/applicationinsights-web': `${staticBase}/node_modules/@microsoft/applicationinsights-web/dist/applicationinsights-web.js`,
},
};
</script>

View File

@ -6,7 +6,7 @@
"background-color": "#fff",
"description": "Run VS Code on a remote server.",
"icons": [{
"src": "./static/out/vs/server/src/media/code-server.png",
"src": "./code-server.png",
"sizes": "384x384",
"type": "image/png"
}]

View File

@ -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);
}

View File

@ -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("");
}

View File

@ -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());

View File

@ -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));

View File

@ -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");