use anstream::println;
use chrono::Utc;
use clap::Parser;
use eyre::eyre;
use owo_colors::OwoColorize;
use sha2::{Digest, Sha256};
use tracing::instrument;
use crate::{
Options,
db::get_db_adapter,
error::Result,
migration::{
dir::get_migrations_dir,
planner::{MigrationState, Planner},
},
};
#[derive(Debug, Parser)]
pub struct Rollup {}
impl Rollup {
#[instrument(name = "rollup", skip_all)]
pub(crate) fn run(&self, opts: &Options) -> Result {
let migrations_dir = get_migrations_dir(opts);
let local = migrations_dir.load()?;
let mut db = get_db_adapter(opts, false)?;
if Planner::new(opts)?
.status()?
.iter()
.any(|s| s.state != MigrationState::Applied)
{
return Err(eyre!(
"cannot rollup when there are pending, variant, or divergent migrations"
));
}
let url = opts.get_url()?;
let up_sql = String::from_utf8_lossy(&db.dump_schema(url, true)?).into_owned();
let ts = Utc::now();
let compound_name = format!("{}_rollup", ts.format("%Y%m%d%H%M%S"));
let mut hasher = Sha256::new();
hasher.update(up_sql.as_bytes());
let hash = hex::encode(hasher.finalize());
let seed_sql = String::from_utf8_lossy(&db.dump_data(url, true)?).into_owned();
migrations_dir.create_migration(&compound_name, Some(&up_sql), Some(&seed_sql))?;
db.clear_migrations()?;
db.record_baseline(&compound_name, &hash)?;
local
.iter()
.filter(|m| m.name != "init")
.try_for_each(|m| {
println!("{} {}", "Rolled up".cyan(), m.compound_name);
migrations_dir.remove_migration(&m.compound_name)
})?;
Ok(())
}
}