morph_cli/core/
manifest.rs1use std::fs;
2use std::path::{Path, PathBuf};
3use anyhow::{Result, Context};
4use serde::{Serialize, Deserialize};
5
6#[derive(Debug, Serialize, Deserialize, Clone)]
7pub struct MigrationManifest {
8 pub profile_name: Option<String>,
9 pub recipes: Vec<String>,
10 pub target_path: PathBuf,
11 pub write: bool,
12 pub dry_run: bool,
13 pub allow_risky: bool,
14 pub strict: bool,
15 pub autofix: bool,
16 pub review: bool,
17 pub verbose: bool,
18 pub summary_only: bool,
19}
20
21impl MigrationManifest {
22 pub fn load_from_file(path: &Path) -> Result<Self> {
23 let content = fs::read_to_string(path)
24 .with_context(|| format!("Failed to read manifest file: {}", path.display()))?;
25
26 let ext = path.extension().and_then(|s| s.to_str()).unwrap_or("");
27 if ext == "json" {
28 serde_json::from_str(&content)
29 .with_context(|| "Failed to parse JSON manifest")
30 } else {
31 toml::from_str(&content)
32 .with_context(|| "Failed to parse TOML manifest")
33 }
34 }
35
36 pub fn save_to_file(&self, path: &Path) -> Result<()> {
37 let ext = path.extension().and_then(|s| s.to_str()).unwrap_or("");
38 let content = if ext == "json" {
39 serde_json::to_string_pretty(self)
40 .with_context(|| "Failed to serialize JSON manifest")?
41 } else {
42 toml::to_string_pretty(self)
43 .with_context(|| "Failed to serialize TOML manifest")?
44 };
45
46 if let Some(parent) = path.parent() {
47 fs::create_dir_all(parent)?;
48 }
49 fs::write(path, content)
50 .with_context(|| format!("Failed to write manifest file: {}", path.display()))?;
51 Ok(())
52 }
53}