Skip to content

Commit

Permalink
feat(cli): add migrate subcommand for generating a build script
Browse files Browse the repository at this point in the history
suggest embedding migrations on `sqlx migrate add` in a new project
  • Loading branch information
abonander committed Jul 20, 2021
1 parent edb6b5f commit 22ef174
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions sqlx-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub async fn run(opt: Opt) -> anyhow::Result<()> {
ignore_missing,
} => migrate::revert(&migrate.source, &database_url, dry_run, ignore_missing).await?,
MigrateCommand::Info => migrate::info(&migrate.source, &database_url).await?,
MigrateCommand::BuildScript { force } => migrate::build_script(&migrate.source, force)?,
},

Command::Database(database) => match database.command {
Expand Down
57 changes: 57 additions & 0 deletions sqlx-cli/src/migrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ pub async fn add(
) -> anyhow::Result<()> {
fs::create_dir_all(migration_source).context("Unable to create migrations directory")?;

// if the migrations directory is empty
let has_existing_migrations = fs::read_dir(migration_source)
.map(|mut dir| dir.next().is_some())
.unwrap_or(false);

let migrator = Migrator::new(Path::new(migration_source)).await?;
// This checks if all existing migrations are of the same type as the reverisble flag passed
for migration in migrator.iter() {
Expand Down Expand Up @@ -74,6 +79,31 @@ pub async fn add(
)?;
}

if !has_existing_migrations {
let quoted_source = if migration_source != "migrations" {
format!("{:?}", migration_source)
} else {
"".to_string()
};

print!(
r#"
Congratulations on creating your first migration!
Did you know you can embed your migrations in your application binary?
On startup, after creating your database connection or pool, add:
sqlx::migrate!({}).run(<&your_pool OR &mut your_connection>).await?;
Note that the compiler won't pick up new migrations if no Rust source files have changed.
You can create a Cargo build script to work around this with `sqlx migrate build-script`.
See: https://docs.rs/sqlx/0.5/sqlx/macro.migrate.html
"#,
quoted_source
);
}

Ok(())
}

Expand Down Expand Up @@ -245,3 +275,30 @@ pub async fn revert(

Ok(())
}

pub fn build_script(migration_source: &str, force: bool) -> anyhow::Result<()> {
anyhow::ensure!(
Path::new("Cargo.toml").exists(),
"must be run in a Cargo project root"
);

anyhow::ensure!(
(force || !Path::new("build.rs").exists()),
"build.rs already exists; use --force to overwrite"
);

let contents = format!(
r#"// generated by `sqlx migrate build-script`
fn main() {{
// trigger recompilation when a new migration is added
println!("cargo:rerun-if-changed={}");
}}"#,
migration_source
);

fs::write("build.rs", contents)?;

println!("Created `build.rs`; be sure to check it into version control!");

Ok(())
}
9 changes: 9 additions & 0 deletions sqlx-cli/src/opt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,13 @@ pub enum MigrateCommand {

/// List all available migrations.
Info,

/// Generate a `build.rs` to trigger recompilation when a new migration is added.
///
/// Must be run in a Cargo project root.
BuildScript {
/// Overwrite the build script if it already exists.
#[clap(long)]
force: bool,
},
}
2 changes: 2 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,8 @@ macro_rules! query_file_scalar_unchecked (
/// }
/// ```
///
/// You can also do this automatically by running `sqlx migrate build-script`.
///
/// See: [The Cargo Book: 3.8 Build Scripts; Outputs of the Build Script](https://doc.rust-lang.org/stable/cargo/reference/build-scripts.html#outputs-of-the-build-script)
///
/// #### Nightly Rust: `cfg` Flag
Expand Down

0 comments on commit 22ef174

Please sign in to comment.