1use super::Result;
2use crate::{
3 addon::{Addon, AddonFolder},
4 parse::parse_toc_path,
5};
6use std::collections::HashSet;
7use std::fs::{remove_dir_all, remove_file};
8use std::path::Path;
9use walkdir::WalkDir;
10
11pub fn delete_addons(addon_folders: &[AddonFolder]) -> Result<()> {
13 for folder in addon_folders {
14 let path = &folder.path;
15 if path.exists() {
16 remove_dir_all(path)?;
17 }
18 }
19
20 Ok(())
21}
22
23pub fn delete_saved_variables(addon_folders: &[AddonFolder], wtf_path: &Path) -> Result<()> {
25 for entry in WalkDir::new(&wtf_path)
26 .into_iter()
27 .filter_map(std::result::Result::ok)
28 {
29 let path = entry.path();
30 let parent_name = path
31 .parent()
32 .and_then(|a| a.file_name())
33 .and_then(|a| a.to_str());
34
35 if parent_name == Some("SavedVariables") {
36 let file_name = path
37 .file_stem()
38 .and_then(|a| a.to_str())
39 .map(|a| a.trim_end_matches(".bak"));
40
41 if let Some(file_name_str) = file_name {
43 for folder in addon_folders {
44 if file_name_str == folder.id {
45 remove_file(path)?;
46 }
47 }
48 }
49 }
50 }
51
52 Ok(())
53}
54
55pub async fn install_addon(
59 addon: &Addon,
60 from_directory: &Path,
61 to_directory: &Path,
62) -> Result<Vec<AddonFolder>> {
63 let zip_path = from_directory.join(&addon.primary_folder_id);
64 let mut zip_file = std::fs::File::open(&zip_path)?;
65 let mut archive = zip::ZipArchive::new(&mut zip_file)?;
66
67 for folder in addon.folders.iter() {
69 let path = &folder.path;
70 if path.exists() {
71 remove_dir_all(path)?;
72 }
73 }
74
75 let new_top_level_folders = archive
77 .file_names()
78 .filter_map(|name| name.split('/').next())
79 .collect::<HashSet<_>>();
80
81 for folder in new_top_level_folders {
83 let path = to_directory.join(&folder);
84
85 if path.exists() {
86 let _ = std::fs::remove_dir_all(path);
87 }
88 }
89
90 let mut toc_files = vec![];
91
92 for i in 0..archive.len() {
93 let mut file = archive.by_index(i)?;
94 #[allow(deprecated)]
95 let path = to_directory.join(file.sanitized_name());
96
97 if let Some(ext) = path.extension() {
98 if let Ok(remainder) = path.strip_prefix(to_directory) {
99 if ext == "toc" && remainder.components().count() == 2 {
100 toc_files.push(path.clone());
101 }
102 }
103 }
104
105 if file.is_dir() {
106 std::fs::create_dir_all(&path)?;
107 } else {
108 if let Some(p) = path.parent() {
109 if !p.exists() {
110 std::fs::create_dir_all(&p)?;
111 }
112 }
113 let mut outfile = std::fs::File::create(&path)?;
114 std::io::copy(&mut file, &mut outfile)?;
115 }
116 }
117
118 std::fs::remove_file(&zip_path)?;
120
121 let mut addon_folders: Vec<_> = toc_files
122 .iter()
123 .filter_map(|p| parse_toc_path(&p))
124 .collect();
125 addon_folders.sort();
126
127 Ok(addon_folders)
128}