Skip to main content

aprender_contracts_cli/commands/
migrate.rs

1use std::path::{Path, PathBuf};
2
3pub fn run(contract_dir: &Path, dry_run: bool) -> Result<(), Box<dyn std::error::Error>> {
4    eprintln!("pv migrate — contract schema migration");
5    eprintln!("=========================================\n");
6
7    let count = scan_and_report(contract_dir, dry_run)?;
8    print_summary(contract_dir, dry_run, count);
9    Ok(())
10}
11
12fn scan_and_report(contract_dir: &Path, dry_run: bool) -> std::io::Result<usize> {
13    let mut count = 0;
14    for entry in std::fs::read_dir(contract_dir)?.flatten() {
15        let path = entry.path();
16        if path.extension().and_then(|e| e.to_str()) != Some("yaml") {
17            continue;
18        }
19        if needs_migration(&path)? {
20            report_migration(&path, dry_run);
21            count += 1;
22        }
23    }
24    Ok(count)
25}
26
27fn needs_migration(path: &PathBuf) -> std::io::Result<bool> {
28    let content = std::fs::read_to_string(path)?;
29    Ok(!content.contains("metadata:")
30        || (!content.contains("proof_obligations:") && !content.contains("registry: true")))
31}
32
33fn report_migration(path: &Path, dry_run: bool) {
34    if dry_run {
35        eprintln!("  [MIGRATE] {}", path.display());
36    } else {
37        eprintln!(
38            "  [MIGRATE] {} (auto-fix not yet implemented)",
39            path.display()
40        );
41    }
42}
43
44fn print_summary(contract_dir: &Path, dry_run: bool, count: usize) {
45    if count == 0 {
46        eprintln!(
47            "  All contracts in {} use current schema.",
48            contract_dir.display()
49        );
50        return;
51    }
52    eprintln!("\n{count} contract(s) need migration.");
53    if dry_run {
54        eprintln!("Run without --dry-run to apply fixes.");
55    }
56}