pub fn print(msg: &str, quiet_mode: bool) {
if !quiet_mode {
println!("{}", msg);
}
}
pub fn get_filename_from_url_or_default(url_str: &str, default_filename: &str) -> String {
if let Ok(parsed_url) = url::Url::parse(url_str) {
if let Some(segments) = parsed_url.path_segments() {
if let Some(last_segment) = segments.last() {
if !last_segment.is_empty() {
return last_segment.to_string();
}
}
}
}
default_filename.to_string()
}
pub fn resolve_output_path(output_arg: Option<String>, url: &str, default_name: &str) -> String {
if let Some(path_str) = output_arg {
let path = std::path::Path::new(&path_str);
if path.is_dir() {
let filename = get_filename_from_url_or_default(url, default_name);
path.join(filename).to_string_lossy().to_string()
} else {
path_str
}
} else {
get_filename_from_url_or_default(url, default_name)
}
}
pub fn is_extractable(path: &std::path::Path) -> bool {
let name = path
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("")
.to_lowercase();
name.ends_with(".zip")
|| name.ends_with(".tar.gz")
|| name.ends_with(".tgz")
|| name.ends_with(".tar.bz2")
|| name.ends_with(".tbz2")
|| name.ends_with(".tar.xz")
|| name.ends_with(".txz")
|| name.ends_with(".7z")
}
pub fn auto_extract(
path: &std::path::Path,
quiet: bool,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let path_str = path.to_str().ok_or("Invalid UTF-8 in path")?;
let dir_str = path
.parent()
.and_then(|d| d.to_str())
.filter(|s| !s.is_empty())
.unwrap_or(".");
let name = path
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("")
.to_lowercase();
let (cmd, args): (&str, Vec<String>) = if name.ends_with(".zip") {
(
"unzip",
vec![
"-o".into(),
path_str.into(),
"-d".into(),
dir_str.into(),
],
)
} else if name.ends_with(".tar.gz") || name.ends_with(".tgz") {
(
"tar",
vec![
"-xzf".into(),
path_str.into(),
"-C".into(),
dir_str.into(),
],
)
} else if name.ends_with(".tar.bz2") || name.ends_with(".tbz2") {
(
"tar",
vec![
"-xjf".into(),
path_str.into(),
"-C".into(),
dir_str.into(),
],
)
} else if name.ends_with(".tar.xz") || name.ends_with(".txz") {
(
"tar",
vec![
"-xJf".into(),
path_str.into(),
"-C".into(),
dir_str.into(),
],
)
} else if name.ends_with(".7z") {
(
"7z",
vec!["x".into(), path_str.into(), format!("-o{dir_str}")],
)
} else {
return Ok(());
};
if !quiet {
println!("Extracting {} …", path.display());
}
let status = std::process::Command::new(cmd)
.args(&args)
.status()
.map_err(|e| format!("Failed to run `{cmd}`: {e} — is it installed?"))?;
if !status.success() {
return Err(format!(
"`{cmd}`: extraction failed (exit {:?})",
status.code()
)
.into());
}
if !quiet {
println!("Extracted to: {dir_str}");
}
Ok(())
}