diff --git a/migra-cli/src/commands/upgrade.rs b/migra-cli/src/commands/upgrade.rs index 48fb980..c83829e 100644 --- a/migra-cli/src/commands/upgrade.rs +++ b/migra-cli/src/commands/upgrade.rs @@ -1,39 +1,41 @@ use crate::database::migration::*; +use crate::opts::UpgradeCommandOpt; use crate::Config; use crate::StdResult; use std::convert::TryFrom; -pub(crate) fn upgrade_pending_migrations(config: Config) -> StdResult<()> { +pub(crate) fn upgrade_pending_migrations(config: Config, opts: UpgradeCommandOpt) -> StdResult<()> { let mut manager = MigrationManager::try_from(&config)?; let applied_migration_names = manager.applied_migration_names()?; let migrations = config.migrations()?; - if is_up_to_date_migrations(&migrations, &applied_migration_names) { + let pending_migrations = filter_pending_migrations(migrations, &applied_migration_names); + if pending_migrations.is_empty() { println!("Up to date"); + } else if let Some(migration_name) = opts.migration_name { + let target_migration = pending_migrations + .iter() + .find(|m| m.name() == &migration_name); + match target_migration { + Some(migration) => { + print_migration_info(migration); + manager.upgrade(migration)?; + } + None => { + eprintln!(r#"Cannot find migration with "{}" name"#, migration_name); + } + } } else { - let pending_migrations = filter_pending_migrations(migrations, &applied_migration_names); - upgrade_all_pending_migrations(manager, &pending_migrations)?; + for migration in pending_migrations.iter() { + print_migration_info(migration); + manager.upgrade(migration)?; + } } Ok(()) } -fn is_up_to_date_migrations(migrations: &[Migration], applied_migration_names: &[String]) -> bool { - migrations.is_empty() || migrations.last().map(|m| m.name()) == applied_migration_names.first() -} - -fn upgrade_all_pending_migrations( - mut manager: ManagerT, - pending_migrations: &[Migration], -) -> StdResult<()> -where - ManagerT: Sized + DatabaseMigrationManager, -{ - for migration in pending_migrations.iter() { - println!("upgrade {}...", migration.name()); - manager.upgrade(migration)?; - } - - Ok(()) +fn print_migration_info(migration: &Migration) { + println!("upgrade {}...", migration.name()); } diff --git a/migra-cli/src/main.rs b/migra-cli/src/main.rs index 321ded4..d8e4526 100644 --- a/migra-cli/src/main.rs +++ b/migra-cli/src/main.rs @@ -31,9 +31,9 @@ fn main() -> StdResult<()> { let config = Config::read(opt.config)?; commands::print_migration_lists(config)?; } - Command::Upgrade => { + Command::Upgrade(opts) => { let config = Config::read(opt.config)?; - commands::upgrade_pending_migrations(config)?; + commands::upgrade_pending_migrations(config, opts)?; } Command::Downgrade(opts) => { let config = Config::read(opt.config)?; diff --git a/migra-cli/src/opts.rs b/migra-cli/src/opts.rs index e3ed40c..b62abaf 100644 --- a/migra-cli/src/opts.rs +++ b/migra-cli/src/opts.rs @@ -24,7 +24,7 @@ pub(crate) enum Command { List, #[structopt(name = "upgrade", visible_alias = "up")] - Upgrade, + Upgrade(UpgradeCommandOpt), #[structopt(name = "downgrade", visible_alias = "down")] Downgrade(DowngradeCommandOpt), @@ -40,13 +40,22 @@ pub(crate) struct ApplyCommandOpt { #[derive(Debug, StructOpt)] pub(crate) struct MakeCommandOpt { + /// Name of the migration to create in specify directory. #[structopt(parse(from_str))] pub migration_name: String, } +#[derive(Debug, StructOpt)] +pub(crate) struct UpgradeCommandOpt { + /// Name of the existing migration that will update the schema + /// in the database. + #[structopt(long = "name")] + pub migration_name: Option, +} + #[derive(Debug, StructOpt)] pub(crate) struct DowngradeCommandOpt { - /// How many applied migrations do we have to rollback + /// How many applied migrations do we have to rollback. #[structopt(long = "number", short = "n", default_value = "1")] pub migrations_number: usize,