Skip to main content

poe_data_tools_cli/commands/
extract.rs

1use std::{
2    fs::{self},
3    path::Path,
4};
5
6use anyhow::{Context, Result};
7use glob::{MatchOptions, Pattern};
8use poe_data_tools::fs::{FS, FileSystem};
9
10/// Extract files to disk matching a glob pattern
11pub fn extract_files(fs: &mut FS, patterns: &[Pattern], output_folder: &Path) -> Result<()> {
12    let filenames = fs
13        .list()
14        .filter(|filename| {
15            patterns.iter().any(|pattern| {
16                pattern.matches_with(
17                    filename,
18                    MatchOptions {
19                        require_literal_separator: true,
20                        ..Default::default()
21                    },
22                )
23            })
24        })
25        .collect::<Vec<_>>();
26
27    fs.batch_read(&filenames)
28        // Print and filter out errors
29        .filter_map(|(path, res)| match res {
30            Ok(b) => Some((path, b)),
31            Err(e) => {
32                log::error!("Failed to extract file: {:?}: {:?}", path, e);
33                None
34            }
35        })
36        // Attempt to read file contents
37        .map(|(filename, contents)| -> Result<_, anyhow::Error> {
38            let out_filename = output_folder.join(filename.as_ref());
39            fs::create_dir_all(out_filename.parent().unwrap()).with_context(|| {
40                format!(
41                    "Failed to create folder: {:?}",
42                    out_filename.parent().unwrap()
43                )
44            })?;
45
46            fs::write(&out_filename, &contents)
47                .with_context(|| format!("Failed to write file: {:?}", out_filename))?;
48
49            Ok(filename)
50        })
51        // Report results
52        .for_each(|result| match result {
53            Ok(filename) => log::info!("Extracted file: {}", filename),
54            Err(e) => log::error!("Failed to extract file: {:?}", e),
55        });
56
57    Ok(())
58}