packler/pipelines/assets/
images.rs1use super::AssetMetadata;
2use crate::PacklerConfig;
3use log::{debug, info, trace, warn};
4use serde::{Deserialize, Serialize};
5use std::path::PathBuf;
6use walkdir::WalkDir;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct ImageProcessOutput {
10 pub generated_at: u64,
11 pub source_dir: PathBuf,
12 pub files: Vec<AssetMetadata>,
13}
14
15pub fn process(config: &PacklerConfig) -> Result<Vec<AssetMetadata>, Box<dyn std::error::Error>> {
16 let images_dir = config.source_image_dir();
17
18 info!("IMG: Collecting all images metadata");
19 let images: Vec<AssetMetadata> = WalkDir::new(&images_dir)
20 .into_iter()
21 .filter_map(|entry| {
22 match entry {
23 Ok(entry) => {
24 if entry.path().is_file() {
25 let relative_path = entry
26 .path()
27 .strip_prefix(&config.assets_source_dir)
28 .unwrap();
29
30 debug!(
31 "IMG: {} (relative: {})",
32 entry.path().display(),
33 relative_path.display()
34 );
35
36 let image_content = std::fs::read(entry.path()).unwrap();
37 let hash = seahash::hash(&image_content);
38
39 let hashed_name = format!(
42 "{}-{:x}.{}",
43 relative_path.file_stem().unwrap().to_string_lossy(),
44 hash,
45 relative_path.extension().unwrap().to_string_lossy()
46 );
47
48 Some(AssetMetadata {
49 source_path: entry.path().to_owned(),
50 logical_path: relative_path.to_owned(),
51 processed_relative_path: relative_path.with_file_name(hashed_name),
52 hash,
53 })
54 } else {
55 trace!("{} is not a file. Skip", entry.path().display());
56 None
57 }
58 }
59 Err(e) => {
60 warn!("Could not walk into images: {e}");
61 None
62 }
63 }
64 })
65 .collect();
66
67 info!("IMG: Cleaning destination directory");
68 clean_dist_dir(config);
69
70 for image in images.iter() {
72 let dest_path = config.dist_dir.join(&image.processed_relative_path);
73
74 if let Some(dir) = dest_path
75 .parent() { std::fs::create_dir_all(dir).expect("Could not create final directory") }
76
77 std::fs::copy(&image.source_path, &dest_path).unwrap();
78 }
79
80 Ok(images)
81}
82
83pub fn clean_dist_dir(cfg: &PacklerConfig) {
84 let images_dir = cfg.dist_image_dir();
85
86 if images_dir.exists() {
87 std::fs::remove_dir_all(&images_dir)
88 .unwrap_or_else(|_| panic!("Could not remove '{}'", images_dir.display()))
89 }
90}