concinnity_dev/authoring/
rm.rs1use crate::world::{WORLD_JSONL, known_names, patch_world_jsonl};
5use concinnity_cook::build_from_path;
6
7pub fn rm_at_path(world_path: &str, name: &str) -> std::io::Result<()> {
12 let mut removed = false;
13
14 patch_world_jsonl(world_path, |assets| {
15 if let Some(i) = assets
16 .iter()
17 .position(|a| a.get("name").and_then(|v| v.as_str()) == Some(name))
18 {
19 let asset = assets.remove(i);
20 tracing::info!(
21 "Removed '{}' (type: {})",
22 name,
23 asset.get("type").and_then(|v| v.as_str()).unwrap_or("?"),
24 );
25 removed = true;
26 }
27 })?;
28
29 if !removed {
30 let known = known_names(world_path).unwrap_or_default();
31 if known.is_empty() {
32 return Err(std::io::Error::new(
33 std::io::ErrorKind::InvalidInput,
34 format!(
35 "no asset named '{}' in {} (no assets declared)",
36 name, WORLD_JSONL
37 ),
38 ));
39 }
40 return Err(std::io::Error::new(
41 std::io::ErrorKind::InvalidInput,
42 format!(
43 "no asset named '{}' in {}\nKnown names: {}",
44 name,
45 WORLD_JSONL,
46 known.join(", ")
47 ),
48 ));
49 }
50
51 build_from_path(
52 &crate::project::require()?,
53 world_path,
54 crate::cook_platform(),
55 )
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
66 fn rm_of_a_missing_world_file_errors() {
67 let dir = tempfile::tempdir().unwrap();
68 let path = dir.path().join("missing.jsonl");
69 assert!(rm_at_path(path.to_str().unwrap(), "anything").is_err());
70 }
71
72 #[test]
73 fn rm_of_an_unknown_name_lists_the_known_names() {
74 let dir = tempfile::tempdir().unwrap();
75 let path = dir.path().join("world.jsonl");
76 std::fs::write(
77 &path,
78 concat!(
79 "{\"name\":\"log\",\"type\":\"Logger\",\"args\":{}}\n",
80 "{\"name\":\"log2\",\"type\":\"Logger\",\"args\":{}}\n",
81 ),
82 )
83 .unwrap();
84
85 let err = rm_at_path(path.to_str().unwrap(), "ghost").unwrap_err();
86 assert_eq!(err.kind(), std::io::ErrorKind::InvalidInput);
87 let msg = err.to_string();
88 assert!(msg.contains("no asset named 'ghost'"), "got: {msg}");
89 assert!(msg.contains("Known names: log, log2"), "got: {msg}");
90 let survived = std::fs::read_to_string(&path).unwrap();
92 assert!(survived.contains("\"log\""));
93 assert!(survived.contains("\"log2\""));
94 }
95
96 #[test]
97 fn rm_from_an_empty_world_reports_no_assets() {
98 let dir = tempfile::tempdir().unwrap();
99 let path = dir.path().join("world.jsonl");
100 std::fs::write(&path, "").unwrap();
101
102 let err = rm_at_path(path.to_str().unwrap(), "ghost").unwrap_err();
103 assert_eq!(err.kind(), std::io::ErrorKind::InvalidInput);
104 assert!(err.to_string().contains("no assets declared"), "got: {err}");
105 }
106}