pub const WORLD_JSONL: &str = "world.jsonl";
pub fn find_world_jsonl(name: Option<&str>) -> std::io::Result<String> {
let worlds_dir = crate::paths::worlds_dir();
if let Some(n) = name {
let path = worlds_dir
.as_deref()
.map(|d| d.join(format!("{}.jsonl", n)));
if let Some(path) = &path
&& path.exists()
{
return Ok(path.to_string_lossy().into_owned());
}
return Err(named_world_not_found(n, path.as_deref()));
}
if let Some(worlds_dir) = worlds_dir.filter(|d| d.is_dir()) {
let mut best: Option<(std::time::SystemTime, std::path::PathBuf)> = None;
if let Ok(entries) = std::fs::read_dir(&worlds_dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.extension().and_then(|e| e.to_str()) != Some("jsonl") {
continue;
}
if let Ok(meta) = std::fs::metadata(&path) {
let mtime = meta.modified().unwrap_or(std::time::UNIX_EPOCH);
if best.as_ref().map(|(t, _)| mtime > *t).unwrap_or(true) {
best = Some((mtime, path));
}
}
}
}
if let Some((_, path)) = best {
return Ok(path.to_string_lossy().into_owned());
}
}
let mut dir = std::env::current_dir()?;
loop {
let candidate = dir.join(WORLD_JSONL);
if candidate.exists() {
return Ok(candidate.to_string_lossy().into_owned());
}
match dir.parent() {
Some(parent) => dir = parent.to_path_buf(),
None => {
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
format!(
"no world found: run `cn fetch-world` or create `{}`",
WORLD_JSONL,
),
));
}
}
}
}
fn named_world_not_found(name: &str, path: Option<&std::path::Path>) -> std::io::Error {
let message = match path {
Some(p) => format!("world '{}' not found at {}", name, p.display()),
None => format!("world '{}' not found: no project state directory", name),
};
std::io::Error::new(std::io::ErrorKind::NotFound, message)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_missing_named_world_names_the_file_it_looked_for() {
let path = std::path::Path::new("/proj/worlds/cn_test_no_such_world.jsonl");
let err = named_world_not_found("cn_test_no_such_world", Some(path));
assert_eq!(err.kind(), std::io::ErrorKind::NotFound);
let msg = err.to_string();
assert!(msg.contains("cn_test_no_such_world"), "message was: {msg}");
assert!(msg.contains(".jsonl"), "message was: {msg}");
}
#[test]
fn a_named_world_without_a_state_root_says_so() {
let err = named_world_not_found("main", None);
assert_eq!(err.kind(), std::io::ErrorKind::NotFound);
let msg = err.to_string();
assert!(msg.contains("main"), "message was: {msg}");
assert!(
msg.contains("no project state directory"),
"message was: {msg}"
);
}
#[test]
fn missing_named_world_is_a_not_found_error() {
let err = find_world_jsonl(Some("cn_test_no_such_world")).unwrap_err();
assert_eq!(err.kind(), std::io::ErrorKind::NotFound);
assert!(err.to_string().contains("cn_test_no_such_world"));
}
}