mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-10-26 18:55:22 +00:00
feat: add pure ssh2 remote operations
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
export type EffectiveSshConfig = Map<string, string[]>;
|
||||
|
||||
export function parseSshG(text: string): EffectiveSshConfig {
|
||||
const values: EffectiveSshConfig = new Map();
|
||||
for (const line of text.split(/\r?\n/)) {
|
||||
const separator = line.indexOf(" ");
|
||||
if (separator < 1) continue;
|
||||
const key = line.slice(0, separator).trim().toLowerCase();
|
||||
const value = line.slice(separator + 1).trim();
|
||||
if (!key || !value) continue;
|
||||
const current = values.get(key) ?? [];
|
||||
current.push(value);
|
||||
values.set(key, current);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
export function resolveOpenSshAlias(alias: string): EffectiveSshConfig {
|
||||
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(alias)) throw new Error(`invalid SSH alias: ${alias}`);
|
||||
const output = execFileSync("ssh", ["-G", "--", alias], {
|
||||
encoding: "utf8",
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
});
|
||||
return parseSshG(output);
|
||||
}
|
||||
|
||||
export function effectiveValue(config: EffectiveSshConfig, key: string): string | undefined {
|
||||
return config.get(key.toLowerCase())?.at(-1);
|
||||
}
|
||||
|
||||
export function effectiveValues(config: EffectiveSshConfig, key: string): string[] {
|
||||
return config.get(key.toLowerCase()) ?? [];
|
||||
}
|
||||
|
||||
export function listDirectSshAliases(configPath = join(homedir(), ".ssh", "config")): string[] {
|
||||
if (!existsSync(configPath)) return [];
|
||||
const aliases: string[] = [];
|
||||
const text = readFileSync(configPath, "utf8");
|
||||
for (const line of text.split(/\r?\n/)) {
|
||||
const match = /^\s*Host\s+(.+?)\s*$/i.exec(line);
|
||||
if (!match) continue;
|
||||
for (const alias of match[1].split(/\s+/)) {
|
||||
if (!alias || alias.includes("*") || alias.includes("?") || alias.startsWith("!")) continue;
|
||||
if (!aliases.includes(alias)) aliases.push(alias);
|
||||
}
|
||||
}
|
||||
return aliases;
|
||||
}
|
||||
Reference in New Issue
Block a user