Skip to main content

morph_cli/core/
manifest.rs

1use 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}