Skip to main content

mc_repack_core/
fop.rs

1use std::collections::HashSet;
2
3use crate::{errors::FileIgnoreError, ext, min::Minifier};
4
5/// A file operation needed before a file is saved in repacked archive
6#[derive(Clone)]
7pub enum FileOp {
8    /// Pass a file (no operation needed).
9    Pass,
10    /// Recompress data (check minimal size to determine if a file can be compressed or not).
11    Recompress(u8),
12    /// Minify a file.
13    Minify(Minifier),
14    /// Ignore a file and return an error.
15    Ignore(FileIgnoreError),
16}
17
18impl FileOp {
19    pub(crate) fn by_name(fname: &str, blacklist: &TypeBlacklist) -> Self {
20        if fname.starts_with(".cache/") { return Self::Ignore(FileIgnoreError::Blacklisted) }
21        if let Some(sub) =  fname.strip_prefix("META-INF/") {
22            match sub {
23                "SIGNFILE.SF" | "SIGNFILE.DSA" => { return Self::Ignore(FileIgnoreError::Signfile) }
24                x if x.starts_with("SIG-") || [".DSA", ".RSA", ".SF"].into_iter().any(|e| x.ends_with(e)) => {
25                    return Self::Ignore(FileIgnoreError::Signfile)
26                }
27                x if x.starts_with("services/") => { return Self::Recompress(64) }
28                _ => {}
29            }
30        }
31        let Some((_, ftype)) = fname.rsplit_once('.') else {
32            return Self::Pass
33        };
34        if blacklist.can_ignore(ftype) {
35            return Self::Ignore(FileIgnoreError::Blacklisted)
36        }
37        ext::KnownFmt::by_extension(ftype)
38            .map_or(Self::Pass, |x| Minifier::by_file_format(x).map_or(Self::Pass, Self::Minify))
39    }
40}
41
42/// A blacklist of file types to ignore.
43/// It has built-in file types (if [`TypeBlacklist::Extend`] is used): `bak`, `blend`, `blend1`, `disabled`, `gitignore`, `gitkeep`, `lnk`, `old`, `pdn`, `psd`, `xcf`.
44pub enum TypeBlacklist {
45    /// Extend the blacklist. It uses a predefined list of file types that are not supposed to be repacked.
46    Extend(Option<HashSet<Box<str>>>),
47    /// Override the blacklist. You can define your own list of file types regardless of the predefined list.
48    Override(Option<HashSet<Box<str>>>)
49}
50impl TypeBlacklist {
51    fn can_ignore(&self, s: &str) -> bool {
52        let inner = match self {
53            Self::Extend(x) => {
54                if matches!(s, "bak" | "blend" | "blend1" | "disabled" | "gitignore" | "gitkeep" | "lnk" | "old" | "pdn" | "psd" | "xcf") {
55                    return true
56                }
57                x
58            }
59            Self::Override(x) => x
60        };
61        inner.as_ref().map_or(false, |x| x.contains(s))
62    }
63}