hexz_cli/cmd/data/
pack.rs1use crate::ui::progress::create_progress_bar;
4use anyhow::Result;
5use hexz_ops::pack::{PackConfig, PackAnalysisFlags, PackTransformFlags, pack_archive};
6use std::path::PathBuf;
7use std::sync::{Arc, Mutex};
8use colored::Colorize;
9
10#[allow(clippy::too_many_arguments, clippy::fn_params_excessive_bools)]
12pub fn run(
13 input: Option<PathBuf>,
14 base: Option<PathBuf>,
15 output: PathBuf,
16 compression: String,
17 encrypt: bool,
18 train_dict: bool,
19 block_size: u32,
20 min_chunk: Option<u32>,
21 avg_chunk: Option<u32>,
22 max_chunk: Option<u32>,
23 workers: Option<usize>,
24 dcam: bool,
25 dcam_optimal: bool,
26 silent: bool,
27) -> Result<()> {
28 let password = if encrypt {
30 Some(match std::env::var("HEXZ_PASSWORD") {
31 Ok(p) => p,
32 Err(_) => rpassword::prompt_password("Enter encryption password: ")?,
33 })
34 } else {
35 None
36 };
37
38 let input_path = input.unwrap_or_else(|| PathBuf::from("."));
39
40 let total_size = if input_path.is_dir() {
42 walkdir::WalkDir::new(&input_path)
43 .into_iter()
44 .filter_map(std::result::Result::ok)
45 .filter(|e: &walkdir::DirEntry| e.file_type().is_file())
46 .map(|e: walkdir::DirEntry| e.metadata().map_or(0, |m| m.len()))
47 .sum()
48 } else {
49 std::fs::metadata(&input_path).map_or(0, |m| m.len())
50 };
51
52 if !silent {
54 println!("{} Packing {}", "╭".dimmed(), output.display().to_string().cyan());
55 println!("{} Input {}", "│".dimmed(), input_path.display().to_string().bright_black());
56 if let Some(ref b) = base {
57 println!("{} Base {}", "│".dimmed(), b.display().to_string().bright_black());
58 }
59 println!("{}", "╰".dimmed());
60 }
61
62 let pb = if silent {
64 None
65 } else {
66 let pb = create_progress_bar(total_size);
67 Some(Arc::new(Mutex::new(pb)))
68 };
69 let pb_clone = pb.clone();
70
71 if train_dict && !silent {
72 println!(" {} Training compression dictionary...", "→".yellow());
73 }
74
75 let config = PackConfig {
77 input: input_path,
78 base,
79 output,
80 compression,
81 password,
82 block_size,
83 min_chunk,
84 avg_chunk,
85 max_chunk,
86 num_workers: workers.unwrap_or(0),
87 transform: PackTransformFlags {
88 encrypt,
89 train_dict,
90 parallel: workers != Some(1),
91 },
92 analysis: PackAnalysisFlags {
93 show_progress: true,
94 use_dcam: dcam,
95 dcam_optimal,
96 },
97 };
98
99 let cb = move |current: u64, _: u64| {
101 if let Some(ref pb) = pb_clone {
102 if let Ok(pb) = pb.lock() {
103 pb.set_position(current);
104 }
105 }
106 };
107 pack_archive(&config, Some(&cb))?;
108
109 if let Some(ref pb) = pb {
110 if let Ok(pb) = pb.lock() {
111 pb.finish_with_message("Done");
112 }
113 }
114
115 if !silent {
116 println!("\n {} Archive created.", "✓".green());
117 }
118 Ok(())
119}