use anyhow::Result;
pub fn expand_path(path: &str, target_user: &str, remote_home: Option<&str>) -> Result<String> {
let mut expanded = path.to_string();
if expanded.starts_with("~/") {
let fallback_home = format!("/home/{}", target_user);
let home = remote_home.unwrap_or(&fallback_home);
expanded = format!("{}{}", home, &expanded[1..]);
} else if expanded.starts_with('~') && expanded.len() > 1 {
if let Some(slash_pos_in_substring) = expanded[1..].find('/') {
let actual_slash_pos = slash_pos_in_substring + 1; let user = &expanded[1..actual_slash_pos]; let rest = &expanded[actual_slash_pos + 1..]; expanded = format!("/home/{}/{}", user, rest);
} else {
let user = &expanded[1..];
expanded = format!("/home/{}", user);
}
}
if expanded.contains('$') {
expanded = expand_variables(&expanded, target_user, remote_home)?;
}
Ok(expanded)
}
fn expand_variables(path: &str, target_user: &str, remote_home: Option<&str>) -> Result<String> {
let mut result = path.to_string();
let fallback_home = format!("/home/{}", target_user);
let home = remote_home.unwrap_or(&fallback_home);
let replacements = vec![
("$HOME", home.to_string()),
("$USER", target_user.to_string()),
("$USERNAME", target_user.to_string()),
];
for (var, value) in replacements {
if result == var {
result = value; } else if result.contains(&format!("{}/", var)) {
result = result.replace(&format!("{}/", var), &format!("{}/", value));
}
}
Ok(result)
}