Files
herdr/src/remote.rs
Can Celik 2863b71513 feat(windows): support remote attach to unix hosts (#2329)
* feat(windows): support remote attach to unix hosts

* fix(remote): preserve unix bridge behavior
2026-08-05 19:34:24 +03:00

90 lines
2.4 KiB
Rust

mod attach;
#[cfg(unix)]
mod host_unix;
pub(crate) use attach::*;
#[cfg(unix)]
pub(crate) use host_unix::run_remote_client_bridge;
#[cfg(windows)]
pub(crate) fn run_remote_client_bridge() -> std::io::Result<()> {
Err(std::io::Error::other(
"remote Windows hosts are not supported yet",
))
}
pub(crate) fn print_remote_error_hint(err: &std::io::Error, target: &str) {
if is_remote_auth_error(err) {
eprintln!(
"hint: verify SSH access first with `{}`.",
ssh_check_command(target)
);
eprintln!(
"hint: if your SSH key has a passphrase, load it into ssh-agent with `ssh-add` before running `herdr --remote`."
);
}
}
fn is_remote_auth_error(err: &std::io::Error) -> bool {
let message = err.to_string();
message.contains("Permission denied")
&& (message.contains("(publickey")
|| message.contains("(keyboard-interactive")
|| message.contains("(password"))
}
fn ssh_check_command(target: &str) -> String {
format!("ssh {}", shell_quote(target))
}
fn shell_quote(value: &str) -> String {
if !value.is_empty()
&& value.chars().all(|ch| {
ch.is_ascii_alphanumeric()
|| matches!(
ch,
'@' | '%' | '_' | '+' | '=' | ':' | ',' | '.' | '/' | '-'
)
})
{
return value.to_string();
}
format!("'{}'", value.replace('\'', "'\\''"))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn remote_auth_error_matches_ssh_auth_denied() {
let err = std::io::Error::other(
"remote platform detection failed: user@host: Permission denied (publickey).",
);
assert!(is_remote_auth_error(&err));
}
#[test]
fn remote_auth_error_matches_keyboard_interactive_denied() {
let err = std::io::Error::other(
"remote server status failed: user@host: Permission denied (keyboard-interactive).",
);
assert!(is_remote_auth_error(&err));
}
#[test]
fn remote_auth_error_ignores_non_auth_errors() {
let err = std::io::Error::other("remote platform detection failed: unsupported platform");
assert!(!is_remote_auth_error(&err));
}
#[test]
fn ssh_check_command_quotes_remote_target() {
assert_eq!(ssh_check_command("host name"), "ssh 'host name'");
}
}