use log::debug; use crate::{ basic_types::{ModdedInstance, RootConfig}, utils::walk_files_recursive, }; use std::io::Write; use std::{fs, io, os::unix, path::Path}; pub fn link_instance_to_target( root_config: &RootConfig, instance: &ModdedInstance, target: impl AsRef, ) -> Result<(), io::Error> { debug!("Linking instance to {}", target.as_ref().to_string_lossy()); for installed_mod in &instance.mods { let mod_config = root_config.get_mod_by_id(&installed_mod.mod_id()).unwrap(); let mod_source_root = root_config.get_mod_location(&mod_config); for (src, dst) in installed_mod.files() { let link_target = mod_source_root.join(src); let link_name = target.as_ref().join(dst); link_file(&link_target, &link_name)?; } } Ok(()) } pub fn link_game_to_target( game_dir: impl AsRef, target: impl AsRef, ) -> Result<(), io::Error> { debug!("Linking install to {}", target.as_ref().to_string_lossy()); walk_files_recursive(&game_dir)?.try_for_each(|file| { let link_target = file.path(); let link_name = target .as_ref() .join(file.path().strip_prefix(&game_dir).unwrap()); link_file(&link_target, &link_name) }) } fn link_file(target: &Path, link_name: &Path) -> Result<(), io::Error> { if let Some(parent) = link_name.parent() { fs::create_dir_all(parent)?; } create_symlink_for_file(target, link_name)?; Ok(()) } pub fn create_plugins_txt( instance: &ModdedInstance, target: impl AsRef, ) -> Result<(), io::Error> { debug!("Generating plugins.txt"); let mut file = fs::File::create(target.as_ref().join("plugins.txt"))?; writeln!(file, "# Auto generated. DO NOT EDIT MANUALLY!")?; for plugin in instance.load_order() { writeln!(file, "*{}", plugin)?; } Ok(()) } fn create_symlink_for_file(target: &Path, link_name: &Path) -> io::Result<()> { let absolute_path = fs::canonicalize(target)?; #[cfg(unix)] { unix::fs::symlink(absolute_path, link_name) } #[cfg(windows)] { std::os::windows::fs::symlink_file(target, link_name) } }