made use of walkdir
This commit is contained in:
29
Cargo.lock
generated
29
Cargo.lock
generated
@@ -325,6 +325,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"toml",
|
"toml",
|
||||||
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -725,6 +726,15 @@ version = "2.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "saphyr"
|
name = "saphyr"
|
||||||
version = "0.0.6"
|
version = "0.0.6"
|
||||||
@@ -896,12 +906,31 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.1+wasi-snapshot-preview1"
|
version = "0.11.1+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-link"
|
name = "windows-link"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
|||||||
@@ -14,3 +14,4 @@ quick-xml = { version = "0.39.2", features = ["serde-types", "serialize"] }
|
|||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
thiserror = "2.0.18"
|
thiserror = "2.0.18"
|
||||||
toml = "1.0.3"
|
toml = "1.0.3"
|
||||||
|
walkdir = "2.5.0"
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use anyhow::Result;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
@@ -6,11 +7,9 @@ use std::{
|
|||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
use crate::{
|
use crate::fomod::{FileType, FileTypeEnum};
|
||||||
fomod::{FileType, FileTypeEnum},
|
|
||||||
utils::walk_files_recursive,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A link between a file from a mod and a destination in a ModdedInstance
|
/// A link between a file from a mod and a destination in a ModdedInstance
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Hash)]
|
||||||
@@ -113,11 +112,19 @@ pub struct Game {
|
|||||||
|
|
||||||
impl Game {
|
impl Game {
|
||||||
pub fn export_links(&self) -> Result<Vec<Link>, io::Error> {
|
pub fn export_links(&self) -> Result<Vec<Link>, io::Error> {
|
||||||
let links: Vec<Link> = walk_files_recursive(&self.install_location)
|
let links: Vec<Link> = WalkDir::new(&self.install_location)
|
||||||
.unwrap()
|
.into_iter()
|
||||||
.map(|file| file.path())
|
.map(|entry| {
|
||||||
.map(|path| Link::new(&path, path.strip_prefix(&self.install_location).unwrap()))
|
let entry = entry?;
|
||||||
.collect();
|
let path = entry.path();
|
||||||
|
|
||||||
|
Ok(Link::new(
|
||||||
|
&path,
|
||||||
|
path.strip_prefix(&self.install_location).unwrap(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.collect::<Result<_, io::Error>>()?;
|
||||||
|
|
||||||
Ok(links)
|
Ok(links)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,13 +324,19 @@ impl ModFile {
|
|||||||
let dest_base: PathBuf =
|
let dest_base: PathBuf =
|
||||||
Path::new("Data").join(PathBuf::from(dir_type.destination.unwrap_or_default()));
|
Path::new("Data").join(PathBuf::from(dir_type.destination.unwrap_or_default()));
|
||||||
|
|
||||||
Ok(walk_files_recursive(&source_root)?
|
let files = WalkDir::new(&source_root)
|
||||||
.map(|file| Self {
|
.into_iter()
|
||||||
|
.map(|entry| {
|
||||||
|
let entry = entry?;
|
||||||
|
Ok(Self {
|
||||||
internal_priority: priority,
|
internal_priority: priority,
|
||||||
source: file.path().strip_prefix(&source).unwrap().to_owned(),
|
source: entry.path().strip_prefix(&source).unwrap().to_owned(),
|
||||||
dest: dest_base.join(file.path().strip_prefix(&source_root).unwrap()),
|
dest: dest_base.join(entry.path().strip_prefix(&source_root).unwrap()),
|
||||||
})
|
})
|
||||||
.collect())
|
})
|
||||||
|
.collect::<Result<_, io::Error>>()?;
|
||||||
|
|
||||||
|
Ok(files)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::HashMap,
|
||||||
io,
|
io,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use globset::{Glob, GlobSet, GlobSetBuilder};
|
use globset::{Glob, GlobSet, GlobSetBuilder};
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
basic_types::{InstalledMod, Link, ModConfig, ModFile, ModdedInstance, RootConfig},
|
basic_types::{InstalledMod, ModConfig, ModFile, ModdedInstance, RootConfig},
|
||||||
file_conflict_solver::ConflictSolver,
|
file_conflict_solver::ConflictSolver,
|
||||||
fomod, install_prompt,
|
fomod, install_prompt,
|
||||||
mod_config_installer::run_fomod_installer,
|
mod_config_installer::run_fomod_installer,
|
||||||
utils::{resolve_case_insensitive, walk_files_recursive},
|
utils::resolve_case_insensitive,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn insert_mod_to_instance(
|
pub fn insert_mod_to_instance(
|
||||||
@@ -129,12 +130,23 @@ fn install_from_dir(
|
|||||||
path: impl AsRef<Path>,
|
path: impl AsRef<Path>,
|
||||||
) -> anyhow::Result<Vec<ModFile>> {
|
) -> anyhow::Result<Vec<ModFile>> {
|
||||||
let glob_filter = create_glob_filter(mod_config.ignore())?;
|
let glob_filter = create_glob_filter(mod_config.ignore())?;
|
||||||
let files: Vec<_> = walk_files_recursive(&path)?
|
let files: Vec<_> = WalkDir::new(path)
|
||||||
.map(|entry| entry.path())
|
.into_iter()
|
||||||
.map(|file_path| file_path.strip_prefix(&path).unwrap().to_owned())
|
.map(|entry| {
|
||||||
.filter(|rel_path| !glob_filter.is_match(rel_path))
|
let entry = entry?;
|
||||||
.map(|rel_path| ModFile::new(&rel_path, &rel_path, 0))
|
let path = entry.path();
|
||||||
.collect();
|
|
||||||
|
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)
|
Ok(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,13 +156,26 @@ fn install_from_dir_to_data(
|
|||||||
) -> anyhow::Result<Vec<ModFile>> {
|
) -> anyhow::Result<Vec<ModFile>> {
|
||||||
let glob_filter = create_glob_filter(mod_config.ignore())?;
|
let glob_filter = create_glob_filter(mod_config.ignore())?;
|
||||||
let data = PathBuf::from("Data");
|
let data = PathBuf::from("Data");
|
||||||
let files: Vec<_> = walk_files_recursive(&path)?
|
let files: Vec<_> = WalkDir::new(&path)
|
||||||
.map(|entry| entry.path())
|
.into_iter()
|
||||||
.map(|file_path| file_path.strip_prefix(&path).unwrap().to_owned())
|
.map(|entry| {
|
||||||
.filter(|rel_path| should_be_included(rel_path))
|
let entry = entry?;
|
||||||
.filter(|rel_path| !glob_filter.is_match(rel_path))
|
let path = entry.path();
|
||||||
.map(|rel_path| ModFile::new(&rel_path, data.join(&rel_path), 0))
|
|
||||||
.collect();
|
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)
|
Ok(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ use libloot::{
|
|||||||
error::{GameHandleCreationError, LoadPluginsError, SortPluginsError},
|
error::{GameHandleCreationError, LoadPluginsError, SortPluginsError},
|
||||||
};
|
};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use std::{io, path::Path};
|
use std::{
|
||||||
use thiserror::Error;
|
io,
|
||||||
|
path::{Path, PathBuf},
|
||||||
use crate::{
|
|
||||||
basic_types::{self, ModdedInstance, RootConfig},
|
|
||||||
utils::walk_files_recursive,
|
|
||||||
};
|
};
|
||||||
|
use thiserror::Error;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
use crate::basic_types::{self, ModdedInstance, RootConfig};
|
||||||
|
|
||||||
pub fn create_loadorder(
|
pub fn create_loadorder(
|
||||||
root_config: &RootConfig,
|
root_config: &RootConfig,
|
||||||
@@ -19,11 +20,23 @@ pub fn create_loadorder(
|
|||||||
let mut loot_game = Game::new(GameType::SkyrimSE, &game.install_location)?;
|
let mut loot_game = Game::new(GameType::SkyrimSE, &game.install_location)?;
|
||||||
|
|
||||||
// Add plugins files from the game install
|
// Add plugins files from the game install
|
||||||
let install_plugins: Vec<_> = walk_files_recursive(game.install_location.join("Data"))?
|
let install_plugins: Vec<PathBuf> = WalkDir::new(game.install_location.join("Data"))
|
||||||
.filter(|f| is_plugin_file(f.path()))
|
.into_iter()
|
||||||
.map(|f| f.path())
|
.map(|entry| {
|
||||||
.collect();
|
let entry = entry?;
|
||||||
let refs: Vec<_> = install_plugins.iter().map(|e| e.as_path()).collect();
|
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());
|
trace!("Loading {} plugins to game", refs.len());
|
||||||
loot_game.load_plugins(&refs)?;
|
loot_game.load_plugins(&refs)?;
|
||||||
|
|||||||
25
src/utils.rs
25
src/utils.rs
@@ -1,32 +1,9 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fs::{self, DirEntry},
|
fs::{self},
|
||||||
io,
|
io,
|
||||||
path::{Path, PathBuf},
|
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 {
|
pub fn path_to_lowercase(path: impl AsRef<Path>) -> PathBuf {
|
||||||
PathBuf::from(path.as_ref().to_string_lossy().to_lowercase())
|
PathBuf::from(path.as_ref().to_string_lossy().to_lowercase())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user