1use anyhow::{Context, Result};
2use std::process::Command;
3
4pub fn get_remote_home(remote_host: &str) -> Result<String> {
5 let output = Command::new("ssh")
6 .arg(remote_host)
7 .arg("echo $HOME")
8 .output()
9 .context("Failed to get remote home directory")?;
10
11 if !output.status.success() {
12 anyhow::bail!(
13 "SSH command failed: {}",
14 String::from_utf8_lossy(&output.stderr)
15 );
16 }
17
18 let home = String::from_utf8(output.stdout)?.trim().to_string();
19
20 if home.is_empty() {
21 anyhow::bail!("Remote home directory is empty");
22 }
23
24 Ok(home)
25}
26
27pub fn sync_directory(
28 source: &str,
29 destination: &str,
30 filter: Option<&str>,
31 delete: bool,
32) -> Result<()> {
33 let mut cmd = Command::new("rsync");
34 cmd.args(["-azP"]);
35
36 if delete {
37 cmd.args(["--delete"]);
38 }
39
40 if let Some(f) = filter {
41 cmd.args(["--filter", f]);
42 }
43
44 cmd.args([source, destination]);
45
46 let status = cmd.status().context("Failed to execute rsync command")?;
47
48 if !status.success() {
49 anyhow::bail!("rsync failed with exit code: {:?}", status.code());
50 }
51
52 Ok(())
53}
54
55pub fn execute_ssh_command(host: &str, command: &str) -> Result<()> {
56 let status = Command::new("ssh")
57 .arg(host)
58 .arg(command)
59 .status()
60 .context("Failed to execute SSH command")?;
61
62 if !status.success() {
63 anyhow::bail!("SSH command failed with exit code: {:?}", status.code());
64 }
65
66 Ok(())
67}
68
69pub fn open_remote_shell(host: &str, directory: &str) -> Result<()> {
70 let status = Command::new("ssh")
71 .arg("-t") .arg(host)
73 .arg(format!("cd {} && exec $SHELL -l", directory))
74 .status()
75 .context("Failed to open remote shell")?;
76
77 if !status.success() {
78 anyhow::bail!("Remote shell exited with code: {:?}", status.code());
79 }
80
81 Ok(())
82}