Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions butane_cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,29 @@ pub fn default_name() -> String {
Utc::now().format("%Y%m%d_%H%M%S%3f").to_string()
}

/// Parse comma-separated backend names and validate they exist.
pub fn parse_backends(backends_str: &str) -> Result<NonEmpty<Box<dyn Backend>>> {
let backend_names: Vec<&str> = backends_str
.split(',')
.map(|s| s.trim())
.filter(|s| !s.is_empty())
.collect();

if backend_names.is_empty() {
return Err(anyhow::anyhow!("No backends specified"));
}

let mut backends: Vec<Box<dyn Backend>> = Vec::new();

for name in backend_names {
let backend =
db::get_backend(name).ok_or_else(|| anyhow::anyhow!("Unknown backend: {}", name))?;
backends.push(backend);
}

Ok(NonEmpty::from_vec(backends).unwrap())
}

pub fn init(base_dir: &PathBuf, name: &str, connstr: &str, connect: bool) -> Result<()> {
if db::get_backend(name).is_none() {
eprintln!("Unknown backend {name}");
Expand All @@ -76,8 +99,13 @@ pub fn init(base_dir: &PathBuf, name: &str, connstr: &str, connect: bool) -> Res
}

/// Make a migration.
/// The backends are selected from the existing migrations, or the initialised connection.
pub fn make_migration(base_dir: &Path, name: Option<&String>) -> Result<()> {
///
/// The backends are selected from the CLI arg, existing migrations, or the initialised connection.
pub fn make_migration(
base_dir: &Path,
name: Option<&String>,
cli_backends: Option<NonEmpty<Box<dyn Backend>>>,
) -> Result<()> {
let name = match name {
Some(name) => format!("{}_{}", default_name(), name),
None => default_name(),
Expand All @@ -87,7 +115,10 @@ pub fn make_migration(base_dir: &Path, name: Option<&String>) -> Result<()> {
eprintln!("Migration {name} already exists");
std::process::exit(1);
}
let backends = load_backends(base_dir)?;
let backends = match cli_backends {
Some(backends) => backends,
None => load_backends(base_dir)?,
};

let created = ms.create_migration(&backends, &name, ms.latest().as_ref())?;
if created {
Expand Down
21 changes: 18 additions & 3 deletions butane_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use std::path::PathBuf;
use butane_cli::{
add_backend, base_dir, clean, clear_data, collapse_migrations, delete_table,
describe_migration, detach_latest_migration, embed, get_migrations, handle_error, init,
list_backends, list_migrations, make_migration, migrate, regenerate_migrations, remove_backend,
unmigrate,
list_backends, list_migrations, make_migration, migrate, parse_backends, regenerate_migrations,
remove_backend, unmigrate,
};
use clap::{ArgAction, Parser, Subcommand};

Expand Down Expand Up @@ -37,6 +37,9 @@ enum Commands {
MakeMigration {
/// Name to use for the migration.
name: String,
/// Comma-separated list of backends to use (e.g., "sqlite,pg")
#[arg(short = 'b', long)]
backends: Option<String>,
},
/// Detach the latest migration.
#[command(
Expand Down Expand Up @@ -173,7 +176,19 @@ fn main() {
BackendCommands::Remove { name } => handle_error(remove_backend(&base_dir, name)),
BackendCommands::List => handle_error(list_backends(&base_dir)),
},
Commands::MakeMigration { name } => handle_error(make_migration(&base_dir, Some(name))),
Commands::MakeMigration { name, backends } => {
let parsed_backends = match backends {
Some(backends_str) => match parse_backends(backends_str) {
Ok(backends) => Some(backends),
Err(e) => {
handle_error(Err(e));
return;
}
},
None => None,
};
handle_error(make_migration(&base_dir, Some(name), parsed_backends))
}
Commands::DescribeMigration { name } => handle_error(describe_migration(&base_dir, name)),
Commands::Regenerate => handle_error(regenerate_migrations(&base_dir)),
Commands::DetachMigration => handle_error(detach_latest_migration(&base_dir)),
Expand Down
Loading