hexz_cli/cmd/data/
pack.rs1use crate::ui::progress::create_progress_bar;
4use anyhow::Result;
5use colored::Colorize;
6use hexz_ops::pack::{PackAnalysisFlags, PackConfig, PackTransformFlags, pack_archive};
7use std::path::PathBuf;
8use std::sync::{Arc, Mutex};
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!(
55 "{} Packing {}",
56 "╭".dimmed(),
57 output.display().to_string().cyan()
58 );
59 println!(
60 "{} Input {}",
61 "│".dimmed(),
62 input_path.display().to_string().bright_black()
63 );
64 if let Some(ref b) = base {
65 println!(
66 "{} Base {}",
67 "│".dimmed(),
68 b.display().to_string().bright_black()
69 );
70 }
71 println!("{}", "╰".dimmed());
72 }
73
74 let pb = if silent {
76 None
77 } else {
78 let pb = create_progress_bar(total_size);
79 Some(Arc::new(Mutex::new(pb)))
80 };
81 let pb_clone = pb.clone();
82
83 if train_dict && !silent {
84 println!(" {} Training compression dictionary...", "→".yellow());
85 }
86
87 let config = PackConfig {
89 input: input_path,
90 base,
91 output,
92 compression,
93 password,
94 block_size,
95 min_chunk,
96 avg_chunk,
97 max_chunk,
98 num_workers: workers.unwrap_or(0),
99 transform: PackTransformFlags {
100 encrypt,
101 train_dict,
102 parallel: workers != Some(1),
103 },
104 analysis: PackAnalysisFlags {
105 show_progress: true,
106 use_dcam: dcam,
107 dcam_optimal,
108 },
109 };
110
111 let cb = move |current: u64, _: u64| {
113 if let Some(ref pb) = pb_clone {
114 if let Ok(pb) = pb.lock() {
115 pb.set_position(current);
116 }
117 }
118 };
119 pack_archive(&config, Some(&cb))?;
120
121 if let Some(ref pb) = pb {
122 if let Ok(pb) = pb.lock() {
123 pb.finish_with_message("Done");
124 }
125 }
126
127 if !silent {
128 println!("\n {} Archive created.", "✓".green());
129 }
130 Ok(())
131}