thunderstore_engine/profile/
cache.rs1#![deny(missing_docs)]
8
9use crate::error::{Error, Result};
10use crate::extract::{extract_zip, should_extract};
11use std::path::{Path, PathBuf};
12
13pub fn package_cache_dir(base: &Path, game: &str, full_name: &str, version: &str) -> PathBuf {
16 base.join(game).join("cache").join(full_name).join(version)
17}
18
19pub fn ensure_extracted(
23 base: &Path,
24 game: &str,
25 full_name: &str,
26 version: &str,
27 archive: &Path,
28) -> Result<PathBuf> {
29 let dir = package_cache_dir(base, game, full_name, version);
30
31 if should_extract(&dir, version)? {
32 extract_zip(archive, &dir)?;
33 }
34
35 if !dir.exists() {
36 return Err(Error::Profile(format!(
37 "package cache {} missing after extraction",
38 dir.display()
39 )));
40 }
41
42 Ok(dir)
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use std::io::{Cursor, Write};
49 use tempfile::tempdir;
50 use zip::write::{FileOptions, ZipWriter};
51
52 fn build_zip() -> Vec<u8> {
53 let mut zip = ZipWriter::new(Cursor::new(Vec::new()));
54 let opts: FileOptions<'_, ()> =
55 FileOptions::default().compression_method(zip::CompressionMethod::Stored);
56
57 zip.start_file("manifest.json", opts).unwrap();
58 zip.write_all(br#"{"version_number":"1.0.0"}"#).unwrap();
59 zip.start_file("plugins/Mod.dll", opts).unwrap();
60 zip.write_all(b"dll").unwrap();
61
62 zip.finish().unwrap().into_inner()
63 }
64
65 #[test]
66 fn ensure_extracted_places_and_is_idempotent() {
67 let dir = tempdir().unwrap();
68 let base = dir.path();
69
70 let archive = base.join("Author-Mod-1.0.0.zip");
71 std::fs::write(&archive, build_zip()).unwrap();
72
73 let out = ensure_extracted(base, "valheim", "Author-Mod", "1.0.0", &archive).unwrap();
74
75 assert_eq!(
76 out,
77 package_cache_dir(base, "valheim", "Author-Mod", "1.0.0")
78 );
79 assert!(out.join("plugins/Mod.dll").exists());
80
81 let again = ensure_extracted(base, "valheim", "Author-Mod", "1.0.0", &archive).unwrap();
83
84 assert!(again.join("plugins/Mod.dll").exists());
85 }
86}