toasty_cli/migration/
drop.rs1use super::HistoryFile;
2use crate::{Config, theme::dialoguer_theme};
3use anyhow::Result;
4use clap::Parser;
5use console::style;
6use dialoguer::Select;
7use std::fs;
8use toasty::Db;
9
10#[derive(Parser, Debug)]
17pub struct DropCommand {
18 #[arg(short, long)]
20 name: Option<String>,
21
22 #[arg(short, long)]
24 latest: bool,
25}
26
27impl DropCommand {
28 pub(crate) fn run(self, _db: &Db, config: &Config) -> Result<()> {
29 let history_path = config.migration.get_history_file_path();
30 let mut history = HistoryFile::load_or_default(&history_path)?;
31
32 if history.migrations().is_empty() {
33 eprintln!("{}", style("No migrations found in history").red().bold());
34 anyhow::bail!("No migrations found in history");
35 }
36
37 let migration_index = if self.latest {
39 history.migrations().len() - 1
41 } else if let Some(name) = &self.name {
42 history
44 .migrations()
45 .iter()
46 .position(|m| m.name == *name)
47 .ok_or_else(|| anyhow::anyhow!("Migration '{}' not found", name))?
48 } else {
49 println!();
51 println!(" {}", style("Drop Migration").cyan().bold().underlined());
52 println!();
53
54 let migration_display: Vec<String> = history
55 .migrations()
56 .iter()
57 .map(|m| format!(" {}", m.name))
58 .collect();
59
60 Select::with_theme(&dialoguer_theme())
61 .with_prompt(" Select migration to drop")
62 .items(&migration_display)
63 .default(migration_display.len() - 1)
64 .interact()?
65 };
66
67 println!();
68
69 let migration = &history.migrations()[migration_index];
70 let migration_name = migration.name.clone();
71 let snapshot_name = migration.snapshot_name.clone();
72
73 let migration_path = config.migration.get_migrations_dir().join(&migration_name);
75 if migration_path.exists() {
76 fs::remove_file(&migration_path)?;
77 println!(
78 " {} {}",
79 style("✓").green().bold(),
80 style(format!("Deleted migration: {}", migration_name)).dim()
81 );
82 } else {
83 println!(
84 " {} {}",
85 style("⚠").yellow().bold(),
86 style(format!("Migration file not found: {}", migration_name))
87 .yellow()
88 .dim()
89 );
90 }
91
92 let snapshot_path = config.migration.get_snapshots_dir().join(&snapshot_name);
94 if snapshot_path.exists() {
95 fs::remove_file(&snapshot_path)?;
96 println!(
97 " {} {}",
98 style("✓").green().bold(),
99 style(format!("Deleted snapshot: {}", snapshot_name)).dim()
100 );
101 } else {
102 println!(
103 " {} {}",
104 style("⚠").yellow().bold(),
105 style(format!("Snapshot file not found: {}", snapshot_name))
106 .yellow()
107 .dim()
108 );
109 }
110
111 history.remove_migration(migration_index);
113 history.save(&history_path)?;
114
115 println!(
116 " {} {}",
117 style("✓").green().bold(),
118 style("Updated migration history").dim()
119 );
120 println!();
121 println!(
122 " {} {}",
123 style("").magenta(),
124 style(format!(
125 "Migration '{}' successfully dropped",
126 migration_name
127 ))
128 .green()
129 .bold()
130 );
131 println!();
132
133 Ok(())
134 }
135}