Skip to content

Commit

Permalink
Merge pull request #28 from iamsauravsharma/use-migrator-command
Browse files Browse the repository at this point in the history
feat!: direcly provides MigrationCommand to create cli
  • Loading branch information
iamsauravsharma committed Jan 6, 2024
2 parents d9029e9 + 7107371 commit 666c7ac
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 37 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/publish.yml
Expand Up @@ -3,6 +3,9 @@ on:
push:
tags: "v*"

permissions:
contents: write

jobs:
publish_crate:
name: Publish to crates.io
Expand Down
36 changes: 32 additions & 4 deletions README.MD
Expand Up @@ -95,7 +95,7 @@ impl Migration<sqlx::Postgres> for FirstMigration {
}

// use parents function to add parents of a migrations.
fn parents(&self) -> Vec<Box<dyn Migration<DB>>> {
fn parents(&self) -> Vec<Box<dyn Migration<sqlx::Postgres>>> {
vec![]
}

Expand Down Expand Up @@ -133,10 +133,37 @@ migrator.apply_all(&pool).await.unwrap();
migrator.revert_all(&pool).await.unwrap();
```

Or you can create cli
Or you can create cli using

```rust
sqlx_migrator::cli::run(Box::new(migrator), &pool).await.unwrap();
use sqlx_migrator::cli::MigrationCommand;
MigrationCommand::parse_and_run(Box::new(migrator), &pool).await.unwrap();
```

If you want to extend your own clap based cli then you can add migrator to sub command enum and then run migrator
```rust
#[derive(clap::Parser)]
struct Cli {
#[command(subcommand)]
sub_command: CliSubcommand
}

#[derive(clap::Subcommand)]
enum CliSubcommand {
#[command()]
Migrator(sqlx_migrator::cli::MigrationCommand)
}

impl Cli {
async fn run() {
let cli = Self::parse();
match cli.sub_command {
Migrator(m) => {
m.run(Box::new(migrator), &pool).await.unwrap()
}
}
}
}
```

# Migrate from sqlx default sql based migration
Expand All @@ -152,7 +179,8 @@ Can be easily applied by following above usage docs where you only need to write
Then you can create cli for migrator

```rust
sqlx_migrator::cli::run(Box::new(migrator), &pool).await.unwrap();
use sqlx_migrator::cli::MigrationCommand;
MigrationCommand::parse_and_run(Box::new(migrator), &pool).await.unwrap();
```

and run fake apply cli command
Expand Down
3 changes: 2 additions & 1 deletion examples/mysql/main.rs
@@ -1,4 +1,5 @@
//! Example crate for mysql
use sqlx_migrator::cli::MigrationCommand;
use sqlx_migrator::migrator::{Info, Migrator};
use sqlx_migrator::sqlx::MySql;

Expand All @@ -10,7 +11,7 @@ async fn main() {
let mut migrator = Migrator::default();
migrator.add_migrations(migrations::migrations());
// There are two way to run migration. Either you can create cli as shown below
sqlx_migrator::cli::run(Box::new(migrator), &pool)
MigrationCommand::parse_and_run(Box::new(migrator), &pool)
.await
.unwrap();
// Or you can directly use migrator apply_all function instead of creating
Expand Down
3 changes: 2 additions & 1 deletion examples/postgres/main.rs
@@ -1,4 +1,5 @@
//! Example crate for postgres
use sqlx_migrator::cli::MigrationCommand;
use sqlx_migrator::migrator::{Info, Migrator};
use sqlx_migrator::sqlx::Postgres;

Expand All @@ -10,7 +11,7 @@ async fn main() {
let mut migrator = Migrator::default().with_prefix("prefix").unwrap();
migrator.add_migrations(migrations::migrations());
// There are two way to run migration. Either you can create cli as shown below
sqlx_migrator::cli::run(Box::new(migrator), &pool)
MigrationCommand::parse_and_run(Box::new(migrator), &pool)
.await
.unwrap();
// Or you can directly use migrator apply_all function instead of creating
Expand Down
3 changes: 2 additions & 1 deletion examples/sqlite/main.rs
@@ -1,4 +1,5 @@
//! Example crate for sqlite
use sqlx_migrator::cli::MigrationCommand;
use sqlx_migrator::migrator::{Info, Migrator};
use sqlx_migrator::sqlx::Sqlite;

Expand All @@ -10,7 +11,7 @@ async fn main() {
let mut migrator = Migrator::default();
migrator.add_migrations(migrations::migrations());
// There are two way to run migration. Either you can create cli as shown below
sqlx_migrator::cli::run(Box::new(migrator), &pool)
MigrationCommand::parse_and_run(Box::new(migrator), &pool)
.await
.unwrap();
// Or you can directly use migrator apply_all function instead of creating
Expand Down
66 changes: 39 additions & 27 deletions src/cli.rs
Expand Up @@ -8,15 +8,48 @@ use sqlx::Pool;
use crate::error::Error;
use crate::migrator::{Migrate, Plan};

/// Migration command for performing rust based sqlx migrations
#[derive(Parser, Debug)]
struct Args {
pub struct MigrationCommand {
#[command(subcommand)]
sub_command: SubCommand,
}

impl MigrationCommand {
/// Parse `MigrationCommand` and run migration command line interface
///
/// # Errors
/// If migration command fails to complete and raise some issue
pub async fn parse_and_run<DB>(
migrator: Box<dyn Migrate<DB>>,
pool: &Pool<DB>,
) -> Result<(), Error>
where
DB: sqlx::Database,
{
let migration_command = Self::parse();
migration_command.run(migrator, pool).await
}

/// Run migration command line interface
///
/// # Errors
/// If migration command fails to complete and raise some issue
pub async fn run<DB>(
&self,
migrator: Box<dyn Migrate<DB>>,
pool: &Pool<DB>,
) -> Result<(), Error>
where
DB: sqlx::Database,
{
self.sub_command.handle_subcommand(migrator, pool).await?;
Ok(())
}
}

#[derive(Subcommand, Debug)]
/// Subcommand for sqlx migrator cli
pub enum SubCommand {
enum SubCommand {
/// Apply migrations
#[command()]
Apply(Apply),
Expand All @@ -34,11 +67,7 @@ pub enum SubCommand {
}

impl SubCommand {
/// Handle all subcommand operations
///
/// # Errors
/// If any subcommand operations fail running
pub async fn handle_subcommand<DB>(
async fn handle_subcommand<DB>(
&self,
migrator: Box<dyn Migrate<DB>>,
pool: &Pool<DB>,
Expand Down Expand Up @@ -136,9 +165,8 @@ where
}

#[derive(Parser, Debug)]
/// CLI struct for apply subcommand
#[allow(clippy::struct_excessive_bools)]
pub struct Apply {
struct Apply {
/// App name up to which migration needs to be applied. If migration option
/// is also present than only till migration is applied
#[arg(long)]
Expand Down Expand Up @@ -242,9 +270,8 @@ impl Apply {
}

#[derive(Parser, Debug)]
/// CLI struct for revert subcommand
#[allow(clippy::struct_excessive_bools)]
pub struct Revert {
struct Revert {
/// Revert all migration. Conflicts with app args
#[arg(long, conflicts_with = "app")]
all: bool,
Expand Down Expand Up @@ -341,18 +368,3 @@ impl Revert {
Ok(())
}
}

/// Run full cli by parsing args with help of migrator. If you only need to add
/// subcommand to your app than use `SubCommand` enum `handle_subcommand`
/// function
///
/// # Errors
/// When command fails to run and raises error
pub async fn run<DB>(migrator: Box<dyn Migrate<DB>>, pool: &Pool<DB>) -> Result<(), Error>
where
DB: sqlx::Database,
{
let args = Args::parse();
args.sub_command.handle_subcommand(migrator, pool).await?;
Ok(())
}
6 changes: 3 additions & 3 deletions src/migrator/mod.rs
Expand Up @@ -222,9 +222,9 @@ pub trait Info<DB> {
let migration_parents = migration.parents();
let migration_replaces = migration.replaces();
let is_new_value = self.migrations_mut().insert(migration);
// Only add parents and replaces if migrations was added first time. This can
// increase performance of recursive addition by ignoring parent and replace
// migration recursive addition
// Only add parents and replaces migrations if current migration was added first
// time. This can increase performance of recursive addition by ignoring
// parent and replace migration recursive addition
if is_new_value {
for parent in migration_parents {
self.add_migration(parent);
Expand Down

0 comments on commit 666c7ac

Please sign in to comment.