flodl_cli/util/
archive.rs1use std::path::Path;
6use std::process::{Command, Stdio};
7
8pub fn extract_zip(zip_path: &Path, dest_dir: &Path) -> Result<(), String> {
12 std::fs::create_dir_all(dest_dir)
13 .map_err(|e| format!("cannot create {}: {}", dest_dir.display(), e))?;
14
15 let zip_str = zip_path
16 .to_str()
17 .ok_or_else(|| "zip path is not valid UTF-8".to_string())?;
18 let dest_str = dest_dir
19 .to_str()
20 .ok_or_else(|| "destination path is not valid UTF-8".to_string())?;
21
22 let status = if cfg!(target_os = "windows") {
23 Command::new("powershell")
24 .args([
25 "-NoProfile",
26 "-Command",
27 &format!(
28 "Expand-Archive -Force -Path '{}' -DestinationPath '{}'",
29 zip_str, dest_str
30 ),
31 ])
32 .stdout(Stdio::null())
33 .stderr(Stdio::inherit())
34 .status()
35 } else {
36 if Command::new("unzip")
38 .arg("--help")
39 .stdout(Stdio::null())
40 .stderr(Stdio::null())
41 .status()
42 .is_err()
43 {
44 return Err("unzip is required but not installed.\n\
45 \n\
46 \x20 Ubuntu/Debian: sudo apt install unzip\n\
47 \x20 Fedora/RHEL: sudo dnf install unzip\n\
48 \x20 macOS: available by default"
49 .into());
50 }
51 Command::new("unzip")
52 .args(["-q", "-o", zip_str, "-d", dest_str])
53 .stdout(Stdio::null())
54 .stderr(Stdio::inherit())
55 .status()
56 };
57
58 match status {
59 Ok(s) if s.success() => Ok(()),
60 Ok(s) => Err(format!(
61 "extraction failed (exit code {})\n Archive: {}",
62 s.code().unwrap_or(-1),
63 zip_path.display()
64 )),
65 Err(e) => Err(format!("failed to run extraction command: {}", e)),
66 }
67}