Repository: diesel-rs/diesel
File: diesel_cli/src/migrations/mod.rs (Rust)

Code before:
                            }
                            Err(e) => Some(Err(e)),
                        }
                    })
                    .collect::<Result<Vec<_>, _>>()?
            };

             let mut migrations = MigrationSource::<DB>::migrations(&migrations_dir)
                 .unwrap_or_else(handle_error)
                 .into_iter()
                 .map(|m| (m.name().version().as_owned(), m))
                 .collect::<HashMap<_, _>>();

            let mut migrations = reverted_versions
                .into_iter()
                .map(|v| {
                    migrations
                        .remove(&v)
                        .ok_or_else(|| MigrationError::UnknownMigrationVersion(v.as_owned()))
                })
                .collect::<Result<Vec<_>, _>>()?;
            // Sort the migrations by version to apply them in order.
            migrations.sort_by_key(|m| m.name().version().as_owned());

            harness.run_migrations(&migrations)?;

            Ok(())
        };

    if !should_use_not_use_transaction && should_redo_migration_in_transaction(conn) {
        conn.transaction(|conn| migrations_inner(&mut HarnessWithOutput::write_to_stdout(conn)))
            .unwrap_or_else(handle_error);
    } else {
        migrations_inner(&mut HarnessWithOutput::write_to_stdout(conn))
            .unwrap_or_else(handle_error);
    }
}

#[cfg(feature = "mysql")]
fn should_redo_migration_in_transaction(t: &dyn Any) -> bool {
    !matches!(
        t.downcast_ref::<InferConnection>(),
        Some(InferConnection::Mysql(_))
    )
}

#[cfg(not(feature = "mysql"))]
fn should_redo_migration_in_transaction(_t: &dyn Any) -> bool {
    true
}


Review comment (suggestion):
can we create a new function for this. something like, `remove_reverted_migrations(migrations)`

Code after:
                                    Some(MigrationError::NoMigrationRun) => None,
                                    _ => Some(Err(e)),
                                }
                            }
                            Err(e) => Some(Err(e)),
                        }
                    })
                    .collect::<Result<Vec<_>, _>>()?
            };

            // get a mapping between migrations and migration versions
             let mut migrations = MigrationSource::<DB>::migrations(&migrations_dir)
                 .unwrap_or_else(handle_error)
                 .into_iter()
                 .map(|m| (m.name().version().as_owned(), m))
                 .collect::<HashMap<_, _>>();

            // build a list of migrations that need to be applied
            let mut migrations = reverted_versions
                .into_iter()
                .map(|v| {
                    migrations
                        .remove(&v)
                        .ok_or_else(|| MigrationError::UnknownMigrationVersion(v.as_owned()))
                })
                .collect::<Result<Vec<_>, _>>()?;

            // Sort the migrations by version to apply them in order.
            migrations.sort_by_key(|m| m.name().version().as_owned());

            // apply all outstanding migrations
            harness.run_migrations(&migrations)?;

            Ok(())
        };

    if !should_use_not_use_transaction && should_redo_migration_in_transaction(conn) {
        conn.transaction(|conn| migrations_inner(&mut HarnessWithOutput::write_to_stdout(conn)))
            .unwrap_or_else(handle_error);
    } else {
        migrations_inner(&mut HarnessWithOutput::write_to_stdout(conn))
            .unwrap_or_else(handle_error);
    }
}

#[cfg(feature = "mysql")]
fn should_redo_migration_in_transaction(t: &dyn Any) -> bool {
    !matches!(
        t.downcast_ref::<InferConnection>(),
        Some(InferConnection::Mysql(_))
    )