diff --git a/src/main.rs b/src/main.rs index a7902c1..2765cc9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,97 @@ -use std::{error::Error, fs}; +use std::{ + error::Error, + fs::{self, DirEntry}, + path::{Path, PathBuf}, +}; -use crate::mod_config_installer::FomodInstaller; +use crate::{ + fomod::{FileType, FileTypeEnum}, + mod_config_installer::FomodInstaller, +}; -mod install_prompt; -mod mod_config_installer; -mod linker; +mod conflict_resolver; mod fomod; +mod install_prompt; +mod linker; +mod mod_config_installer; + +#[derive(Debug, Clone, PartialEq, Eq)] +struct ModFile { + source: PathBuf, + dest: PathBuf, + /// Internal priority inside the mod itself + internal_priority: isize, +} + +impl ModFile { + #[inline] + pub fn new_from_installer(file: FileType) -> Self { + ModFile { + source: file.source.into(), + dest: file.destination.unwrap_or_default().into(), + internal_priority: file.priority.unwrap_or(0), + } + } + + pub fn from_installer( + entry: FileTypeEnum, + from_mod: &Mod, + ) -> Result, std::io::Error> { + match entry { + FileTypeEnum::File(file_type) => Ok(vec![Self::new_from_installer(file_type)]), + FileTypeEnum::Folder(dir_type) => { + let source_root = from_mod.source.join(&dir_type.source); + let priority = dir_type.priority.unwrap_or(0); + 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(&from_mod.source) + .unwrap() + .to_owned(), + dest: dest_base.clone(), + }) + .collect()) + } + } + } +} + +pub fn walk_files_recursive( + root: impl AsRef, +) -> std::io::Result> { + fn visit(dir: &Path, out: &mut Vec) -> 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()) +} + +#[derive(Debug, Clone, PartialEq, Eq)] +struct Mod { + name: String, + + source: PathBuf, + + priority: isize, +} fn main() -> Result<(), Box> { const XML_PATH: &str = "./data/xml/ineed.xml";