dev_prune/adapters/
cocos.rs1use super::{BloatDir, EnforcePolicy, PackageManager, dir_size};
24use anyhow::{Result, anyhow};
25use std::fs;
26use std::path::Path;
27
28const MANIFEST: &str = "package.json";
31
32const CACHE_DIRS: &[&str] = &["library", "temp"];
34
35fn is_creator_manifest(content: &str) -> bool {
38 content.contains("\"creator\"") || content.contains("cocos-creator")
39}
40
41pub struct Cocos;
43
44impl PackageManager for Cocos {
45 fn name(&self) -> &'static str {
46 "cocos"
47 }
48
49 fn detect(&self, path: &Path) -> bool {
50 let manifest = path.join(MANIFEST);
51 manifest.is_file()
52 && fs::read_to_string(&manifest).is_ok_and(|content| is_creator_manifest(&content))
53 }
54
55 fn bloat_dirs(&self, path: &Path) -> Vec<BloatDir> {
56 CACHE_DIRS
57 .iter()
58 .map(|name| path.join(name))
59 .filter(|dir| dir.is_dir())
60 .map(|dir| BloatDir {
61 name: dir
62 .file_name()
63 .unwrap_or_default()
64 .to_string_lossy()
65 .into_owned(),
66 size_bytes: dir_size(&dir),
67 path: dir,
68 shared_bytes: 0,
69 })
70 .collect()
71 }
72
73 fn enforce_lockfile(&self, path: &Path, _policy: EnforcePolicy) -> Result<()> {
78 let manifest = path.join(MANIFEST);
79 let content = fs::read_to_string(&manifest).map_err(|e| {
80 anyhow!("`{MANIFEST}` could not be read ({e}): nothing to re-import the assets from.")
81 })?;
82 if !is_creator_manifest(&content) {
83 return Err(anyhow!(
84 "`{MANIFEST}` no longer names Cocos Creator: refusing to treat the \
85 imported-asset cache as regenerable from it."
86 ));
87 }
88 Ok(())
89 }
90
91 fn restore(&self, _path: &Path, _timeout: std::time::Duration) -> Result<()> {
92 println!(
93 "Cocos Creator's imported-asset cache regenerates when the editor next \
94 opens the project"
95 );
96 Ok(())
97 }
98
99 fn lockfiles(&self) -> &'static [&'static str] {
100 &[MANIFEST]
101 }
102
103 fn opt_in(&self) -> bool {
104 true
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111 use std::path::PathBuf;
112 use tempfile::tempdir;
113
114 fn project(dir: &Path) -> PathBuf {
116 fs::write(
117 dir.join(MANIFEST),
118 "{\n \"name\": \"demo\",\n \"creator\": {\n \"version\": \"3.8.0\"\n }\n}\n",
119 )
120 .unwrap();
121 dir.to_path_buf()
122 }
123
124 fn claimed(project: &Path) -> Vec<String> {
125 Cocos
126 .bloat_dirs(project)
127 .into_iter()
128 .map(|b| b.name)
129 .collect()
130 }
131
132 #[test]
133 fn detects_on_a_creator_manifest_only() {
134 let dir = tempdir().unwrap();
135 assert!(!Cocos.detect(dir.path()));
136 fs::write(
138 dir.path().join(MANIFEST),
139 "{\n \"name\": \"demo\",\n \"dependencies\": {}\n}\n",
140 )
141 .unwrap();
142 assert!(!Cocos.detect(dir.path()));
143 project(dir.path());
144 assert!(Cocos.detect(dir.path()));
145 }
146
147 #[test]
148 fn a_creator_2x_engine_line_also_detects() {
149 let dir = tempdir().unwrap();
150 fs::write(
151 dir.path().join(MANIFEST),
152 "{\n \"name\": \"demo\",\n \"engine\": \"cocos-creator-js\",\n \"version\": \"2.4.13\"\n}\n",
153 )
154 .unwrap();
155 assert!(Cocos.detect(dir.path()));
156 }
157
158 #[test]
159 fn the_caches_are_claimed_and_the_exported_build_is_not() {
160 let dir = tempdir().unwrap();
163 let root = project(dir.path());
164 fs::create_dir(root.join("library")).unwrap();
165 fs::write(root.join("library").join("imports.json"), "cache").unwrap();
166 fs::create_dir(root.join("temp")).unwrap();
167 fs::create_dir(root.join("build")).unwrap();
168 fs::create_dir(root.join("assets")).unwrap();
169
170 assert_eq!(claimed(&root), vec!["library", "temp"]);
171 }
172
173 #[test]
174 fn a_missing_or_bogus_manifest_is_refused() {
175 let dir = tempdir().unwrap();
176 let policy = EnforcePolicy::default();
177 assert!(Cocos.enforce_lockfile(dir.path(), policy).is_err());
178 fs::write(dir.path().join(MANIFEST), "{\"name\": \"demo\"}").unwrap();
179 assert!(Cocos.enforce_lockfile(dir.path(), policy).is_err());
180 project(dir.path());
181 assert!(Cocos.enforce_lockfile(dir.path(), policy).is_ok());
182 }
183
184 #[test]
185 fn cocos_is_opt_in() {
186 assert!(Cocos.opt_in());
187 }
188}