fix(macros): tell the compiler about external files/env vars to watch (#1332)

* fix(macros): tell the compiler about external files/env vars to watch

closes #663
closes #681

* feat(cli): add `migrate` subcommand for generating a build script

suggest embedding migrations on `sqlx migrate add` in a new project
This commit is contained in:
Austin Bonander
2021-07-21 16:36:22 -07:00
committed by GitHub
parent a8544fd503
commit e89cb0971a
12 changed files with 259 additions and 31 deletions

View File

@@ -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 {

View File

@@ -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() {
@@ -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(())
}
@@ -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(())
}

View File

@@ -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,
},
}