chore(vscode): update to 1.53.2
These conflicts will be resolved in the following commits. We do it this way so that PR review is possible.
This commit is contained in:
@ -23,14 +23,14 @@ function getDownloadUrl(updateUrl: string, commit: string, platform: string, qua
|
||||
return `${updateUrl}/commit:${commit}/server-${platform}/${quality}`;
|
||||
}
|
||||
|
||||
async function downloadVSCodeServerArchive(updateUrl: string, commit: string, quality: string, destDir: string): Promise<string> {
|
||||
async function downloadVSCodeServerArchive(updateUrl: string, commit: string, quality: string, destDir: string, log: (messsage: string) => void): Promise<string> {
|
||||
ensureFolderExists(destDir);
|
||||
|
||||
const platform = process.platform === 'win32' ? 'win32-x64' : process.platform === 'darwin' ? 'darwin' : 'linux-x64';
|
||||
const downloadUrl = getDownloadUrl(updateUrl, commit, platform, quality);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(`Downloading VS Code Server from: ${downloadUrl}`);
|
||||
log(`Downloading VS Code Server from: ${downloadUrl}`);
|
||||
const requestOptions: https.RequestOptions = parseUrl(downloadUrl);
|
||||
|
||||
https.get(requestOptions, res => {
|
||||
@ -70,9 +70,10 @@ async function downloadVSCodeServerArchive(updateUrl: string, commit: string, qu
|
||||
/**
|
||||
* Unzip a .zip or .tar.gz VS Code archive
|
||||
*/
|
||||
function unzipVSCodeServer(vscodeArchivePath: string, extractDir: string) {
|
||||
function unzipVSCodeServer(vscodeArchivePath: string, extractDir: string, destDir: string, log: (messsage: string) => void) {
|
||||
log(`Extracting ${vscodeArchivePath}`);
|
||||
if (vscodeArchivePath.endsWith('.zip')) {
|
||||
const tempDir = fs.mkdtempSync('vscode-server');
|
||||
const tempDir = fs.mkdtempSync(path.join(destDir, 'vscode-server-extract'));
|
||||
if (process.platform === 'win32') {
|
||||
cp.spawnSync('powershell.exe', [
|
||||
'-NoProfile',
|
||||
@ -95,17 +96,17 @@ function unzipVSCodeServer(vscodeArchivePath: string, extractDir: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function downloadAndUnzipVSCodeServer(updateUrl: string, commit: string, quality: string = 'stable', destDir: string): Promise<string> {
|
||||
export async function downloadAndUnzipVSCodeServer(updateUrl: string, commit: string, quality: string = 'stable', destDir: string, log: (messsage: string) => void): Promise<string> {
|
||||
|
||||
const extractDir = path.join(destDir, commit);
|
||||
if (fs.existsSync(extractDir)) {
|
||||
console.log(`Found ${extractDir}. Skipping download.`);
|
||||
log(`Found ${extractDir}. Skipping download.`);
|
||||
} else {
|
||||
console.log(`Downloading VS Code Server ${quality} - ${commit} into ${extractDir}.`);
|
||||
log(`Downloading VS Code Server ${quality} - ${commit} into ${extractDir}.`);
|
||||
try {
|
||||
const vscodeArchivePath = await downloadVSCodeServerArchive(updateUrl, commit, quality, destDir);
|
||||
const vscodeArchivePath = await downloadVSCodeServerArchive(updateUrl, commit, quality, destDir, log);
|
||||
if (fs.existsSync(vscodeArchivePath)) {
|
||||
unzipVSCodeServer(vscodeArchivePath, extractDir);
|
||||
unzipVSCodeServer(vscodeArchivePath, extractDir, destDir, log);
|
||||
// Remove archive
|
||||
fs.unlinkSync(vscodeArchivePath);
|
||||
}
|
||||
@ -114,4 +115,4 @@ export async function downloadAndUnzipVSCodeServer(updateUrl: string, commit: st
|
||||
}
|
||||
}
|
||||
return Promise.resolve(extractDir);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as net from 'net';
|
||||
import * as http from 'http';
|
||||
import { downloadAndUnzipVSCodeServer } from './download';
|
||||
import { terminateProcess } from './util/processes';
|
||||
|
||||
@ -81,6 +82,13 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
const commandArgs = ['--port=0', '--disable-telemetry'];
|
||||
const env = getNewEnv();
|
||||
const remoteDataDir = process.env['TESTRESOLVER_DATA_FOLDER'] || path.join(os.homedir(), serverDataFolderName || `${dataFolderName}-testresolver`);
|
||||
|
||||
const remoteExtension = process.env['TESTRESOLVER_REMOTE_EXTENSION'];
|
||||
if (remoteExtension) {
|
||||
commandArgs.push('--install-extension', remoteExtension);
|
||||
commandArgs.push('--start-server');
|
||||
}
|
||||
|
||||
env['VSCODE_AGENT_FOLDER'] = remoteDataDir;
|
||||
outputChannel.appendLine(`Using data folder at ${remoteDataDir}`);
|
||||
|
||||
@ -95,10 +103,11 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
if (!serverLocation) {
|
||||
const serverBin = path.join(remoteDataDir, 'bin');
|
||||
progress.report({ message: 'Installing VSCode Server' });
|
||||
serverLocation = await downloadAndUnzipVSCodeServer(updateUrl, commit, quality, serverBin);
|
||||
serverLocation = await downloadAndUnzipVSCodeServer(updateUrl, commit, quality, serverBin, m => outputChannel.appendLine(m));
|
||||
}
|
||||
|
||||
outputChannel.appendLine(`Using server build at ${serverLocation}`);
|
||||
outputChannel.appendLine(`Server arguments ${commandArgs.join(' ')}`);
|
||||
|
||||
extHostProcess = cp.spawn(path.join(serverLocation, serverCommand), commandArgs, { env, cwd: serverLocation });
|
||||
}
|
||||
@ -206,27 +215,76 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
});
|
||||
}
|
||||
|
||||
vscode.workspace.registerRemoteAuthorityResolver('test', {
|
||||
const authorityResolverDisposable = vscode.workspace.registerRemoteAuthorityResolver('test', {
|
||||
resolve(_authority: string): Thenable<vscode.ResolvedAuthority> {
|
||||
return vscode.window.withProgress({
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: 'Open TestResolver Remote ([details](command:vscode-testresolver.showLog))',
|
||||
cancellable: false
|
||||
}, (progress) => doResolve(_authority, progress));
|
||||
}
|
||||
},
|
||||
tunnelFactory,
|
||||
tunnelFeatures: { elevation: true, public: !!vscode.workspace.getConfiguration('testresolver').get('supportPublicPorts') },
|
||||
showCandidatePort
|
||||
});
|
||||
context.subscriptions.push(authorityResolverDisposable);
|
||||
|
||||
vscode.commands.registerCommand('vscode-testresolver.newWindow', () => {
|
||||
context.subscriptions.push(vscode.commands.registerCommand('vscode-testresolver.newWindow', () => {
|
||||
return vscode.commands.executeCommand('vscode.newWindow', { remoteAuthority: 'test+test' });
|
||||
});
|
||||
vscode.commands.registerCommand('vscode-testresolver.newWindowWithError', () => {
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('vscode-testresolver.newWindowWithError', () => {
|
||||
return vscode.commands.executeCommand('vscode.newWindow', { remoteAuthority: 'test+error' });
|
||||
});
|
||||
vscode.commands.registerCommand('vscode-testresolver.showLog', () => {
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('vscode-testresolver.killServerAndTriggerHandledError', () => {
|
||||
authorityResolverDisposable.dispose();
|
||||
if (extHostProcess) {
|
||||
terminateProcess(extHostProcess, context.extensionPath);
|
||||
}
|
||||
vscode.workspace.registerRemoteAuthorityResolver('test', {
|
||||
async resolve(_authority: string): Promise<vscode.ResolvedAuthority> {
|
||||
setTimeout(async () => {
|
||||
await vscode.window.showErrorMessage('Just a custom message.', { modal: true, useCustom: true }, 'OK', 'Great');
|
||||
}, 2000);
|
||||
throw vscode.RemoteAuthorityResolverError.NotAvailable('Intentional Error', true);
|
||||
}
|
||||
});
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('vscode-testresolver.showLog', () => {
|
||||
if (outputChannel) {
|
||||
outputChannel.show();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand('vscode-testresolver.openTunnel', async () => {
|
||||
const result = await vscode.window.showInputBox({
|
||||
prompt: 'Enter the remote port for the tunnel',
|
||||
value: '5000',
|
||||
validateInput: input => /^[\d]+$/.test(input) ? undefined : 'Not a valid number'
|
||||
});
|
||||
if (result) {
|
||||
const port = Number.parseInt(result);
|
||||
vscode.workspace.openTunnel({
|
||||
remoteAddress: {
|
||||
host: 'localhost',
|
||||
port: port
|
||||
},
|
||||
localAddressPort: port + 1
|
||||
});
|
||||
}
|
||||
|
||||
}));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('vscode-testresolver.startRemoteServer', async () => {
|
||||
const result = await vscode.window.showInputBox({
|
||||
prompt: 'Enter the port for the remote server',
|
||||
value: '5000',
|
||||
validateInput: input => /^[\d]+$/.test(input) ? undefined : 'Not a valid number'
|
||||
});
|
||||
if (result) {
|
||||
runHTTPTestServer(Number.parseInt(result));
|
||||
}
|
||||
|
||||
}));
|
||||
vscode.commands.executeCommand('setContext', 'forwardedPortsViewEnabled', true);
|
||||
}
|
||||
|
||||
type ActionItem = (vscode.MessageItem & { execute: () => void; });
|
||||
@ -287,3 +345,92 @@ function sleep(ms: number): Promise<void> {
|
||||
function getConfiguration<T>(id: string): T | undefined {
|
||||
return vscode.workspace.getConfiguration('testresolver').get<T>(id);
|
||||
}
|
||||
|
||||
const remoteServers: number[] = [];
|
||||
|
||||
async function showCandidatePort(_host: string, port: number, _detail: string): Promise<boolean> {
|
||||
return remoteServers.includes(port) || port === 100;
|
||||
}
|
||||
|
||||
async function tunnelFactory(tunnelOptions: vscode.TunnelOptions, tunnelCreationOptions: vscode.TunnelCreationOptions): Promise<vscode.Tunnel> {
|
||||
outputChannel.appendLine(`Tunnel factory request: Remote ${tunnelOptions.remoteAddress.port} -> local ${tunnelOptions.localAddressPort}`);
|
||||
if (tunnelCreationOptions.elevationRequired) {
|
||||
await vscode.window.showInformationMessage('This is a fake elevation message. A real resolver would show a native elevation prompt.', { modal: true }, 'Ok');
|
||||
}
|
||||
|
||||
return createTunnelService();
|
||||
|
||||
function newTunnel(localAddress: { host: string, port: number }) {
|
||||
const onDidDispose: vscode.EventEmitter<void> = new vscode.EventEmitter();
|
||||
let isDisposed = false;
|
||||
return {
|
||||
localAddress,
|
||||
remoteAddress: tunnelOptions.remoteAddress,
|
||||
public: !!vscode.workspace.getConfiguration('testresolver').get('supportPublicPorts') && tunnelOptions.public,
|
||||
onDidDispose: onDidDispose.event,
|
||||
dispose: () => {
|
||||
if (!isDisposed) {
|
||||
isDisposed = true;
|
||||
onDidDispose.fire();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createTunnelService(): Promise<vscode.Tunnel> {
|
||||
return new Promise<vscode.Tunnel>((res, _rej) => {
|
||||
const proxyServer = net.createServer(proxySocket => {
|
||||
const remoteSocket = net.createConnection({ host: tunnelOptions.remoteAddress.host, port: tunnelOptions.remoteAddress.port });
|
||||
remoteSocket.pipe(proxySocket);
|
||||
proxySocket.pipe(remoteSocket);
|
||||
});
|
||||
let localPort = 0;
|
||||
|
||||
if (tunnelOptions.localAddressPort) {
|
||||
// When the tunnelOptions include a localAddressPort, we should use that.
|
||||
// However, the test resolver all runs on one machine, so if the localAddressPort is the same as the remote port,
|
||||
// then we must use a different port number.
|
||||
localPort = tunnelOptions.localAddressPort;
|
||||
} else {
|
||||
localPort = tunnelOptions.remoteAddress.port;
|
||||
}
|
||||
|
||||
if (localPort === tunnelOptions.remoteAddress.port) {
|
||||
localPort += 1;
|
||||
}
|
||||
|
||||
// The test resolver can't actually handle privileged ports, it only pretends to.
|
||||
if (localPort < 1024 && process.platform !== 'win32') {
|
||||
localPort = 0;
|
||||
}
|
||||
proxyServer.listen(localPort, () => {
|
||||
const localPort = (<net.AddressInfo>proxyServer.address()).port;
|
||||
outputChannel.appendLine(`New test resolver tunnel service: Remote ${tunnelOptions.remoteAddress.port} -> local ${localPort}`);
|
||||
const tunnel = newTunnel({ host: 'localhost', port: localPort });
|
||||
tunnel.onDidDispose(() => proxyServer.close());
|
||||
res(tunnel);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function runHTTPTestServer(port: number): vscode.Disposable {
|
||||
const server = http.createServer((_req, res) => {
|
||||
res.writeHead(200);
|
||||
res.end(`Hello, World from test server running on port ${port}!`);
|
||||
});
|
||||
remoteServers.push(port);
|
||||
server.listen(port);
|
||||
const message = `Opened HTTP server on http://localhost:${port}`;
|
||||
console.log(message);
|
||||
outputChannel.appendLine(message);
|
||||
return {
|
||||
dispose: () => {
|
||||
server.close();
|
||||
const index = remoteServers.indexOf(port);
|
||||
if (index !== -1) {
|
||||
remoteServers.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ export function terminateProcess(p: cp.ChildProcess, extensionPath: string): Ter
|
||||
} else if (process.platform === 'darwin' || process.platform === 'linux') {
|
||||
try {
|
||||
const cmd = path.join(extensionPath, 'scripts', 'terminateProcess.sh');
|
||||
const result = cp.spawnSync(cmd, [process.pid.toString()]);
|
||||
const result = cp.spawnSync(cmd, [p.pid.toString()]);
|
||||
if (result.error) {
|
||||
return { success: false, error: result.error };
|
||||
}
|
||||
@ -34,4 +34,4 @@ export function terminateProcess(p: cp.ChildProcess, extensionPath: string): Ter
|
||||
p.kill('SIGKILL');
|
||||
}
|
||||
return { success: true };
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user