hexz_cli/cmd/data/
extract.rs1use anyhow::{Context, Result};
4use colored::Colorize;
5use hexz_core::format::header::Header;
6use hexz_core::format::magic::HEADER_SIZE;
7use hexz_ops::pack::extract_archive;
8use hexz_store::StorageBackend;
9use hexz_store::local::MmapBackend;
10use std::path::{Path, PathBuf};
11
12pub fn run(input: &Path, output: Option<PathBuf>) -> Result<()> {
14 let output = if let Some(p) = output {
16 p
17 } else {
18 let mut out = input.to_path_buf();
20 let _ = out.set_extension("");
21 out
22 };
23
24 let password = {
26 let backend = MmapBackend::new(input)?;
27 let header_bytes = backend.read_exact(0, HEADER_SIZE)?;
28 let header: Header = bincode::deserialize(&header_bytes)?;
29
30 if header.encryption.is_some() {
31 Some(match std::env::var("HEXZ_PASSWORD") {
32 Ok(p) => p,
33 Err(_) => rpassword::prompt_password("Enter decryption password: ")?,
34 })
35 } else {
36 None
37 }
38 };
39
40 println!(
41 "{} Extracting {}",
42 "╭".dimmed(),
43 input.display().to_string().cyan()
44 );
45 println!(
46 "{} Output {}",
47 "╰".dimmed(),
48 output.display().to_string().bright_black()
49 );
50
51 extract_archive(input, &output, password).context("Failed to extract archive")?;
52
53 println!("\n {} Extraction complete.", "✓".green());
54
55 Ok(())
56}