use std::path::Path;
use std::sync::OnceLock;
pub(crate) fn warn_if_vault_present(suppress: bool) {
if suppress {
return;
}
static FIRED: OnceLock<()> = OnceLock::new();
if FIRED.get().is_some() {
return;
}
let vault = crate::paths::wonka_vault_archives_dir();
if !vault_has_snapshots(&vault) {
return;
}
eprintln!(
"note: {} contains historical session data not in the codex.\n \
Run `mx codex archive --backfill` to ingest, then remove the vault directory.",
vault.display()
);
let _ = FIRED.set(());
}
fn vault_has_snapshots(vault_path: &Path) -> bool {
let entries = match std::fs::read_dir(vault_path) {
Ok(e) => e,
Err(_) => return false,
};
for entry in entries.flatten() {
if !entry.path().is_dir() {
continue;
}
match entry.file_name().to_str() {
Some(name) if name.starts_with("session-") => return true,
_ => continue,
}
}
false
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
#[test]
fn vault_missing_is_silent() {
let tmp = tempfile::tempdir().unwrap();
let bogus = tmp.path().join("does-not-exist");
assert!(!vault_has_snapshots(&bogus));
}
#[test]
fn vault_present_but_empty_is_silent() {
let tmp = tempfile::tempdir().unwrap();
let vault = tmp.path().join("empty-vault");
fs::create_dir_all(&vault).unwrap();
assert!(!vault_has_snapshots(&vault));
}
#[test]
fn vault_with_only_junk_files_is_silent() {
let tmp = tempfile::tempdir().unwrap();
let vault = tmp.path().join("junk-vault");
fs::create_dir_all(&vault).unwrap();
fs::write(vault.join("README.txt"), "hi").unwrap();
fs::create_dir_all(vault.join("other-dir")).unwrap();
assert!(!vault_has_snapshots(&vault));
}
#[test]
fn vault_with_one_snapshot_fires() {
let tmp = tempfile::tempdir().unwrap();
let vault = tmp.path().join("real-vault");
fs::create_dir_all(vault.join("session-20260311-202812-631046")).unwrap();
assert!(vault_has_snapshots(&vault));
}
#[test]
fn warning_text_uses_archive_subcommand() {
let tmp = tempfile::tempdir().unwrap();
let vault = tmp.path().join("real-vault");
fs::create_dir_all(vault.join("session-20260311-202812-631046")).unwrap();
assert!(vault_has_snapshots(&vault));
let msg = format!(
"note: {} contains historical session data not in the codex.\n \
Run `mx codex archive --backfill` to ingest, then remove the vault directory.",
vault.display()
);
assert!(
msg.contains("mx codex archive --backfill"),
"vault-warning string must reference `mx codex archive --backfill`: {msg}"
);
let src = include_str!("notices.rs");
let func_start = src.find("pub(crate) fn warn_if_vault_present").unwrap();
let func_end = src[func_start..].find("\n}\n").unwrap() + func_start;
let func_body = &src[func_start..func_end];
assert!(
func_body.contains("mx codex archive --backfill"),
"warn_if_vault_present must emit `mx codex archive --backfill`"
);
assert!(
!func_body.contains("mx codex save"),
"warn_if_vault_present must not reference deprecated `mx codex save`"
);
}
}