
https://github.com/zed-industries/zed/issues/30972 brought up another case where our context is not enough to track the actual source of the issue: we get a general top-level error without inner error. The reason for this was `.ok_or_else(|| anyhow!("failed to read HEAD SHA"))?; ` on the top level. The PR finally reworks the way we use anyhow to reduce such issues (or at least make it simpler to bubble them up later in a fix). On top of that, uses a few more anyhow methods for better readability. * `.ok_or_else(|| anyhow!("..."))`, `map_err` and other similar error conversion/option reporting cases are replaced with `context` and `with_context` calls * in addition to that, various `anyhow!("failed to do ...")` are stripped with `.context("Doing ...")` messages instead to remove the parasitic `failed to` text * `anyhow::ensure!` is used instead of `if ... { return Err(...); }` calls * `anyhow::bail!` is used instead of `return Err(anyhow!(...));` Release Notes: - N/A
47 lines
1.5 KiB
Rust
47 lines
1.5 KiB
Rust
use std::path::Path;
|
|
use std::time::Duration;
|
|
|
|
use anyhow::{Result, anyhow};
|
|
use collections::HashMap;
|
|
use sea_orm::ConnectOptions;
|
|
use sqlx::Connection;
|
|
use sqlx::migrate::{Migrate, Migration, MigrationSource};
|
|
|
|
/// Runs the database migrations for the specified database.
|
|
pub async fn run_database_migrations(
|
|
database_options: &ConnectOptions,
|
|
migrations_path: impl AsRef<Path>,
|
|
) -> Result<Vec<(Migration, Duration)>> {
|
|
let migrations = MigrationSource::resolve(migrations_path.as_ref())
|
|
.await
|
|
.map_err(|err| anyhow!("failed to load migrations: {err:?}"))?;
|
|
|
|
let mut connection = sqlx::AnyConnection::connect(database_options.get_url()).await?;
|
|
|
|
connection.ensure_migrations_table().await?;
|
|
let applied_migrations: HashMap<_, _> = connection
|
|
.list_applied_migrations()
|
|
.await?
|
|
.into_iter()
|
|
.map(|migration| (migration.version, migration))
|
|
.collect();
|
|
|
|
let mut new_migrations = Vec::new();
|
|
for migration in migrations {
|
|
match applied_migrations.get(&migration.version) {
|
|
Some(applied_migration) => {
|
|
anyhow::ensure!(
|
|
migration.checksum == applied_migration.checksum,
|
|
"checksum mismatch for applied migration {}",
|
|
migration.description
|
|
);
|
|
}
|
|
None => {
|
|
let elapsed = connection.apply(&migration).await?;
|
|
new_migrations.push((migration, elapsed));
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(new_migrations)
|
|
}
|