improved instance module
This commit is contained in:
@@ -5,7 +5,8 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use globset::{Glob, GlobSet, GlobSetBuilder};
|
use globset::{Glob, GlobSet, GlobSetBuilder};
|
||||||
use log::{error, warn};
|
use log::warn;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
file_conflict_solver::ConflictSolver,
|
file_conflict_solver::ConflictSolver,
|
||||||
@@ -20,7 +21,7 @@ pub fn insert_mod_to_instance(
|
|||||||
from_mod: &ModConfig,
|
from_mod: &ModConfig,
|
||||||
files: &[ModFile],
|
files: &[ModFile],
|
||||||
priority: isize,
|
priority: isize,
|
||||||
) -> bool {
|
) -> Result<(), InststanceError> {
|
||||||
let mut solver = ConflictSolver::new();
|
let mut solver = ConflictSolver::new();
|
||||||
|
|
||||||
let mut installed_files: Vec<(ModFile, &InstalledMod)> = Vec::new();
|
let mut installed_files: Vec<(ModFile, &InstalledMod)> = Vec::new();
|
||||||
@@ -33,21 +34,18 @@ pub fn insert_mod_to_instance(
|
|||||||
|
|
||||||
for (file, from_mod) in &installed_files {
|
for (file, from_mod) in &installed_files {
|
||||||
if let Some(conflict) = solver.add_file(file, from_mod) {
|
if let Some(conflict) = solver.add_file(file, from_mod) {
|
||||||
warn!("Got file conflict on already added file: {:?}", conflict);
|
warn!("File conflict on already added file: {:?}", conflict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_mod = InstalledMod::new(from_mod.id(), priority);
|
let new_mod = InstalledMod::new(from_mod.id(), priority);
|
||||||
for file in files {
|
for file in files {
|
||||||
if let Some(conflict) = solver.add_file(file, &new_mod) {
|
if let Some(conflict) = solver.add_file(file, &new_mod) {
|
||||||
error!(
|
return Err(InststanceError::FileConflict {
|
||||||
"File conflict detected at: {} between {} and {}",
|
lhs_mod_id: conflict.lhs_mod.mod_id().to_owned(),
|
||||||
conflict.rhs_file.dst().to_string_lossy(),
|
rhs_mod_id: conflict.rhs_mod.mod_id().to_owned(),
|
||||||
conflict.lhs_mod.mod_id(),
|
path: conflict.rhs_file.dst().to_owned(),
|
||||||
conflict.rhs_mod.mod_id()
|
});
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +70,7 @@ pub fn insert_mod_to_instance(
|
|||||||
instance.update_or_create_mod(&installed_mod);
|
instance.update_or_create_mod(&installed_mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn files_to_install_mod(
|
pub fn files_to_install_mod(
|
||||||
@@ -123,13 +121,18 @@ fn install_fomod(
|
|||||||
let module_config = fomod::Config::load_from_file(module_config_path)?;
|
let module_config = fomod::Config::load_from_file(module_config_path)?;
|
||||||
|
|
||||||
// TODO: add active plugins from instance config
|
// TODO: add active plugins from instance config
|
||||||
let files = run_fomod_installer(module_config, &[], install_prompt::prompt)?;
|
let files = run_fomod_installer(module_config, &[], install_prompt::prompt)
|
||||||
|
.map_err(|_| InststanceError::FomodRunInstaller)?;
|
||||||
|
|
||||||
let mod_files: Vec<_> = files
|
let mod_files: Vec<_> = files
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|f| ModFile::from_installer(f.clone(), &mod_root).unwrap())
|
.map(|f| {
|
||||||
|
ModFile::from_installer(f.clone(), &mod_root).map_err(InststanceError::FomodFinalize)
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()?
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(mod_files)
|
Ok(mod_files)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,3 +205,19 @@ fn should_be_included(path: impl AsRef<Path>) -> bool {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum InststanceError {
|
||||||
|
#[error("Two mods write the same file")]
|
||||||
|
FileConflict {
|
||||||
|
lhs_mod_id: String,
|
||||||
|
rhs_mod_id: String,
|
||||||
|
path: PathBuf,
|
||||||
|
},
|
||||||
|
|
||||||
|
#[error("Failed to run fomod installer")]
|
||||||
|
FomodRunInstaller,
|
||||||
|
|
||||||
|
#[error("Failed to handle results of fomod installer")]
|
||||||
|
FomodFinalize(io::Error),
|
||||||
|
}
|
||||||
|
|||||||
43
src/main.rs
43
src/main.rs
@@ -1,13 +1,13 @@
|
|||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use log::debug;
|
use log::{debug, error, info};
|
||||||
use std::{error::Error, path::Path};
|
use std::{error::Error, path::Path};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
activator::activate_instance,
|
activator::activate_instance,
|
||||||
cli::Args,
|
cli::Args,
|
||||||
instance::{files_to_install_mod, insert_mod_to_instance},
|
instance::{files_to_install_mod, insert_mod_to_instance},
|
||||||
nexus::{NexusAPI,download_nxm},
|
nexus::{NexusAPI, download_nxm},
|
||||||
types::RootConfig,
|
types::RootConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,13 +41,40 @@ fn command_add(root_config: &RootConfig, instance_id: &str, mod_id: &str) -> any
|
|||||||
|
|
||||||
let files = files_to_install_mod(root_config, &instance, mod_to_install)?;
|
let files = files_to_install_mod(root_config, &instance, mod_to_install)?;
|
||||||
|
|
||||||
if !insert_mod_to_instance(&mut instance, mod_to_install, &files, 0) {
|
match insert_mod_to_instance(&mut instance, mod_to_install, &files, 0) {
|
||||||
return Err(anyhow!("File conflict"));
|
Ok(_) => {
|
||||||
|
instance.save_to_file()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
match &err {
|
||||||
|
instance::InststanceError::FileConflict {
|
||||||
|
lhs_mod_id,
|
||||||
|
rhs_mod_id,
|
||||||
|
path,
|
||||||
|
} => {
|
||||||
|
error!(
|
||||||
|
"File conflict between {} and {} at {}",
|
||||||
|
lhs_mod_id,
|
||||||
|
rhs_mod_id,
|
||||||
|
path.to_string_lossy()
|
||||||
|
);
|
||||||
|
info!("To resolve file conflicts give one mod a higher priority in the config");
|
||||||
|
}
|
||||||
|
instance::InststanceError::FomodRunInstaller => {
|
||||||
|
error!("Failed to run FOMod installer");
|
||||||
|
}
|
||||||
|
instance::InststanceError::FomodFinalize(error) => {
|
||||||
|
error!(
|
||||||
|
"FOMod installer finished but failed to finalize result: {}",
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Err(err.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.save_to_file()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_order(root_config: &RootConfig, instance_id: &str) -> anyhow::Result<()> {
|
fn command_order(root_config: &RootConfig, instance_id: &str) -> anyhow::Result<()> {
|
||||||
|
|||||||
Reference in New Issue
Block a user