aprender_contracts_cli/commands/
migrate.rs1use 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}