Files
fomod-manager/src/linker.rs
2026-03-02 23:00:24 +01:00

82 lines
2.2 KiB
Rust

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<Path>,
) -> 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<Path>,
target: impl AsRef<Path>,
) -> 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<Path>,
) -> 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)
}
}