changed the way files get resolved on mod install
to better handle fomod and it's required interactivity
This commit is contained in:
@@ -7,5 +7,5 @@ mod load_order;
|
||||
pub use activate::{ActivationError, activate_instance};
|
||||
pub use download::handle_nxm;
|
||||
pub use include::insert_mod_to_instance;
|
||||
pub use install::resolve_files_for_install;
|
||||
pub use install::{resolve_files_for_install, ResolveFileResult};
|
||||
pub use load_order::{LoadOrderError, create_loadorder};
|
||||
|
||||
@@ -4,30 +4,34 @@ use std::{
|
||||
};
|
||||
|
||||
use globset::{Glob, GlobSet, GlobSetBuilder};
|
||||
use log::{debug, trace};
|
||||
|
||||
use crate::{
|
||||
fomod, install_prompt,
|
||||
mod_config_installer::FomodInstaller,
|
||||
types::{ModConfig, ModFile, ModdedInstance, RootConfig},
|
||||
fomod,
|
||||
types::{ModConfig, ModFile, RootConfig},
|
||||
utils::{resolve_case_insensitive, walk_all_files},
|
||||
};
|
||||
|
||||
pub fn resolve_files_for_install(
|
||||
root_config: &RootConfig,
|
||||
instance: &ModdedInstance,
|
||||
mod_to_install: &ModConfig,
|
||||
) -> anyhow::Result<Vec<ModFile>> {
|
||||
) -> anyhow::Result<ResolveFileResult> {
|
||||
let mod_location = root_config.mod_location().join(mod_to_install.path());
|
||||
|
||||
let files = match determain_mod_kind(mod_to_install, &mod_location)? {
|
||||
ModKind::Fomod(xml_path) => install_fomod(instance, xml_path, &mod_location)?,
|
||||
ModKind::EmbeddedData(_data_path) => install_from_dir(mod_to_install, mod_location)?,
|
||||
ModKind::Root => install_root(mod_to_install, mod_location)?,
|
||||
ModKind::Unkown => install_from_dir_to_data(mod_to_install, mod_location)?,
|
||||
let result = match determain_mod_kind(mod_to_install, &mod_location)? {
|
||||
ModKind::Fomod(xml_path) => {
|
||||
let module_config = fomod::Config::load_from_file(xml_path)?;
|
||||
ResolveFileResult::Fomod(module_config)
|
||||
}
|
||||
ModKind::EmbeddedData(_data_path) => {
|
||||
ResolveFileResult::Files(install_from_dir(mod_to_install, mod_location)?)
|
||||
}
|
||||
ModKind::Root => ResolveFileResult::Files(install_root(mod_to_install, mod_location)?),
|
||||
ModKind::Unkown => {
|
||||
ResolveFileResult::Files(install_from_dir_to_data(mod_to_install, mod_location)?)
|
||||
}
|
||||
};
|
||||
|
||||
Ok(files)
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn determain_mod_kind(
|
||||
@@ -51,38 +55,38 @@ fn determain_mod_kind(
|
||||
}
|
||||
}
|
||||
|
||||
fn install_fomod(
|
||||
instance: &ModdedInstance,
|
||||
module_config_path: impl AsRef<Path>,
|
||||
mod_root: impl AsRef<Path>,
|
||||
) -> anyhow::Result<Vec<ModFile>> {
|
||||
debug!("Running FOmod installer");
|
||||
let module_config = fomod::Config::load_from_file(module_config_path)?;
|
||||
|
||||
let active_plugins: Vec<_> = instance
|
||||
.active_plugins()
|
||||
.map(|e| e.to_string_lossy())
|
||||
.map(|e| e.to_string())
|
||||
.collect();
|
||||
|
||||
trace!("Current loded plugins: {:?}", active_plugins);
|
||||
|
||||
let mut installer = FomodInstaller::new(&module_config, &active_plugins);
|
||||
let mut selection: Option<Vec<usize>> = None;
|
||||
while let Some(prompt) = installer.run_step(selection.as_deref()) {
|
||||
selection = Some(install_prompt::prompt(prompt));
|
||||
}
|
||||
let files = installer.finalize();
|
||||
|
||||
let mod_files: Vec<_> = files
|
||||
.iter()
|
||||
.map(|f| ModFile::from_installer(f.clone(), &mod_root))
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect();
|
||||
Ok(mod_files)
|
||||
}
|
||||
// fn install_fomod(
|
||||
// instance: &ModdedInstance,
|
||||
// module_config_path: impl AsRef<Path>,
|
||||
// mod_root: impl AsRef<Path>,
|
||||
// ) -> anyhow::Result<Vec<ModFile>> {
|
||||
// debug!("Running FOmod installer");
|
||||
// let module_config = fomod::Config::load_from_file(module_config_path)?;
|
||||
//
|
||||
// let active_plugins: Vec<_> = instance
|
||||
// .active_plugins()
|
||||
// .map(|e| e.to_string_lossy())
|
||||
// .map(|e| e.to_string())
|
||||
// .collect();
|
||||
//
|
||||
// trace!("Current loded plugins: {:?}", active_plugins);
|
||||
//
|
||||
// let mut installer = FomodInstaller::new(&module_config, &active_plugins);
|
||||
// let mut selection: Option<Vec<usize>> = None;
|
||||
// while let Some(prompt) = installer.run_step(selection.as_deref()) {
|
||||
// selection = Some(install_prompt::prompt(prompt));
|
||||
// }
|
||||
// let files = installer.finalize();
|
||||
//
|
||||
// let mod_files: Vec<_> = files
|
||||
// .iter()
|
||||
// .map(|f| ModFile::from_installer(f.clone(), &mod_root))
|
||||
// .collect::<Result<Vec<_>, _>>()?
|
||||
// .into_iter()
|
||||
// .flatten()
|
||||
// .collect();
|
||||
// Ok(mod_files)
|
||||
// }
|
||||
|
||||
fn install_from_dir(
|
||||
mod_config: &ModConfig,
|
||||
@@ -149,6 +153,11 @@ enum ModKind {
|
||||
Unkown,
|
||||
}
|
||||
|
||||
pub enum ResolveFileResult {
|
||||
Files(Vec<ModFile>),
|
||||
Fomod(fomod::Config),
|
||||
}
|
||||
|
||||
fn should_be_included(path: impl AsRef<Path>) -> bool {
|
||||
matches!(
|
||||
path.as_ref().extension().and_then(|e| e.to_str()),
|
||||
|
||||
25
src/main.rs
25
src/main.rs
@@ -5,9 +5,14 @@ use std::{error::Error, path::Path};
|
||||
|
||||
use fomod_manager::{
|
||||
actions::{
|
||||
activate_instance, create_loadorder, handle_nxm, insert_mod_to_instance,
|
||||
ResolveFileResult, activate_instance, create_loadorder, handle_nxm, insert_mod_to_instance,
|
||||
resolve_files_for_install,
|
||||
}, cli::{self, Args}, nexus::NexusAPI, tui, types::RootConfig
|
||||
},
|
||||
cli::{self, Args},
|
||||
mod_config_installer::FomodInstaller,
|
||||
nexus::NexusAPI,
|
||||
tui,
|
||||
types::RootConfig,
|
||||
};
|
||||
|
||||
fn command_activate(
|
||||
@@ -26,7 +31,19 @@ fn command_add(root_config: &RootConfig, instance_id: &str, mod_id: &str) -> any
|
||||
.mod_by_id(mod_id)
|
||||
.ok_or(anyhow!("Can't find mod in config"))?;
|
||||
|
||||
let files = resolve_files_for_install(root_config, &instance, &mod_to_install)?;
|
||||
let files = match resolve_files_for_install(root_config, &mod_to_install)? {
|
||||
ResolveFileResult::Files(mod_files) => mod_files,
|
||||
ResolveFileResult::Fomod(module_config) => {
|
||||
let mod_location = root_config.mod_location().join(mod_to_install.path());
|
||||
let active_plugins: Vec<String> = instance.active_plugins().collect();
|
||||
let mut installer = FomodInstaller::new(&module_config, &active_plugins);
|
||||
let mut selection: Option<Vec<usize>> = None;
|
||||
while let Some(prompt) = installer.run_step(selection.as_deref()) {
|
||||
selection = Some(fomod_manager::install_prompt::prompt(prompt));
|
||||
}
|
||||
installer.finalize(mod_location)?
|
||||
}
|
||||
};
|
||||
|
||||
match insert_mod_to_instance(&mut instance, &mod_to_install, &files, 0) {
|
||||
None => {
|
||||
@@ -101,7 +118,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
cli::Commands::Tui => {
|
||||
tui::run(&mut root_config)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
use std::{collections::HashMap, fmt::Display};
|
||||
use std::{collections::HashMap, fmt::Display, io, path::Path};
|
||||
|
||||
use log::{debug, warn};
|
||||
|
||||
use crate::fomod::{
|
||||
CompositeDependency, Config, DependencyOperator, DependencyState, FileList, FileTypeEnum,
|
||||
Group, GroupType, ModuleDependency, Plugin, PluginTypeDescriptorEnum, PluginTypeEnum,
|
||||
use crate::{
|
||||
fomod::{
|
||||
CompositeDependency, Config, DependencyOperator, DependencyState, FileList, FileTypeEnum,
|
||||
Group, GroupType, ModuleDependency, Plugin, PluginTypeDescriptorEnum, PluginTypeEnum,
|
||||
},
|
||||
types::ModFile,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -117,6 +120,7 @@ fn evaluate_module_depbendecy(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GroupPrompt {
|
||||
pub name: String,
|
||||
pub select_type: GroupType,
|
||||
@@ -146,6 +150,7 @@ impl GroupPrompt {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InstallOption {
|
||||
pub name: String,
|
||||
pub option_type: PluginTypeEnum,
|
||||
@@ -264,7 +269,17 @@ impl<'a> FomodInstaller<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finalize(self) -> Vec<FileTypeEnum> {
|
||||
self.state.into_file_list()
|
||||
pub fn finalize(self, mod_root: impl AsRef<Path>) -> Result<Vec<ModFile>, io::Error> {
|
||||
let files: Vec<_> = self
|
||||
.state
|
||||
.into_file_list()
|
||||
.iter()
|
||||
.map(|f| ModFile::from_installer(f.clone(), &mod_root))
|
||||
.collect::<Result<Vec<_>, _>>()?
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
Ok(files)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
fs::{self, read_to_string},
|
||||
io::Write,
|
||||
path::{Path, PathBuf},
|
||||
@@ -106,8 +105,12 @@ impl ModdedInstance {
|
||||
&self.mods
|
||||
}
|
||||
|
||||
pub fn active_plugins(&self) -> impl Iterator<Item = &OsStr> {
|
||||
self.mods.iter().flat_map(|e| e.active_plugins())
|
||||
pub fn active_plugins(&self) -> impl Iterator<Item = String> {
|
||||
self.mods
|
||||
.iter()
|
||||
.flat_map(|e| e.active_plugins())
|
||||
.map(|e| e.to_string_lossy())
|
||||
.map(|e| e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,6 +159,5 @@ mod tests {
|
||||
let new_mod = InstalledMod::new("mod1", 1);
|
||||
|
||||
cfg.update_or_create_mod(&new_mod);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,12 @@ fn add_plain() -> Result<(), Box<dyn Error>> {
|
||||
let mod_to_install = root_config
|
||||
.mod_by_id("add_test_plain")
|
||||
.expect("Mod not found");
|
||||
let files_to_add = resolve_files_for_install(&root_config, &instance, &mod_to_install)?;
|
||||
let files_to_add = match resolve_files_for_install(&root_config, &mod_to_install)? {
|
||||
fomod_manager::actions::ResolveFileResult::Files(mod_files) => mod_files,
|
||||
_ => {
|
||||
panic!("Resolved files have wrong type");
|
||||
}
|
||||
};
|
||||
|
||||
insert_mod_to_instance(&mut instance, &mod_to_install, &files_to_add, 0);
|
||||
|
||||
@@ -53,7 +58,12 @@ fn add_nested() -> Result<(), Box<dyn Error>> {
|
||||
let mod_to_install = root_config
|
||||
.mod_by_id("add_test_nested")
|
||||
.expect("Mod not found");
|
||||
let files_to_add = resolve_files_for_install(&root_config, &instance, &mod_to_install)?;
|
||||
let files_to_add = match resolve_files_for_install(&root_config, &mod_to_install)? {
|
||||
fomod_manager::actions::ResolveFileResult::Files(mod_files) => mod_files,
|
||||
_ => {
|
||||
panic!("Resolved files have wrong type");
|
||||
}
|
||||
};
|
||||
|
||||
insert_mod_to_instance(&mut instance, &mod_to_install, &files_to_add, 0);
|
||||
|
||||
@@ -86,7 +96,12 @@ fn add_root() -> Result<(), Box<dyn Error>> {
|
||||
let mod_to_install = root_config
|
||||
.mod_by_id("add_test_root")
|
||||
.expect("Mod not found");
|
||||
let files_to_add = resolve_files_for_install(&root_config, &instance, &mod_to_install)?;
|
||||
let files_to_add = match resolve_files_for_install(&root_config, &mod_to_install)? {
|
||||
fomod_manager::actions::ResolveFileResult::Files(mod_files) => mod_files,
|
||||
_ => {
|
||||
panic!("Resolved files have wrong type");
|
||||
}
|
||||
};
|
||||
|
||||
insert_mod_to_instance(&mut instance, &mod_to_install, &files_to_add, 0);
|
||||
|
||||
@@ -117,7 +132,12 @@ fn add_filter() -> Result<(), Box<dyn Error>> {
|
||||
let mod_to_install = root_config
|
||||
.mod_by_id("add_test_filter")
|
||||
.expect("Mod not found");
|
||||
let files_to_add = resolve_files_for_install(&root_config, &instance, &mod_to_install)?;
|
||||
let files_to_add = match resolve_files_for_install(&root_config, &mod_to_install)? {
|
||||
fomod_manager::actions::ResolveFileResult::Files(mod_files) => mod_files,
|
||||
_ => {
|
||||
panic!("Resolved files have wrong type");
|
||||
}
|
||||
};
|
||||
|
||||
insert_mod_to_instance(&mut instance, &mod_to_install, &files_to_add, 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user