mirror of
https://github.com/jeanp413/open-remote-ssh.git
synced 2026-07-16 19:17:11 +02:00
This commit is contained in:
+9
-1
@@ -1,7 +1,7 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_style = space
|
||||
tab_width = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
@@ -12,6 +12,10 @@ insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[{*.json,.fixpackrc}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.md]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
@@ -20,3 +24,7 @@ indent_size = 4
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[{*.sh,*.ps1}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
@@ -5,26 +5,26 @@ const path = require('path');
|
||||
const version = process.argv[2];
|
||||
|
||||
try {
|
||||
const changelog = fs.readFileSync(path.join(process.cwd(), 'CHANGELOG.md'), 'utf8');
|
||||
const changelog = fs.readFileSync(path.join(process.cwd(), 'CHANGELOG.md'), 'utf8');
|
||||
|
||||
// Regular expression to match a version section with the date
|
||||
// Matches from "## 0.0.48" until the next ## or end of file
|
||||
const versionRegex = new RegExp(`## ${version.slice(1)}([^#]|#(?!#))*(?=## |$)`, 's');
|
||||
// Regular expression to match a version section with the date
|
||||
// Matches from "## 0.0.48" until the next ## or end of file
|
||||
const versionRegex = new RegExp(`## ${version.slice(1)}([^#]|#(?!#))*(?=## |$)`, 's');
|
||||
|
||||
const match = changelog.match(versionRegex);
|
||||
const match = changelog.match(versionRegex);
|
||||
|
||||
if(match) {
|
||||
// Remove the version header and trim whitespace
|
||||
const notes = match[0].replace(/^## \d+\.\d+\.\d+\n/, '').trim();
|
||||
console.log(notes);
|
||||
process.exit(0);
|
||||
}
|
||||
else {
|
||||
console.error(`No changelog entry found for version ${version}`);
|
||||
process.exit(1);
|
||||
}
|
||||
if(match) {
|
||||
// Remove the version header and trim whitespace
|
||||
const notes = match[0].replace(/^## \d+\.\d+\.\d+\n/, '').trim();
|
||||
console.log(notes);
|
||||
process.exit(0);
|
||||
}
|
||||
else {
|
||||
console.error(`No changelog entry found for version ${version}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
catch(error) {
|
||||
console.error('Error reading CHANGELOG.md:', error);
|
||||
process.exit(1);
|
||||
console.error('Error reading CHANGELOG.md:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
+12
-12
@@ -56,21 +56,21 @@ Community Moderators take reports of violations seriously and will make every ef
|
||||
If an investigation by the Community Moderators finds that this Code of Conduct has been violated, the following enforcement ladder may be used to determine how best to repair harm, based on the incident's impact on the individuals involved and the community as a whole. Depending on the severity of a violation, lower rungs on the ladder may be skipped.
|
||||
|
||||
1) Warning
|
||||
1) Event: A violation involving a single incident or series of incidents.
|
||||
2) Consequence: A private, written warning from the Community Moderators.
|
||||
3) Repair: Examples of repair include a private written apology, acknowledgement of responsibility, and seeking clarification on expectations.
|
||||
1) Event: A violation involving a single incident or series of incidents.
|
||||
2) Consequence: A private, written warning from the Community Moderators.
|
||||
3) Repair: Examples of repair include a private written apology, acknowledgement of responsibility, and seeking clarification on expectations.
|
||||
2) Temporarily Limited Activities
|
||||
1) Event: A repeated incidence of a violation that previously resulted in a warning, or the first incidence of a more serious violation.
|
||||
2) Consequence: A private, written warning with a time-limited cooldown period designed to underscore the seriousness of the situation and give the community members involved time to process the incident. The cooldown period may be limited to particular communication channels or interactions with particular community members.
|
||||
3) Repair: Examples of repair may include making an apology, using the cooldown period to reflect on actions and impact, and being thoughtful about re-entering community spaces after the period is over.
|
||||
1) Event: A repeated incidence of a violation that previously resulted in a warning, or the first incidence of a more serious violation.
|
||||
2) Consequence: A private, written warning with a time-limited cooldown period designed to underscore the seriousness of the situation and give the community members involved time to process the incident. The cooldown period may be limited to particular communication channels or interactions with particular community members.
|
||||
3) Repair: Examples of repair may include making an apology, using the cooldown period to reflect on actions and impact, and being thoughtful about re-entering community spaces after the period is over.
|
||||
3) Temporary Suspension
|
||||
1) Event: A pattern of repeated violation which the Community Moderators have tried to address with warnings, or a single serious violation.
|
||||
2) Consequence: A private written warning with conditions for return from suspension. In general, temporary suspensions give the person being suspended time to reflect upon their behavior and possible corrective actions.
|
||||
3) Repair: Examples of repair include respecting the spirit of the suspension, meeting the specified conditions for return, and being thoughtful about how to reintegrate with the community when the suspension is lifted.
|
||||
1) Event: A pattern of repeated violation which the Community Moderators have tried to address with warnings, or a single serious violation.
|
||||
2) Consequence: A private written warning with conditions for return from suspension. In general, temporary suspensions give the person being suspended time to reflect upon their behavior and possible corrective actions.
|
||||
3) Repair: Examples of repair include respecting the spirit of the suspension, meeting the specified conditions for return, and being thoughtful about how to reintegrate with the community when the suspension is lifted.
|
||||
4) Permanent Ban
|
||||
1) Event: A pattern of repeated code of conduct violations that other steps on the ladder have failed to resolve, or a violation so serious that the Community Moderators determine there is no way to keep the community safe with this person as a member.
|
||||
2) Consequence: Access to all community spaces, tools, and communication channels is removed. In general, permanent bans should be rarely used, should have strong reasoning behind them, and should only be resorted to if working through other remedies has failed to change the behavior.
|
||||
3) Repair: There is no possible repair in cases of this severity.
|
||||
1) Event: A pattern of repeated code of conduct violations that other steps on the ladder have failed to resolve, or a violation so serious that the Community Moderators determine there is no way to keep the community safe with this person as a member.
|
||||
2) Consequence: Access to all community spaces, tools, and communication channels is removed. In general, permanent bans should be rarely used, should have strong reasoning behind them, and should only be resorted to if working through other remedies has failed to change the behavior.
|
||||
3) Repair: There is no possible repair in cases of this severity.
|
||||
|
||||
This enforcement ladder is intended as a guideline. It does not limit the ability of Community Managers to use their discretion and judgment, in keeping with the best interests of our community.
|
||||
|
||||
|
||||
+2
-2
@@ -434,7 +434,7 @@ export class RemoteSSHResolver implements vscode.RemoteAuthorityResolver, vscode
|
||||
}
|
||||
if (!await fileExists(identityKey.filename)) {
|
||||
// Try next identity file
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return callback(null as any);
|
||||
}
|
||||
|
||||
@@ -457,7 +457,7 @@ export class RemoteSSHResolver implements vscode.RemoteAuthorityResolver, vscode
|
||||
}
|
||||
if (!result || result instanceof Error) {
|
||||
// Try next identity file
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return callback(null as any);
|
||||
}
|
||||
|
||||
|
||||
+26
-26
@@ -1,37 +1,37 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export function disposeAll(disposables: vscode.Disposable[]): void {
|
||||
while (disposables.length) {
|
||||
const item = disposables.pop();
|
||||
if (item) {
|
||||
item.dispose();
|
||||
}
|
||||
}
|
||||
while (disposables.length) {
|
||||
const item = disposables.pop();
|
||||
if (item) {
|
||||
item.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class Disposable {
|
||||
private _isDisposed = false;
|
||||
private _isDisposed = false;
|
||||
|
||||
protected _disposables: vscode.Disposable[] = [];
|
||||
protected _disposables: vscode.Disposable[] = [];
|
||||
|
||||
public dispose(): void {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
this._isDisposed = true;
|
||||
disposeAll(this._disposables);
|
||||
}
|
||||
public dispose(): void {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
this._isDisposed = true;
|
||||
disposeAll(this._disposables);
|
||||
}
|
||||
|
||||
protected _register<T extends vscode.Disposable>(value: T): T {
|
||||
if (this._isDisposed) {
|
||||
value.dispose();
|
||||
} else {
|
||||
this._disposables.push(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
protected _register<T extends vscode.Disposable>(value: T): T {
|
||||
if (this._isDisposed) {
|
||||
value.dispose();
|
||||
} else {
|
||||
this._disposables.push(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected get isDisposed(): boolean {
|
||||
return this._isDisposed;
|
||||
}
|
||||
protected get isDisposed(): boolean {
|
||||
return this._isDisposed;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ export async function exists(path: string) {
|
||||
}
|
||||
|
||||
export function untildify(path: string){
|
||||
return path.replace(/^~(?=$|\/|\\)/, homeDir);
|
||||
return path.replace(/^~(?=$|\/|\\)/, homeDir);
|
||||
}
|
||||
|
||||
export function normalizeToSlash(path: string) {
|
||||
|
||||
+44
-44
@@ -5,63 +5,63 @@ import { inspect } from 'node:util';
|
||||
type LogLevel = 'Trace' | 'Info' | 'Error';
|
||||
|
||||
export default class Log {
|
||||
private output: vscode.OutputChannel;
|
||||
private output: vscode.OutputChannel;
|
||||
|
||||
constructor(name: string) {
|
||||
this.output = vscode.window.createOutputChannel(name);
|
||||
}
|
||||
constructor(name: string) {
|
||||
this.output = vscode.window.createOutputChannel(name);
|
||||
}
|
||||
|
||||
public trace(message: string, data?: unknown): void {
|
||||
this.logLevel('Trace', message, data);
|
||||
}
|
||||
public trace(message: string, data?: unknown): void {
|
||||
this.logLevel('Trace', message, data);
|
||||
}
|
||||
|
||||
public info(message: string, data?: unknown): void {
|
||||
this.logLevel('Info', message, data);
|
||||
}
|
||||
public info(message: string, data?: unknown): void {
|
||||
this.logLevel('Info', message, data);
|
||||
}
|
||||
|
||||
public error(message: string, data?: unknown): void {
|
||||
this.logLevel('Error', message, data);
|
||||
}
|
||||
public error(message: string, data?: unknown): void {
|
||||
this.logLevel('Error', message, data);
|
||||
}
|
||||
|
||||
public logLevel(level: LogLevel, message: string, data?: unknown): void {
|
||||
this.output.appendLine(`[${level} - ${this.now()}] ${message}`);
|
||||
if (data) {
|
||||
this.output.appendLine(toString(data));
|
||||
}
|
||||
}
|
||||
public logLevel(level: LogLevel, message: string, data?: unknown): void {
|
||||
this.output.appendLine(`[${level} - ${this.now()}] ${message}`);
|
||||
if (data) {
|
||||
this.output.appendLine(toString(data));
|
||||
}
|
||||
}
|
||||
|
||||
private now(): string {
|
||||
const now = new Date();
|
||||
return padLeft(now.getUTCHours() + '', 2, '0')
|
||||
+ ':' + padLeft(now.getMinutes() + '', 2, '0')
|
||||
+ ':' + padLeft(now.getUTCSeconds() + '', 2, '0') + '.' + now.getMilliseconds();
|
||||
}
|
||||
private now(): string {
|
||||
const now = new Date();
|
||||
return padLeft(now.getUTCHours() + '', 2, '0')
|
||||
+ ':' + padLeft(now.getMinutes() + '', 2, '0')
|
||||
+ ':' + padLeft(now.getUTCSeconds() + '', 2, '0') + '.' + now.getMilliseconds();
|
||||
}
|
||||
|
||||
public show() {
|
||||
this.output.show();
|
||||
}
|
||||
public show() {
|
||||
this.output.show();
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
this.output.dispose();
|
||||
}
|
||||
public dispose() {
|
||||
this.output.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
function padLeft(s: string, n: number, pad = ' ') {
|
||||
return pad.repeat(Math.max(0, n - s.length)) + s;
|
||||
return pad.repeat(Math.max(0, n - s.length)) + s;
|
||||
}
|
||||
|
||||
function toString(value: unknown): string {
|
||||
if (isPrimitive(value)) {
|
||||
return `${value}`;
|
||||
}
|
||||
else if (value instanceof Error) {
|
||||
return value.stack || value.message;
|
||||
}
|
||||
else if (isRecord(value)) {
|
||||
if (value.success === false && isString(value.message)) {
|
||||
return value.message;
|
||||
}
|
||||
}
|
||||
if (isPrimitive(value)) {
|
||||
return `${value}`;
|
||||
}
|
||||
else if (value instanceof Error) {
|
||||
return value.stack || value.message;
|
||||
}
|
||||
else if (isRecord(value)) {
|
||||
if (value.success === false && isString(value.message)) {
|
||||
return value.message;
|
||||
}
|
||||
}
|
||||
|
||||
return inspect(value, { depth: null, compact: true, breakLength: Infinity });
|
||||
return inspect(value, { depth: null, compact: true, breakLength: Infinity });
|
||||
}
|
||||
|
||||
+92
-92
@@ -5,15 +5,15 @@ import * as net from 'net';
|
||||
* Finds a random unused port assigned by the operating system. Will reject in case no free port can be found.
|
||||
*/
|
||||
export function findRandomPort(): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const server = net.createServer({ pauseOnConnect: true });
|
||||
server.on('error', reject);
|
||||
server.on('listening', () => {
|
||||
const port = (server.address() as net.AddressInfo).port;
|
||||
server.close(() => resolve(port));
|
||||
});
|
||||
server.listen(0, '127.0.0.1');
|
||||
});
|
||||
return new Promise((resolve, reject) => {
|
||||
const server = net.createServer({ pauseOnConnect: true });
|
||||
server.on('error', reject);
|
||||
server.on('listening', () => {
|
||||
const port = (server.address() as net.AddressInfo).port;
|
||||
server.close(() => resolve(port));
|
||||
});
|
||||
server.listen(0, '127.0.0.1');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21,110 +21,110 @@ export function findRandomPort(): Promise<number> {
|
||||
* is openable. Will return 0 in case no free port can be found.
|
||||
*/
|
||||
export function findFreePort(startPort: number, giveUpAfter: number, timeout: number, stride = 1): Promise<number> {
|
||||
let done = false;
|
||||
let done = false;
|
||||
|
||||
return new Promise(resolve => {
|
||||
const timeoutHandle = setTimeout(() => {
|
||||
if (!done) {
|
||||
done = true;
|
||||
return resolve(0);
|
||||
}
|
||||
}, timeout);
|
||||
return new Promise(resolve => {
|
||||
const timeoutHandle = setTimeout(() => {
|
||||
if (!done) {
|
||||
done = true;
|
||||
return resolve(0);
|
||||
}
|
||||
}, timeout);
|
||||
|
||||
doFindFreePort(startPort, giveUpAfter, stride, (port) => {
|
||||
if (!done) {
|
||||
done = true;
|
||||
clearTimeout(timeoutHandle);
|
||||
return resolve(port);
|
||||
}
|
||||
});
|
||||
});
|
||||
doFindFreePort(startPort, giveUpAfter, stride, (port) => {
|
||||
if (!done) {
|
||||
done = true;
|
||||
clearTimeout(timeoutHandle);
|
||||
return resolve(port);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function doFindFreePort(startPort: number, giveUpAfter: number, stride: number, clb: (port: number) => void): void {
|
||||
if (giveUpAfter === 0) {
|
||||
return clb(0);
|
||||
}
|
||||
if (giveUpAfter === 0) {
|
||||
return clb(0);
|
||||
}
|
||||
|
||||
const client = new net.Socket();
|
||||
const client = new net.Socket();
|
||||
|
||||
// If we can connect to the port it means the port is already taken so we continue searching
|
||||
client.once('connect', () => {
|
||||
dispose(client);
|
||||
// If we can connect to the port it means the port is already taken so we continue searching
|
||||
client.once('connect', () => {
|
||||
dispose(client);
|
||||
|
||||
return doFindFreePort(startPort + stride, giveUpAfter - 1, stride, clb);
|
||||
});
|
||||
return doFindFreePort(startPort + stride, giveUpAfter - 1, stride, clb);
|
||||
});
|
||||
|
||||
client.once('data', () => {
|
||||
// this listener is required since node.js 8.x
|
||||
});
|
||||
client.once('data', () => {
|
||||
// this listener is required since node.js 8.x
|
||||
});
|
||||
|
||||
client.once('error', (err: Error & { code?: string }) => {
|
||||
dispose(client);
|
||||
client.once('error', (err: Error & { code?: string }) => {
|
||||
dispose(client);
|
||||
|
||||
// If we receive any non ECONNREFUSED error, it means the port is used but we cannot connect
|
||||
if (err.code !== 'ECONNREFUSED') {
|
||||
return doFindFreePort(startPort + stride, giveUpAfter - 1, stride, clb);
|
||||
}
|
||||
// If we receive any non ECONNREFUSED error, it means the port is used but we cannot connect
|
||||
if (err.code !== 'ECONNREFUSED') {
|
||||
return doFindFreePort(startPort + stride, giveUpAfter - 1, stride, clb);
|
||||
}
|
||||
|
||||
// Otherwise it means the port is free to use!
|
||||
return clb(startPort);
|
||||
});
|
||||
// Otherwise it means the port is free to use!
|
||||
return clb(startPort);
|
||||
});
|
||||
|
||||
client.connect(startPort, '127.0.0.1');
|
||||
client.connect(startPort, '127.0.0.1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses listen instead of connect. Is faster, but if there is another listener on 0.0.0.0 then this will take 127.0.0.1 from that listener.
|
||||
*/
|
||||
export function findFreePortFaster(startPort: number, giveUpAfter: number, timeout: number): Promise<number> {
|
||||
let resolved = false;
|
||||
let timeoutHandle: NodeJS.Timeout | undefined = undefined;
|
||||
let countTried = 1;
|
||||
const server = net.createServer({ pauseOnConnect: true });
|
||||
function doResolve(port: number, resolve: (port: number) => void) {
|
||||
if (!resolved) {
|
||||
resolved = true;
|
||||
server.removeAllListeners();
|
||||
server.close();
|
||||
if (timeoutHandle) {
|
||||
clearTimeout(timeoutHandle);
|
||||
}
|
||||
resolve(port);
|
||||
}
|
||||
}
|
||||
return new Promise<number>(resolve => {
|
||||
timeoutHandle = setTimeout(() => {
|
||||
doResolve(0, resolve);
|
||||
}, timeout);
|
||||
let resolved = false;
|
||||
let timeoutHandle: NodeJS.Timeout | undefined = undefined;
|
||||
let countTried = 1;
|
||||
const server = net.createServer({ pauseOnConnect: true });
|
||||
function doResolve(port: number, resolve: (port: number) => void) {
|
||||
if (!resolved) {
|
||||
resolved = true;
|
||||
server.removeAllListeners();
|
||||
server.close();
|
||||
if (timeoutHandle) {
|
||||
clearTimeout(timeoutHandle);
|
||||
}
|
||||
resolve(port);
|
||||
}
|
||||
}
|
||||
return new Promise<number>(resolve => {
|
||||
timeoutHandle = setTimeout(() => {
|
||||
doResolve(0, resolve);
|
||||
}, timeout);
|
||||
|
||||
server.on('listening', () => {
|
||||
doResolve(startPort, resolve);
|
||||
});
|
||||
server.on('error', err => {
|
||||
if (isNodeError(err) && (err.code === 'EADDRINUSE' || err.code === 'EACCES') && (countTried < giveUpAfter)) {
|
||||
startPort++;
|
||||
countTried++;
|
||||
server.listen(startPort, '127.0.0.1');
|
||||
} else {
|
||||
doResolve(0, resolve);
|
||||
}
|
||||
});
|
||||
server.on('close', () => {
|
||||
doResolve(0, resolve);
|
||||
});
|
||||
server.listen(startPort, '127.0.0.1');
|
||||
});
|
||||
server.on('listening', () => {
|
||||
doResolve(startPort, resolve);
|
||||
});
|
||||
server.on('error', err => {
|
||||
if (isNodeError(err) && (err.code === 'EADDRINUSE' || err.code === 'EACCES') && (countTried < giveUpAfter)) {
|
||||
startPort++;
|
||||
countTried++;
|
||||
server.listen(startPort, '127.0.0.1');
|
||||
} else {
|
||||
doResolve(0, resolve);
|
||||
}
|
||||
});
|
||||
server.on('close', () => {
|
||||
doResolve(0, resolve);
|
||||
});
|
||||
server.listen(startPort, '127.0.0.1');
|
||||
});
|
||||
}
|
||||
|
||||
function dispose(socket: net.Socket): void {
|
||||
try {
|
||||
socket.removeAllListeners('connect');
|
||||
socket.removeAllListeners('error');
|
||||
socket.end();
|
||||
socket.destroy();
|
||||
socket.unref();
|
||||
} catch (error) {
|
||||
console.error(error); // otherwise this error would get lost in the callback chain
|
||||
}
|
||||
try {
|
||||
socket.removeAllListeners('connect');
|
||||
socket.removeAllListeners('error');
|
||||
socket.end();
|
||||
socket.destroy();
|
||||
socket.unref();
|
||||
} catch (error) {
|
||||
console.error(error); // otherwise this error would get lost in the callback chain
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,166 +29,166 @@ $ARCH=
|
||||
$PLATFORM="win32"
|
||||
|
||||
function printInstallResults($code) {
|
||||
"%%SCRIPT_ID%%: start"
|
||||
"exitCode==$code=="
|
||||
"listeningOn==$LISTENING_ON=="
|
||||
"connectionToken==$SERVER_CONNECTION_TOKEN=="
|
||||
"logFile==$SERVER_LOGFILE=="
|
||||
"osReleaseId==$OS_RELEASE_ID=="
|
||||
"arch==$ARCH=="
|
||||
"platform==$PLATFORM=="
|
||||
"tmpDir==$TMP_DIR=="
|
||||
"%%SCRIPT_ID%%: start"
|
||||
"exitCode==$code=="
|
||||
"listeningOn==$LISTENING_ON=="
|
||||
"connectionToken==$SERVER_CONNECTION_TOKEN=="
|
||||
"logFile==$SERVER_LOGFILE=="
|
||||
"osReleaseId==$OS_RELEASE_ID=="
|
||||
"arch==$ARCH=="
|
||||
"platform==$PLATFORM=="
|
||||
"tmpDir==$TMP_DIR=="
|
||||
%%ENV_VAR_LINES%%
|
||||
"%%SCRIPT_ID%%: end"
|
||||
"%%SCRIPT_ID%%: end"
|
||||
}
|
||||
|
||||
# Check machine architecture
|
||||
$ARCH=$env:PROCESSOR_ARCHITECTURE
|
||||
# Use x64 version for ARM64, as it's not yet available.
|
||||
if(($ARCH -eq "AMD64") -or ($ARCH -eq "IA64") -or ($ARCH -eq "ARM64")) {
|
||||
$SERVER_ARCH="x64"
|
||||
$SERVER_ARCH="x64"
|
||||
}
|
||||
else {
|
||||
"Error architecture not supported: $ARCH"
|
||||
printInstallResults 1
|
||||
exit 0
|
||||
"Error architecture not supported: $ARCH"
|
||||
printInstallResults 1
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Create installation folder
|
||||
if(!(Test-Path $SERVER_DIR)) {
|
||||
try {
|
||||
ni -it d $SERVER_DIR -f -ea si
|
||||
} catch {
|
||||
"Error creating server install directory - $($_.ToString())"
|
||||
exit 1
|
||||
}
|
||||
try {
|
||||
ni -it d $SERVER_DIR -f -ea si
|
||||
} catch {
|
||||
"Error creating server install directory - $($_.ToString())"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if(!(Test-Path $SERVER_DIR)) {
|
||||
"Error creating server install directory"
|
||||
exit 1
|
||||
}
|
||||
if(!(Test-Path $SERVER_DIR)) {
|
||||
"Error creating server install directory"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
cd $SERVER_DIR
|
||||
|
||||
# Check if server script is already installed
|
||||
if(!(Test-Path $SERVER_SCRIPT)) {
|
||||
del vscode-server.tar.gz
|
||||
|
||||
$REQUEST_ARGUMENTS = @{
|
||||
Uri="$SERVER_DOWNLOAD_URL"
|
||||
TimeoutSec=20
|
||||
OutFile="vscode-server.tar.gz"
|
||||
UseBasicParsing=$True
|
||||
}
|
||||
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
Invoke-RestMethod @REQUEST_ARGUMENTS
|
||||
|
||||
if(Test-Path "vscode-server.tar.gz") {
|
||||
tar -xf vscode-server.tar.gz --strip-components 1
|
||||
|
||||
del vscode-server.tar.gz
|
||||
}
|
||||
|
||||
$REQUEST_ARGUMENTS = @{
|
||||
Uri="$SERVER_DOWNLOAD_URL"
|
||||
TimeoutSec=20
|
||||
OutFile="vscode-server.tar.gz"
|
||||
UseBasicParsing=$True
|
||||
}
|
||||
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
|
||||
Invoke-RestMethod @REQUEST_ARGUMENTS
|
||||
|
||||
if(Test-Path "vscode-server.tar.gz") {
|
||||
tar -xf vscode-server.tar.gz --strip-components 1
|
||||
|
||||
del vscode-server.tar.gz
|
||||
}
|
||||
|
||||
if(!(Test-Path $SERVER_SCRIPT)) {
|
||||
"Error while installing the server binary"
|
||||
exit 1
|
||||
}
|
||||
if(!(Test-Path $SERVER_SCRIPT)) {
|
||||
"Error while installing the server binary"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
else {
|
||||
"Server script already installed in $SERVER_SCRIPT"
|
||||
"Server script already installed in $SERVER_SCRIPT"
|
||||
}
|
||||
|
||||
# Modify the commit in the remote server to match the local value
|
||||
if(%%MODIFY_PRODUCT_JSON%%) {
|
||||
echo "Will modify product.json on remote to match the commit value"
|
||||
(Get-Content -Raw "$SERVER_DIR\product.json") -replace '"commit": "[0-9a-f]+",', ('"commit": "' + $DISTRO_COMMIT + '",') |
|
||||
Set-Content -NoNewLine "$SERVER_DIR\product.json"
|
||||
echo "Will modify product.json on remote to match the commit value"
|
||||
(Get-Content -Raw "$SERVER_DIR\product.json") -replace '"commit": "[0-9a-f]+",', ('"commit": "' + $DISTRO_COMMIT + '",') |
|
||||
Set-Content -NoNewLine "$SERVER_DIR\product.json"
|
||||
}
|
||||
|
||||
# Try to find if server is already running
|
||||
if(Get-Process node -ErrorAction SilentlyContinue | Where-Object Path -Like "$SERVER_DIR\*") {
|
||||
echo "Server script is already running $SERVER_SCRIPT"
|
||||
echo "Server script is already running $SERVER_SCRIPT"
|
||||
}
|
||||
else {
|
||||
if(Test-Path $SERVER_LOGFILE) {
|
||||
del $SERVER_LOGFILE
|
||||
}
|
||||
if(Test-Path $SERVER_PIDFILE) {
|
||||
del $SERVER_PIDFILE
|
||||
}
|
||||
if(Test-Path $SERVER_TOKENFILE) {
|
||||
del $SERVER_TOKENFILE
|
||||
}
|
||||
if(Test-Path $SERVER_LOGFILE) {
|
||||
del $SERVER_LOGFILE
|
||||
}
|
||||
if(Test-Path $SERVER_PIDFILE) {
|
||||
del $SERVER_PIDFILE
|
||||
}
|
||||
if(Test-Path $SERVER_TOKENFILE) {
|
||||
del $SERVER_TOKENFILE
|
||||
}
|
||||
|
||||
$SERVER_CONNECTION_TOKEN="%%SERVER_CONNECTION_TOKEN%%"
|
||||
[System.IO.File]::WriteAllLines($SERVER_TOKENFILE, $SERVER_CONNECTION_TOKEN)
|
||||
$SERVER_CONNECTION_TOKEN="%%SERVER_CONNECTION_TOKEN%%"
|
||||
[System.IO.File]::WriteAllLines($SERVER_TOKENFILE, $SERVER_CONNECTION_TOKEN)
|
||||
|
||||
$SCRIPT_ARGUMENTS="--start-server --host=127.0.0.1 $SERVER_LISTEN_FLAG $SERVER_DATA_DIR_FLAG $SERVER_VALIDATION_FLAG $SERVER_INITIAL_EXTENSIONS --connection-token-file $SERVER_TOKENFILE --telemetry-level off --enable-remote-auto-shutdown --accept-server-license-terms *> '$SERVER_LOGFILE'"
|
||||
$SCRIPT_ARGUMENTS="--start-server --host=127.0.0.1 $SERVER_LISTEN_FLAG $SERVER_DATA_DIR_FLAG $SERVER_VALIDATION_FLAG $SERVER_INITIAL_EXTENSIONS --connection-token-file $SERVER_TOKENFILE --telemetry-level off --enable-remote-auto-shutdown --accept-server-license-terms *> '$SERVER_LOGFILE'"
|
||||
|
||||
$START_ARGUMENTS = @{
|
||||
FilePath = "powershell.exe"
|
||||
WindowStyle = "hidden"
|
||||
ArgumentList = @(
|
||||
"-ExecutionPolicy", "Unrestricted", "-NoLogo", "-NoProfile", "-NonInteractive", "-c", "$SERVER_SCRIPT $SCRIPT_ARGUMENTS"
|
||||
)
|
||||
PassThru = $True
|
||||
}
|
||||
$START_ARGUMENTS = @{
|
||||
FilePath = "powershell.exe"
|
||||
WindowStyle = "hidden"
|
||||
ArgumentList = @(
|
||||
"-ExecutionPolicy", "Unrestricted", "-NoLogo", "-NoProfile", "-NonInteractive", "-c", "$SERVER_SCRIPT $SCRIPT_ARGUMENTS"
|
||||
)
|
||||
PassThru = $True
|
||||
}
|
||||
|
||||
$SERVER_ID = (start @START_ARGUMENTS).ID
|
||||
$SERVER_ID = (start @START_ARGUMENTS).ID
|
||||
|
||||
if($SERVER_ID) {
|
||||
[System.IO.File]::WriteAllLines($SERVER_PIDFILE, $SERVER_ID)
|
||||
}
|
||||
if($SERVER_ID) {
|
||||
[System.IO.File]::WriteAllLines($SERVER_PIDFILE, $SERVER_ID)
|
||||
}
|
||||
}
|
||||
|
||||
if(Test-Path $SERVER_TOKENFILE) {
|
||||
$SERVER_CONNECTION_TOKEN="$(cat $SERVER_TOKENFILE)"
|
||||
$SERVER_CONNECTION_TOKEN="$(cat $SERVER_TOKENFILE)"
|
||||
}
|
||||
else {
|
||||
"Error server token file not found $SERVER_TOKENFILE"
|
||||
printInstallResults 1
|
||||
exit 0
|
||||
"Error server token file not found $SERVER_TOKENFILE"
|
||||
printInstallResults 1
|
||||
exit 0
|
||||
}
|
||||
|
||||
sleep -Milliseconds 500
|
||||
|
||||
$SELECT_ARGUMENTS = @{
|
||||
Path = $SERVER_LOGFILE
|
||||
Pattern = "Extension host agent listening on (\d+)"
|
||||
Path = $SERVER_LOGFILE
|
||||
Pattern = "Extension host agent listening on (\d+)"
|
||||
}
|
||||
|
||||
for($I = 1; $I -le 5; $I++) {
|
||||
if(Test-Path $SERVER_LOGFILE) {
|
||||
$GROUPS = (Select-String @SELECT_ARGUMENTS).Matches.Groups
|
||||
if(Test-Path $SERVER_LOGFILE) {
|
||||
$GROUPS = (Select-String @SELECT_ARGUMENTS).Matches.Groups
|
||||
|
||||
if($GROUPS) {
|
||||
$LISTENING_ON = $GROUPS[1].Value
|
||||
break
|
||||
}
|
||||
if($GROUPS) {
|
||||
$LISTENING_ON = $GROUPS[1].Value
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
sleep -Milliseconds 500
|
||||
sleep -Milliseconds 500
|
||||
}
|
||||
|
||||
if(!(Test-Path $SERVER_LOGFILE)) {
|
||||
"Error server log file not found $SERVER_LOGFILE"
|
||||
printInstallResults 1
|
||||
exit 0
|
||||
"Error server log file not found $SERVER_LOGFILE"
|
||||
printInstallResults 1
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Finish server setup
|
||||
printInstallResults 0
|
||||
|
||||
if($SERVER_ID) {
|
||||
while($True) {
|
||||
if(!(gps -Id $SERVER_ID)) {
|
||||
"server died, exit"
|
||||
exit 0
|
||||
}
|
||||
|
||||
sleep 30
|
||||
while($True) {
|
||||
if(!(gps -Id $SERVER_ID)) {
|
||||
"server died, exit"
|
||||
exit 0
|
||||
}
|
||||
|
||||
sleep 30
|
||||
}
|
||||
}
|
||||
|
||||
+145
-145
@@ -29,18 +29,18 @@ PLATFORM=
|
||||
|
||||
# Mimic output from logs of remote-ssh extension
|
||||
print_install_results_and_exit() {
|
||||
echo "%%SCRIPT_ID%%: start"
|
||||
echo "exitCode==$1=="
|
||||
echo "listeningOn==$LISTENING_ON=="
|
||||
echo "connectionToken==$SERVER_CONNECTION_TOKEN=="
|
||||
echo "logFile==$SERVER_LOGFILE=="
|
||||
echo "osReleaseId==$OS_RELEASE_ID=="
|
||||
echo "arch==$ARCH=="
|
||||
echo "platform==$PLATFORM=="
|
||||
echo "tmpDir==$TMP_DIR=="
|
||||
echo "%%SCRIPT_ID%%: start"
|
||||
echo "exitCode==$1=="
|
||||
echo "listeningOn==$LISTENING_ON=="
|
||||
echo "connectionToken==$SERVER_CONNECTION_TOKEN=="
|
||||
echo "logFile==$SERVER_LOGFILE=="
|
||||
echo "osReleaseId==$OS_RELEASE_ID=="
|
||||
echo "arch==$ARCH=="
|
||||
echo "platform==$PLATFORM=="
|
||||
echo "tmpDir==$TMP_DIR=="
|
||||
%%ENV_VAR_LINES%%
|
||||
echo "%%SCRIPT_ID%%: end"
|
||||
exit 0
|
||||
echo "%%SCRIPT_ID%%: end"
|
||||
exit 0
|
||||
}
|
||||
|
||||
LOCKFILE="$TMP_DIR/server_install.lock"
|
||||
@@ -51,204 +51,204 @@ if command -v flock >/dev/null 2>&1; then
|
||||
flock -x -w 30 $FD || print_install_results_and_exit 1
|
||||
trap "flock -u $FD; trap - EXIT INT HUP; exit" EXIT INT HUP
|
||||
else
|
||||
echo "Warning: flock not available, skipping install lock" >&2
|
||||
echo "Warning: flock not available, skipping install lock" >&2
|
||||
fi
|
||||
|
||||
# Check if platform is supported
|
||||
if ! command -v uname; then
|
||||
echo "Error 'uname' command not found, could not get platform/arch data."
|
||||
print_install_results_and_exit 1
|
||||
echo "Error 'uname' command not found, could not get platform/arch data."
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
|
||||
KERNEL="$(uname -s)"
|
||||
case $KERNEL in
|
||||
Darwin)
|
||||
PLATFORM="darwin"
|
||||
;;
|
||||
Linux)
|
||||
PLATFORM="linux"
|
||||
;;
|
||||
FreeBSD)
|
||||
PLATFORM="freebsd"
|
||||
;;
|
||||
DragonFly)
|
||||
PLATFORM="dragonfly"
|
||||
;;
|
||||
"")
|
||||
echo "Error uname -s yields empty result"
|
||||
print_install_results_and_exit 1
|
||||
;;
|
||||
*)
|
||||
echo "Error platform not supported: $KERNEL"
|
||||
print_install_results_and_exit 1
|
||||
;;
|
||||
Darwin)
|
||||
PLATFORM="darwin"
|
||||
;;
|
||||
Linux)
|
||||
PLATFORM="linux"
|
||||
;;
|
||||
FreeBSD)
|
||||
PLATFORM="freebsd"
|
||||
;;
|
||||
DragonFly)
|
||||
PLATFORM="dragonfly"
|
||||
;;
|
||||
"")
|
||||
echo "Error uname -s yields empty result"
|
||||
print_install_results_and_exit 1
|
||||
;;
|
||||
*)
|
||||
echo "Error platform not supported: $KERNEL"
|
||||
print_install_results_and_exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check machine architecture
|
||||
ARCH="$(uname -m)"
|
||||
case $ARCH in
|
||||
x86_64 | amd64)
|
||||
SERVER_ARCH="x64"
|
||||
;;
|
||||
armv7l | armv8l)
|
||||
SERVER_ARCH="armhf"
|
||||
;;
|
||||
arm64 | aarch64)
|
||||
SERVER_ARCH="arm64"
|
||||
;;
|
||||
ppc64le)
|
||||
SERVER_ARCH="ppc64le"
|
||||
;;
|
||||
riscv64)
|
||||
SERVER_ARCH="riscv64"
|
||||
;;
|
||||
loongarch64)
|
||||
SERVER_ARCH="loong64"
|
||||
;;
|
||||
s390x)
|
||||
SERVER_ARCH="s390x"
|
||||
;;
|
||||
*)
|
||||
echo "Error architecture not supported: $ARCH"
|
||||
print_install_results_and_exit 1
|
||||
;;
|
||||
x86_64 | amd64)
|
||||
SERVER_ARCH="x64"
|
||||
;;
|
||||
armv7l | armv8l)
|
||||
SERVER_ARCH="armhf"
|
||||
;;
|
||||
arm64 | aarch64)
|
||||
SERVER_ARCH="arm64"
|
||||
;;
|
||||
ppc64le)
|
||||
SERVER_ARCH="ppc64le"
|
||||
;;
|
||||
riscv64)
|
||||
SERVER_ARCH="riscv64"
|
||||
;;
|
||||
loongarch64)
|
||||
SERVER_ARCH="loong64"
|
||||
;;
|
||||
s390x)
|
||||
SERVER_ARCH="s390x"
|
||||
;;
|
||||
*)
|
||||
echo "Error architecture not supported: $ARCH"
|
||||
print_install_results_and_exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# https://www.freedesktop.org/software/systemd/man/os-release.html
|
||||
OS_RELEASE_ID="$(grep -i '^ID=' /etc/os-release 2>/dev/null | sed 's/^ID=//gi' | sed 's/"//g')"
|
||||
if [[ -z $OS_RELEASE_ID ]]; then
|
||||
OS_RELEASE_ID="$(grep -i '^ID=' /usr/lib/os-release 2>/dev/null | sed 's/^ID=//gi' | sed 's/"//g')"
|
||||
if [[ -z $OS_RELEASE_ID ]]; then
|
||||
OS_RELEASE_ID="unknown"
|
||||
fi
|
||||
OS_RELEASE_ID="$(grep -i '^ID=' /usr/lib/os-release 2>/dev/null | sed 's/^ID=//gi' | sed 's/"//g')"
|
||||
if [[ -z $OS_RELEASE_ID ]]; then
|
||||
OS_RELEASE_ID="unknown"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create installation folder
|
||||
if [[ ! -d $SERVER_DIR ]]; then
|
||||
mkdir -p $SERVER_DIR
|
||||
if (( $? > 0 )); then
|
||||
echo "Error creating server install directory"
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
mkdir -p $SERVER_DIR
|
||||
if (( $? > 0 )); then
|
||||
echo "Error creating server install directory"
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# adjust platform for vscodium download, if needed
|
||||
if [[ $OS_RELEASE_ID = alpine ]]; then
|
||||
PLATFORM=$OS_RELEASE_ID
|
||||
PLATFORM=$OS_RELEASE_ID
|
||||
fi
|
||||
|
||||
SERVER_DOWNLOAD_URL="$(echo "%%SERVER_DOWNLOAD_URL_TEMPLATE%%" | sed "s/\${quality}/$DISTRO_QUALITY/g" | sed "s/\${version}/$DISTRO_VERSION/g" | sed "s/\${commit}/$DISTRO_COMMIT/g" | sed "s/\${os}/$PLATFORM/g" | sed "s/\${arch}/$SERVER_ARCH/g" | sed "s/\${release}/$DISTRO_VSCODIUM_RELEASE/g")"
|
||||
|
||||
# Check if server script is already installed
|
||||
if [[ ! -f $SERVER_SCRIPT ]]; then
|
||||
case "$PLATFORM" in
|
||||
darwin | linux | alpine | freebsd )
|
||||
;;
|
||||
*)
|
||||
echo "Error '$PLATFORM' needs manual installation of remote extension host"
|
||||
print_install_results_and_exit 1
|
||||
;;
|
||||
esac
|
||||
case "$PLATFORM" in
|
||||
darwin | linux | alpine | freebsd )
|
||||
;;
|
||||
*)
|
||||
echo "Error '$PLATFORM' needs manual installation of remote extension host"
|
||||
print_install_results_and_exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
pushd $SERVER_DIR > /dev/null
|
||||
pushd $SERVER_DIR > /dev/null
|
||||
|
||||
if command -v wget >/dev/null 2>&1; then
|
||||
wget --tries=3 --timeout=10 --continue --no-verbose -O vscode-server.tar.gz $SERVER_DOWNLOAD_URL
|
||||
elif command -v curl >/dev/null 2>&1; then
|
||||
curl --retry 3 --connect-timeout 10 --location --show-error --silent --output vscode-server.tar.gz $SERVER_DOWNLOAD_URL
|
||||
elif command -v fetch >/dev/null 2>&1; then
|
||||
fetch --retry --timeout=10 --quiet --output=vscode-server.tar.gz $SERVER_DOWNLOAD_URL
|
||||
else
|
||||
echo "Error no tool to download server binary"
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
if command -v wget >/dev/null 2>&1; then
|
||||
wget --tries=3 --timeout=10 --continue --no-verbose -O vscode-server.tar.gz $SERVER_DOWNLOAD_URL
|
||||
elif command -v curl >/dev/null 2>&1; then
|
||||
curl --retry 3 --connect-timeout 10 --location --show-error --silent --output vscode-server.tar.gz $SERVER_DOWNLOAD_URL
|
||||
elif command -v fetch >/dev/null 2>&1; then
|
||||
fetch --retry --timeout=10 --quiet --output=vscode-server.tar.gz $SERVER_DOWNLOAD_URL
|
||||
else
|
||||
echo "Error no tool to download server binary"
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
|
||||
if (( $? > 0 )); then
|
||||
echo "Error downloading server from $SERVER_DOWNLOAD_URL"
|
||||
rm -rf vscode-server.tar.gz
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
if (( $? > 0 )); then
|
||||
echo "Error downloading server from $SERVER_DOWNLOAD_URL"
|
||||
rm -rf vscode-server.tar.gz
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
|
||||
tar -xf vscode-server.tar.gz --strip-components 1
|
||||
if (( $? > 0 )); then
|
||||
echo "Error while extracting server contents"
|
||||
rm -rf vscode-server.tar.gz
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
tar -xf vscode-server.tar.gz --strip-components 1
|
||||
if (( $? > 0 )); then
|
||||
echo "Error while extracting server contents"
|
||||
rm -rf vscode-server.tar.gz
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f $SERVER_SCRIPT ]]; then
|
||||
rm -rf $SERVER_DIR/*
|
||||
echo "Error server contents are corrupted"
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
if [[ ! -f $SERVER_SCRIPT ]]; then
|
||||
rm -rf $SERVER_DIR/*
|
||||
echo "Error server contents are corrupted"
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
|
||||
rm -f vscode-server.tar.gz
|
||||
rm -f vscode-server.tar.gz
|
||||
|
||||
popd > /dev/null
|
||||
popd > /dev/null
|
||||
else
|
||||
echo "Server script already installed in $SERVER_SCRIPT"
|
||||
echo "Server script already installed in $SERVER_SCRIPT"
|
||||
fi
|
||||
|
||||
# Modify the commit in the remote server to match the local value
|
||||
if %%MODIFY_PRODUCT_JSON%%; then
|
||||
if command -v sed >/dev/null 2>&1; then
|
||||
echo "Will modify product.json on remote to match the commit value"
|
||||
sed -i -E 's/"commit": "[0-9a-f]+",/"commit": "'"$DISTRO_COMMIT"'",/' "$SERVER_DIR/product.json";
|
||||
else
|
||||
echo "Cannot find the 'sed' command, make sure it is installed to modify product.json with the matching commit."
|
||||
fi
|
||||
if command -v sed >/dev/null 2>&1; then
|
||||
echo "Will modify product.json on remote to match the commit value"
|
||||
sed -i -E 's/"commit": "[0-9a-f]+",/"commit": "'"$DISTRO_COMMIT"'",/' "$SERVER_DIR/product.json";
|
||||
else
|
||||
echo "Cannot find the 'sed' command, make sure it is installed to modify product.json with the matching commit."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Try to find if server is already running
|
||||
if [[ -f $SERVER_PIDFILE ]]; then
|
||||
SERVER_PID="$(cat $SERVER_PIDFILE)"
|
||||
SERVER_RUNNING_PROCESS="$(ps -o pid,args -p $SERVER_PID | grep $SERVER_SCRIPT)"
|
||||
SERVER_PID="$(cat $SERVER_PIDFILE)"
|
||||
SERVER_RUNNING_PROCESS="$(ps -o pid,args -p $SERVER_PID | grep $SERVER_SCRIPT)"
|
||||
else
|
||||
SERVER_RUNNING_PROCESS="$(ps -o pid,args -A | grep $SERVER_SCRIPT | grep -v grep)"
|
||||
SERVER_RUNNING_PROCESS="$(ps -o pid,args -A | grep $SERVER_SCRIPT | grep -v grep)"
|
||||
fi
|
||||
|
||||
if [[ -z $SERVER_RUNNING_PROCESS ]]; then
|
||||
if [[ -f $SERVER_LOGFILE ]]; then
|
||||
rm $SERVER_LOGFILE
|
||||
fi
|
||||
if [[ -f $SERVER_TOKENFILE ]]; then
|
||||
rm $SERVER_TOKENFILE
|
||||
fi
|
||||
if [[ -f $SERVER_LOGFILE ]]; then
|
||||
rm $SERVER_LOGFILE
|
||||
fi
|
||||
if [[ -f $SERVER_TOKENFILE ]]; then
|
||||
rm $SERVER_TOKENFILE
|
||||
fi
|
||||
|
||||
touch $SERVER_TOKENFILE
|
||||
chmod 600 $SERVER_TOKENFILE
|
||||
SERVER_CONNECTION_TOKEN="%%SERVER_CONNECTION_TOKEN%%"
|
||||
echo $SERVER_CONNECTION_TOKEN > $SERVER_TOKENFILE
|
||||
touch $SERVER_TOKENFILE
|
||||
chmod 600 $SERVER_TOKENFILE
|
||||
SERVER_CONNECTION_TOKEN="%%SERVER_CONNECTION_TOKEN%%"
|
||||
echo $SERVER_CONNECTION_TOKEN > $SERVER_TOKENFILE
|
||||
|
||||
$SERVER_SCRIPT --start-server --host=127.0.0.1 $SERVER_LISTEN_FLAG $SERVER_DATA_DIR_FLAG $SERVER_VALIDATION_FLAG $SERVER_INITIAL_EXTENSIONS --connection-token-file $SERVER_TOKENFILE --telemetry-level off --enable-remote-auto-shutdown --accept-server-license-terms &> $SERVER_LOGFILE &
|
||||
echo $! > $SERVER_PIDFILE
|
||||
$SERVER_SCRIPT --start-server --host=127.0.0.1 $SERVER_LISTEN_FLAG $SERVER_DATA_DIR_FLAG $SERVER_VALIDATION_FLAG $SERVER_INITIAL_EXTENSIONS --connection-token-file $SERVER_TOKENFILE --telemetry-level off --enable-remote-auto-shutdown --accept-server-license-terms &> $SERVER_LOGFILE &
|
||||
echo $! > $SERVER_PIDFILE
|
||||
else
|
||||
echo "Server script is already running $SERVER_SCRIPT"
|
||||
echo "Server script is already running $SERVER_SCRIPT"
|
||||
fi
|
||||
|
||||
if [[ -f $SERVER_TOKENFILE ]]; then
|
||||
SERVER_CONNECTION_TOKEN="$(cat $SERVER_TOKENFILE)"
|
||||
SERVER_CONNECTION_TOKEN="$(cat $SERVER_TOKENFILE)"
|
||||
else
|
||||
echo "Error server token file not found $SERVER_TOKENFILE"
|
||||
print_install_results_and_exit 1
|
||||
echo "Error server token file not found $SERVER_TOKENFILE"
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
|
||||
if [[ -f $SERVER_LOGFILE ]]; then
|
||||
for i in {1..35}; do
|
||||
LISTENING_ON="$(cat $SERVER_LOGFILE | grep -E 'Extension host agent listening on .+' | sed 's/Extension host agent listening on //')"
|
||||
if [[ -n $LISTENING_ON ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
if [[ -z $LISTENING_ON ]]; then
|
||||
echo "Error server did not start successfully"
|
||||
print_install_results_and_exit 1
|
||||
for i in {1..35}; do
|
||||
LISTENING_ON="$(cat $SERVER_LOGFILE | grep -E 'Extension host agent listening on .+' | sed 's/Extension host agent listening on //')"
|
||||
if [[ -n $LISTENING_ON ]]; then
|
||||
break
|
||||
fi
|
||||
else
|
||||
echo "Error server log file not found $SERVER_LOGFILE"
|
||||
sleep 0.5
|
||||
done
|
||||
|
||||
if [[ -z $LISTENING_ON ]]; then
|
||||
echo "Error server did not start successfully"
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
else
|
||||
echo "Error server log file not found $SERVER_LOGFILE"
|
||||
print_install_results_and_exit 1
|
||||
fi
|
||||
|
||||
# Finish server setup
|
||||
|
||||
+33
-33
@@ -25,32 +25,32 @@ function compileTemplate(templateName: string, variables: Record<string, string>
|
||||
* Returns -1 if no match.
|
||||
*/
|
||||
function matchHostnamePattern(hostname: string, pattern: string): number {
|
||||
// Exact match has highest priority
|
||||
if (hostname === pattern) {
|
||||
return 1000;
|
||||
}
|
||||
// Exact match has highest priority
|
||||
if (hostname === pattern) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
// Catch-all wildcard has lowest priority
|
||||
if (pattern === '*') {
|
||||
return 1;
|
||||
}
|
||||
// Catch-all wildcard has lowest priority
|
||||
if (pattern === '*') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Convert wildcard pattern to regex
|
||||
// Escape special regex characters except *
|
||||
const regexPattern = pattern
|
||||
.replace(/[.+?^${}()|[\]\\]/g, '\\$&')
|
||||
.replace(/\*/g, '.*');
|
||||
// Convert wildcard pattern to regex
|
||||
// Escape special regex characters except *
|
||||
const regexPattern = pattern
|
||||
.replace(/[.+?^${}()|[\]\\]/g, '\\$&')
|
||||
.replace(/\*/g, '.*');
|
||||
|
||||
const regex = new RegExp(`^${regexPattern}$`);
|
||||
const regex = new RegExp(`^${regexPattern}$`);
|
||||
|
||||
if (regex.test(hostname)) {
|
||||
// Calculate specificity based on the number of non-wildcard characters
|
||||
// More specific patterns (more characters) get higher scores
|
||||
const nonWildcardChars = pattern.replace(/\*/g, '').length;
|
||||
return 10 + nonWildcardChars;
|
||||
}
|
||||
if (regex.test(hostname)) {
|
||||
// Calculate specificity based on the number of non-wildcard characters
|
||||
// More specific patterns (more characters) get higher scores
|
||||
const nonWildcardChars = pattern.replace(/\*/g, '').length;
|
||||
return 10 + nonWildcardChars;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,19 +58,19 @@ function matchHostnamePattern(hostname: string, pattern: string): number {
|
||||
* Supports wildcards with priority: exact match > specific wildcard > general wildcard.
|
||||
*/
|
||||
export function findServerInstallPath(hostname: string, pathMap: Record<string, string>): string | undefined {
|
||||
let bestMatch: { pattern: string; path: string; score: number } | undefined;
|
||||
let bestMatch: { pattern: string; path: string; score: number } | undefined;
|
||||
|
||||
for (const [pattern, path] of Object.entries(pathMap)) {
|
||||
const score = matchHostnamePattern(hostname, pattern);
|
||||
for (const [pattern, path] of Object.entries(pathMap)) {
|
||||
const score = matchHostnamePattern(hostname, pattern);
|
||||
|
||||
if (score > 0) {
|
||||
if (!bestMatch || score > bestMatch.score) {
|
||||
bestMatch = { pattern, path, score };
|
||||
}
|
||||
}
|
||||
}
|
||||
if (score > 0) {
|
||||
if (!bestMatch || score > bestMatch.score) {
|
||||
bestMatch = { pattern, path, score };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestMatch?.path;
|
||||
return bestMatch?.path;
|
||||
}
|
||||
|
||||
export type ServerInstallOptions = {
|
||||
@@ -186,7 +186,7 @@ export async function installCodeServer(
|
||||
|
||||
// investigate if it's possible to use `-EncodedCommand` flag
|
||||
// https://devblogs.microsoft.com/powershell/invoking-powershell-with-complex-expressions-using-scriptblocks/
|
||||
// eslint-disable-next-line no-useless-assignment
|
||||
// eslint-disable-next-line no-useless-assignment
|
||||
let command = '';
|
||||
|
||||
if (shell === 'powershell') {
|
||||
@@ -300,7 +300,7 @@ function generateBashInstallScript({ id, quality, version, commit, release, exte
|
||||
const listenFlag = useSocketPath
|
||||
? `--socket-path="$TMP_DIR/vscode-server-sock-${crypto.randomUUID()}"`
|
||||
: '--port=0';
|
||||
const envVarLines = envVariables.map(envVar => ` echo "${envVar}==$${envVar}=="`).join('\n');
|
||||
const envVarLines = envVariables.map(envVar => ` echo "${envVar}==$${envVar}=="`).join('\n');
|
||||
|
||||
return compileTemplate('server-setup.sh', {
|
||||
DISTRO_VERSION: version,
|
||||
|
||||
@@ -10,14 +10,14 @@ import { glob } from 'glob';
|
||||
// Only a few directives might return an array
|
||||
// https://github.com/cyjake/ssh-config/blob/master/src/ssh-config.ts#L10
|
||||
export type HostConfiguration = {
|
||||
CanonicalDomains?: string | string[];
|
||||
GlobalKnownHostsFile?: string | string[];
|
||||
Host?: string | string[];
|
||||
IPQoS?: string | string[];
|
||||
Match?: string | string[];
|
||||
ProxyCommand?: string | string[];
|
||||
SendEnv?: string | string[];
|
||||
UserKnownHostsFile?: string | string[];
|
||||
CanonicalDomains?: string | string[];
|
||||
GlobalKnownHostsFile?: string | string[];
|
||||
Host?: string | string[];
|
||||
IPQoS?: string | string[];
|
||||
Match?: string | string[];
|
||||
ProxyCommand?: string | string[];
|
||||
SendEnv?: string | string[];
|
||||
UserKnownHostsFile?: string | string[];
|
||||
} & Record<string, string>;
|
||||
|
||||
const systemSSHConfig = isWindows ? path.resolve(process.env.ALLUSERSPROFILE || 'C:\\ProgramData', 'ssh\\ssh_config') : '/etc/ssh/ssh_config';
|
||||
|
||||
@@ -44,7 +44,7 @@ export default class SSHDestination {
|
||||
const data = JSON.parse(Buffer.from(dest, 'hex').toString());
|
||||
return new SSHDestination(data.hostName, data.user, data.port);
|
||||
} catch {
|
||||
// ignore
|
||||
// ignore
|
||||
}
|
||||
|
||||
return SSHDestination.parse(dest.replace(/\\x([0-9a-f]{2})/g, (_, charCode) => String.fromCharCode(parseInt(charCode, 16))));
|
||||
|
||||
+38
-38
@@ -7,46 +7,46 @@ const webpack = require('webpack');
|
||||
|
||||
/**@type {import('webpack').Configuration}*/
|
||||
const config = {
|
||||
target: 'node',
|
||||
entry: './src/extension.ts',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'lib'),
|
||||
filename: 'extension.js',
|
||||
libraryTarget: "commonjs2",
|
||||
devtoolModuleFilenameTemplate: "../[resource-path]",
|
||||
},
|
||||
devtool: 'source-map',
|
||||
externals: {
|
||||
vscode: "commonjs vscode",
|
||||
bufferutil: "bufferutil",
|
||||
"utf-8-validate": "utf-8-validate",
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
use: [{
|
||||
loader: 'ts-loader'
|
||||
}]
|
||||
}]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.IgnorePlugin({
|
||||
resourceRegExp: /crypto\/build\/Release\/sshcrypto\.node$/,
|
||||
}),
|
||||
new webpack.IgnorePlugin({
|
||||
resourceRegExp: /cpu-features/,
|
||||
})
|
||||
]
|
||||
target: 'node',
|
||||
entry: './src/extension.ts',
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'lib'),
|
||||
filename: 'extension.js',
|
||||
libraryTarget: "commonjs2",
|
||||
devtoolModuleFilenameTemplate: "../[resource-path]",
|
||||
},
|
||||
devtool: 'source-map',
|
||||
externals: {
|
||||
vscode: "commonjs vscode",
|
||||
bufferutil: "bufferutil",
|
||||
"utf-8-validate": "utf-8-validate",
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.ts$/,
|
||||
exclude: /node_modules/,
|
||||
use: [{
|
||||
loader: 'ts-loader'
|
||||
}]
|
||||
}]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.IgnorePlugin({
|
||||
resourceRegExp: /crypto\/build\/Release\/sshcrypto\.node$/,
|
||||
}),
|
||||
new webpack.IgnorePlugin({
|
||||
resourceRegExp: /cpu-features/,
|
||||
})
|
||||
]
|
||||
}
|
||||
|
||||
module.exports = (_env, argv) => {
|
||||
if (argv.mode === 'production') {
|
||||
config.devtool = false;
|
||||
}
|
||||
if (argv.mode === 'production') {
|
||||
config.devtool = false;
|
||||
}
|
||||
|
||||
return config;
|
||||
return config;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user