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 for filter_rule in f.split(',') {
43 cmd.args(["--filter", filter_rule.trim()]);
44 }
45 }
46
47 cmd.args([source, destination]);
48
49 let status = cmd.status().context("Failed to execute rsync command")?;
50
51 if !status.success() {
52 anyhow::bail!("rsync failed with exit code: {:?}", status.code());
53 }
54
55 Ok(())
56}
57
58pub fn execute_ssh_command(host: &str, command: &str) -> Result<()> {
59 let status = Command::new("ssh")
60 .arg(host)
61 .arg(command)
62 .status()
63 .context("Failed to execute SSH command")?;
64
65 if !status.success() {
66 anyhow::bail!("SSH command failed with exit code: {:?}", status.code());
67 }
68
69 Ok(())
70}
71
72pub fn open_remote_shell(host: &str, directory: &str) -> Result<()> {
73 let status = Command::new("ssh")
74 .arg("-t") .arg(host)
76 .arg(format!("cd {} && exec $SHELL -l", directory))
77 .status()
78 .context("Failed to open remote shell")?;
79
80 if !status.success() {
81 anyhow::bail!("Remote shell exited with code: {:?}", status.code());
82 }
83
84 Ok(())
85}