made use of walkdir

This commit is contained in:
2026-03-04 19:56:33 +01:00
parent d263d487b1
commit b6efa0a818
6 changed files with 124 additions and 66 deletions

View File

@@ -1,3 +1,4 @@
use anyhow::Result;
use log::trace;
use serde::{Deserialize, Serialize};
use std::{
@@ -6,11 +7,9 @@ use std::{
path::{Path, PathBuf},
};
use thiserror::Error;
use walkdir::WalkDir;
use crate::{
fomod::{FileType, FileTypeEnum},
utils::walk_files_recursive,
};
use crate::fomod::{FileType, FileTypeEnum};
/// A link between a file from a mod and a destination in a ModdedInstance
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
@@ -113,11 +112,19 @@ pub struct Game {
impl Game {
pub fn export_links(&self) -> Result<Vec<Link>, io::Error> {
let links: Vec<Link> = walk_files_recursive(&self.install_location)
.unwrap()
.map(|file| file.path())
.map(|path| Link::new(&path, path.strip_prefix(&self.install_location).unwrap()))
.collect();
let links: Vec<Link> = WalkDir::new(&self.install_location)
.into_iter()
.map(|entry| {
let entry = entry?;
let path = entry.path();
Ok(Link::new(
&path,
path.strip_prefix(&self.install_location).unwrap(),
))
})
.collect::<Result<_, io::Error>>()?;
Ok(links)
}
}
@@ -317,13 +324,19 @@ impl ModFile {
let dest_base: PathBuf =
Path::new("Data").join(PathBuf::from(dir_type.destination.unwrap_or_default()));
Ok(walk_files_recursive(&source_root)?
.map(|file| Self {
internal_priority: priority,
source: file.path().strip_prefix(&source).unwrap().to_owned(),
dest: dest_base.join(file.path().strip_prefix(&source_root).unwrap()),
let files = WalkDir::new(&source_root)
.into_iter()
.map(|entry| {
let entry = entry?;
Ok(Self {
internal_priority: priority,
source: entry.path().strip_prefix(&source).unwrap().to_owned(),
dest: dest_base.join(entry.path().strip_prefix(&source_root).unwrap()),
})
})
.collect())
.collect::<Result<_, io::Error>>()?;
Ok(files)
}
}
}

View File

@@ -1,18 +1,19 @@
use std::{
collections::{HashMap, HashSet},
collections::HashMap,
io,
path::{Path, PathBuf},
};
use globset::{Glob, GlobSet, GlobSetBuilder};
use log::warn;
use walkdir::WalkDir;
use crate::{
basic_types::{InstalledMod, Link, ModConfig, ModFile, ModdedInstance, RootConfig},
basic_types::{InstalledMod, ModConfig, ModFile, ModdedInstance, RootConfig},
file_conflict_solver::ConflictSolver,
fomod, install_prompt,
mod_config_installer::run_fomod_installer,
utils::{resolve_case_insensitive, walk_files_recursive},
utils::resolve_case_insensitive,
};
pub fn insert_mod_to_instance(
@@ -129,12 +130,23 @@ fn install_from_dir(
path: impl AsRef<Path>,
) -> anyhow::Result<Vec<ModFile>> {
let glob_filter = create_glob_filter(mod_config.ignore())?;
let files: Vec<_> = walk_files_recursive(&path)?
.map(|entry| entry.path())
.map(|file_path| file_path.strip_prefix(&path).unwrap().to_owned())
.filter(|rel_path| !glob_filter.is_match(rel_path))
.map(|rel_path| ModFile::new(&rel_path, &rel_path, 0))
.collect();
let files: Vec<_> = WalkDir::new(path)
.into_iter()
.map(|entry| {
let entry = entry?;
let path = entry.path();
let rel_path = path.strip_prefix(&path).unwrap();
if !glob_filter.is_match(rel_path) {
Ok(Some(ModFile::new(&rel_path, &rel_path, 0)))
} else {
Ok(None)
}
})
.filter_map(|r| r.transpose())
.collect::<Result<_, io::Error>>()?;
Ok(files)
}
@@ -144,13 +156,26 @@ fn install_from_dir_to_data(
) -> anyhow::Result<Vec<ModFile>> {
let glob_filter = create_glob_filter(mod_config.ignore())?;
let data = PathBuf::from("Data");
let files: Vec<_> = walk_files_recursive(&path)?
.map(|entry| entry.path())
.map(|file_path| file_path.strip_prefix(&path).unwrap().to_owned())
.filter(|rel_path| should_be_included(rel_path))
.filter(|rel_path| !glob_filter.is_match(rel_path))
.map(|rel_path| ModFile::new(&rel_path, data.join(&rel_path), 0))
.collect();
let files: Vec<_> = WalkDir::new(&path)
.into_iter()
.map(|entry| {
let entry = entry?;
let path = entry.path();
let rel_path = path.strip_prefix(&path).unwrap();
if !should_be_included(rel_path) {
return Ok(None);
}
if glob_filter.is_match(rel_path) {
return Ok(None);
}
Ok(Some(ModFile::new(rel_path, data.join(rel_path), 0)))
})
.filter_map(|r| r.transpose())
.collect::<Result<_, io::Error>>()?;
Ok(files)
}

View File

@@ -3,13 +3,14 @@ use libloot::{
error::{GameHandleCreationError, LoadPluginsError, SortPluginsError},
};
use log::trace;
use std::{io, path::Path};
use thiserror::Error;
use crate::{
basic_types::{self, ModdedInstance, RootConfig},
utils::walk_files_recursive,
use std::{
io,
path::{Path, PathBuf},
};
use thiserror::Error;
use walkdir::WalkDir;
use crate::basic_types::{self, ModdedInstance, RootConfig};
pub fn create_loadorder(
root_config: &RootConfig,
@@ -19,11 +20,23 @@ pub fn create_loadorder(
let mut loot_game = Game::new(GameType::SkyrimSE, &game.install_location)?;
// Add plugins files from the game install
let install_plugins: Vec<_> = walk_files_recursive(game.install_location.join("Data"))?
.filter(|f| is_plugin_file(f.path()))
.map(|f| f.path())
.collect();
let refs: Vec<_> = install_plugins.iter().map(|e| e.as_path()).collect();
let install_plugins: Vec<PathBuf> = WalkDir::new(game.install_location.join("Data"))
.into_iter()
.map(|entry| {
let entry = entry?;
let path = entry.path();
if is_plugin_file(path) {
Ok(Some(path.to_path_buf()))
} else {
Ok(None)
}
})
.filter_map(|r| r.transpose())
.collect::<Result<_, io::Error>>()?;
// The loaded_plugins function requires &[&Path]
let refs: Vec<&Path> = install_plugins.iter().map(|e| e.as_path()).collect();
trace!("Loading {} plugins to game", refs.len());
loot_game.load_plugins(&refs)?;

View File

@@ -1,32 +1,9 @@
use std::{
fs::{self, DirEntry},
fs::{self},
io,
path::{Path, PathBuf},
};
pub fn walk_files_recursive(
root: impl AsRef<Path>,
) -> std::io::Result<impl Iterator<Item = DirEntry>> {
fn visit(dir: &Path, out: &mut Vec<DirEntry>) -> std::io::Result<()> {
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
let file_type = entry.file_type()?;
if file_type.is_dir() {
visit(&path, out)?;
} else if file_type.is_file() {
out.push(entry);
}
}
Ok(())
}
let mut files = Vec::new();
visit(root.as_ref(), &mut files)?;
Ok(files.into_iter())
}
pub fn path_to_lowercase(path: impl AsRef<Path>) -> PathBuf {
PathBuf::from(path.as_ref().to_string_lossy().to_lowercase())
}