proton_launch/command/
move_compat.rs

1use std::path::{Path, PathBuf};
2
3use crate::{paths::Paths, steam::SteamData};
4
5use super::{Runnable, RunnableResult};
6
7#[derive(Debug, Clone)]
8#[cfg_attr(feature = "commandline", derive(clap::ValueEnum))]
9enum MoveDirection {
10    /// Move the compat folder from the global save folder to a local folder named `compat`
11    GlobalToLocal,
12    /// Move the compat folder from the local `compat` folder to the global save folder
13    LocalToGlobal,
14}
15
16#[derive(Debug, Clone)]
17#[cfg_attr(feature = "commandline", derive(clap::Args))]
18pub struct MoveCompat {
19    /// Direction to move the compat folder
20    direction: MoveDirection,
21
22    /// Path to the game exe
23    exe: PathBuf,
24
25    /// Optional save name to use
26    /// If not specified, the game exe without the extension will be used
27    #[cfg_attr(feature = "commandline", clap(short, long))]
28    save_name: Option<String>,
29}
30
31impl Runnable for MoveCompat {
32    fn run(&self, paths: &Paths, _steam_data: &SteamData) -> RunnableResult<()> {
33        let save_name = self
34            .save_name
35            .as_deref()
36            .unwrap_or_else(|| self.exe.file_stem().unwrap().to_str().unwrap());
37        let global_compat_dir = paths.compat_dir(save_name);
38        let local_compat_dir = self.exe.parent().unwrap().join("compat");
39        println!("global exists: {}", global_compat_dir.exists());
40        println!("local exists: {}", local_compat_dir.exists());
41        match self.direction {
42            MoveDirection::GlobalToLocal => {
43                println!(
44                    "Moving compat folder from {} to {}",
45                    global_compat_dir.display(),
46                    local_compat_dir.display()
47                );
48                copy_file_tree(&global_compat_dir, &local_compat_dir).unwrap();
49            }
50            MoveDirection::LocalToGlobal => {
51                println!(
52                    "Moving compat folder from {} to {}",
53                    local_compat_dir.display(),
54                    global_compat_dir.display()
55                );
56                copy_file_tree(&local_compat_dir, &global_compat_dir).unwrap();
57            }
58        };
59        Ok(())
60    }
61}
62
63fn copy_file_tree(source: &Path, dest: &Path) -> Result<(), std::io::Error> {
64    std::fs::create_dir_all(dest)?;
65    for entry in walkdir::WalkDir::new(source) {
66        let entry = entry?;
67        let path = entry.path().strip_prefix(source).unwrap();
68        if entry.file_type().is_dir() {
69            std::fs::create_dir_all(&dest.join(path))?;
70        } else if entry.file_type().is_file() {
71            std::fs::copy(entry.path(), &dest.join(path))?;
72        }
73    }
74
75    Ok(())
76}