added abilty to ignore files in a mod

This commit is contained in:
2026-03-03 18:09:10 +01:00
parent f2042be088
commit 63171acbe4
4 changed files with 74 additions and 1 deletions

24
Cargo.lock generated
View File

@@ -79,6 +79,16 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "bstr"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
dependencies = [
"memchr",
"serde",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.4" version = "1.0.4"
@@ -301,6 +311,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"env_logger", "env_logger",
"globset",
"libloot", "libloot",
"log", "log",
"quick-xml", "quick-xml",
@@ -320,6 +331,19 @@ dependencies = [
"wasi", "wasi",
] ]
[[package]]
name = "globset"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3"
dependencies = [
"aho-corasick",
"bstr",
"log",
"regex-automata",
"regex-syntax",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.14.5" version = "0.14.5"

View File

@@ -6,6 +6,7 @@ edition = "2024"
[dependencies] [dependencies]
clap = { version = "4.5.60", features = ["derive"] } clap = { version = "4.5.60", features = ["derive"] }
env_logger = "0.11.9" env_logger = "0.11.9"
globset = "0.4.18"
libloot = "0.29.0" libloot = "0.29.0"
log = "0.4.29" log = "0.4.29"
quick-xml = { version = "0.39.2", features = ["serde-types", "serialize"] } quick-xml = { version = "0.39.2", features = ["serde-types", "serialize"] }

View File

@@ -84,6 +84,14 @@ pub struct ModConfig {
/// Relative to the mod_location from root config /// Relative to the mod_location from root config
pub path: PathBuf, pub path: PathBuf,
/// If the files should be included on the root
#[serde(default)]
root_mod: bool,
/// Globs of what files to ignore
#[serde(default)]
ignore: Vec<String>,
} }
impl ModConfig { impl ModConfig {
@@ -91,8 +99,18 @@ impl ModConfig {
Self { Self {
id: id.to_owned(), id: id.to_owned(),
path: source.as_ref().to_owned(), path: source.as_ref().to_owned(),
root_mod: false,
ignore: Vec::new(),
} }
} }
pub fn is_root_mod(&self) -> bool {
self.root_mod
}
pub fn ignore(&self) -> &[String] {
&self.ignore
}
} }
/// An modded game with all plugins and files /// An modded game with all plugins and files

View File

@@ -1,8 +1,8 @@
use clap::Parser; use clap::Parser;
use globset::{Glob, GlobSet, GlobSetBuilder};
use log::debug; use log::debug;
use std::{ use std::{
error::Error, error::Error,
fs,
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
@@ -32,6 +32,10 @@ pub fn gen_filelist_for_mod(
) -> Result<Vec<ModFile>, Box<dyn Error>> { ) -> Result<Vec<ModFile>, Box<dyn Error>> {
let mod_location = root_config.get_mod_location(mod_config); let mod_location = root_config.get_mod_location(mod_config);
if mod_config.is_root_mod() {
return gen_filelist_for_root_mod(mod_config, mod_location);
}
let module_config_path = resolve_case_insensitive(&mod_location, "fomod/ModuleConfig.xml")?; let module_config_path = resolve_case_insensitive(&mod_location, "fomod/ModuleConfig.xml")?;
let files: Vec<ModFile> = match module_config_path { let files: Vec<ModFile> = match module_config_path {
@@ -48,6 +52,32 @@ pub fn gen_filelist_for_mod(
Ok(files) Ok(files)
} }
fn create_glob_filter(rules: &[String]) -> Result<GlobSet, Box<dyn Error>> {
let mut builder = GlobSetBuilder::new();
for p in rules {
builder.add(Glob::new(p)?);
}
let set = builder.build()?;
Ok(set)
}
fn gen_filelist_for_root_mod(
mod_config: &ModConfig,
mod_location: impl AsRef<Path>,
) -> Result<Vec<ModFile>, Box<dyn Error>> {
let glob_filter = create_glob_filter(mod_config.ignore())?;
let files: Vec<_> = walk_files_recursive(&mod_location)?
.map(|entry| entry.path())
.map(|path| path.strip_prefix(&mod_location).unwrap().to_owned())
.filter(|rel_path| !glob_filter.is_match(rel_path))
.map(|rel_path| ModFile::new(&rel_path, &rel_path, 0))
.collect();
Ok(files)
}
pub fn gen_filelist_from_mod_dir( pub fn gen_filelist_from_mod_dir(
mod_location: impl AsRef<Path>, mod_location: impl AsRef<Path>,
) -> Result<Vec<ModFile>, Box<dyn Error>> { ) -> Result<Vec<ModFile>, Box<dyn Error>> {