use anyhow::Result; use crate::{error::SkipStep, execution_context::ExecutionContext, terminal::print_separator, utils}; fn prepare_async_ssh_command(args: &mut Vec<&str>) { args.insert(0, "ssh"); args.push("--keep"); } pub fn ssh_step(ctx: &ExecutionContext, hostname: &str) -> Result<()> { let ssh = utils::require("ssh")?; let topgrade = ctx.config().remote_topgrade_path(); let mut args = vec!["-t", hostname]; if let Some(ssh_arguments) = ctx.config().ssh_arguments() { args.extend(ssh_arguments.split_whitespace()); } let env = format!("TOPGRADE_PREFIX={}", hostname); args.extend(["env", &env, "$SHELL", "-lc", topgrade]); if ctx.config().run_in_tmux() && !ctx.run_type().dry() { #[cfg(unix)] { prepare_async_ssh_command(&mut args); crate::tmux::run_command(ctx, &args.join(" "))?; Err(SkipStep(String::from("Remote Topgrade launched in Tmux")).into()) } #[cfg(not(unix))] unreachable!("Tmux execution is only implemented in Unix"); } else if ctx.config().open_remotes_in_new_terminal() && !ctx.run_type().dry() && cfg!(windows) { prepare_async_ssh_command(&mut args); ctx.run_type().execute("wt").args(&args).spawn()?; Err(SkipStep(String::from("Remote Topgrade launched in an external terminal")).into()) } else { let mut args = vec!["-t", hostname]; if let Some(ssh_arguments) = ctx.config().ssh_arguments() { args.extend(ssh_arguments.split_whitespace()); } let env = format!("TOPGRADE_PREFIX={}", hostname); args.extend(["env", &env, "$SHELL", "-lc", topgrade]); print_separator(format!("Remote ({})", hostname)); println!("Connecting to {}...", hostname); ctx.run_type().execute(&ssh).args(&args).check_run() } }