use std::path::{Path, PathBuf};
pub fn find_legacy_v1_db(start: &Path) -> Option<PathBuf> {
let mut cur = start.to_path_buf();
loop {
let legacy = cur.join(".synth").join("main.db");
if legacy.is_file() {
return Some(legacy);
}
if !cur.pop() {
break;
}
}
None
}
pub fn legacy_migration_error(legacy_db: &Path) -> anyhow::Error {
let target = legacy_db
.parent()
.and_then(|p| p.parent())
.map(|p| p.join("claims"))
.unwrap_or_else(|| PathBuf::from("claims"));
anyhow::anyhow!(
"found v1 database at `{legacy}` but no v2 `claims/` directory in scope.\n\
\n\
synthesist v2 stores data in `claims/` (Automerge claim log + SQLite view).\n\
Port your v1 data before using v2 commands here:\n\
\n\
\u{20}\u{20}# dry-run first, then migrate\n\
\u{20}\u{20}synthesist migrate v1-to-v2 --from {legacy} --to {target} --dry-run\n\
\u{20}\u{20}synthesist migrate v1-to-v2 --from {legacy} --to {target}\n\
\n\
See MIGRATION.md in the synthesist repo for rollback + verification.\n\
If the v1 db is obsolete and you want a fresh v2 estate here,\n\
remove `.synth/` first.",
legacy = legacy_db.display(),
target = target.display(),
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn find_legacy_returns_none_for_clean_dir() {
let tmp = tempfile::tempdir().unwrap();
assert!(find_legacy_v1_db(tmp.path()).is_none());
}
#[test]
fn find_legacy_walks_upward() {
let tmp = tempfile::tempdir().unwrap();
std::fs::create_dir_all(tmp.path().join(".synth")).unwrap();
std::fs::write(tmp.path().join(".synth/main.db"), b"fake").unwrap();
let nested = tmp.path().join("a/b/c");
std::fs::create_dir_all(&nested).unwrap();
let found = find_legacy_v1_db(&nested).expect("walks up");
assert!(found.ends_with(".synth/main.db"));
}
#[test]
fn legacy_error_names_target_dir() {
let tmp = tempfile::tempdir().unwrap();
let db = tmp.path().join(".synth/main.db");
let err = legacy_migration_error(&db).to_string();
assert!(err.contains("v1 database"));
assert!(err.contains("synthesist migrate v1-to-v2"));
assert!(err.contains("MIGRATION.md"));
assert!(err.contains(&tmp.path().join("claims").display().to_string()));
}
}