Enable migration generation in modules (#933)
* Enable migration generation in modules Previously, migration generation expected migrations to be at the crate root. * Fix migration backup file extension * Document behavior of migration_dir
This commit is contained in:
parent
4e51b8837a
commit
be0d846d8f
@ -25,7 +25,11 @@ pub enum Commands {
|
|||||||
global = true,
|
global = true,
|
||||||
short = 'd',
|
short = 'd',
|
||||||
long,
|
long,
|
||||||
help = "Migration script directory",
|
help = "Migration script directory.
|
||||||
|
If your migrations are in their own crate,
|
||||||
|
you can provide the root of that crate.
|
||||||
|
If your migrations are in a submodule of your app,
|
||||||
|
you should provide the directory of that submodule.",
|
||||||
default_value = "./migration"
|
default_value = "./migration"
|
||||||
)]
|
)]
|
||||||
migration_dir: String,
|
migration_dir: String,
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::{error::Error, fs, io::Write, path::Path, process::Command};
|
use std::{
|
||||||
|
error::Error,
|
||||||
|
fs,
|
||||||
|
io::Write,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
process::Command,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::MigrateSubcommands;
|
use crate::MigrateSubcommands;
|
||||||
|
|
||||||
@ -117,10 +123,27 @@ pub fn run_migrate_generate(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `get_full_migration_dir` looks for a `src` directory
|
||||||
|
/// inside of `migration_dir` and appends that to the returned path if found.
|
||||||
|
///
|
||||||
|
/// Otherwise, `migration_dir` can point directly to a directory containing the
|
||||||
|
/// migrations. In that case, nothing is appended.
|
||||||
|
///
|
||||||
|
/// This way, `src` doesn't need to be appended in the standard case where
|
||||||
|
/// migrations are in their own crate. If the migrations are in a submodule
|
||||||
|
/// of another crate, `migration_dir` can point directly to that module.
|
||||||
|
fn get_full_migration_dir(migration_dir: &str) -> PathBuf {
|
||||||
|
let without_src = Path::new(migration_dir).to_owned();
|
||||||
|
let with_src = without_src.join("src");
|
||||||
|
match () {
|
||||||
|
_ if with_src.is_dir() => with_src,
|
||||||
|
_ => without_src,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn create_new_migration(migration_name: &str, migration_dir: &str) -> Result<(), Box<dyn Error>> {
|
fn create_new_migration(migration_name: &str, migration_dir: &str) -> Result<(), Box<dyn Error>> {
|
||||||
let migration_filepath = Path::new(migration_dir)
|
let migration_filepath =
|
||||||
.join("src")
|
get_full_migration_dir(migration_dir).join(format!("{}.rs", &migration_name));
|
||||||
.join(format!("{}.rs", &migration_name));
|
|
||||||
println!("Creating migration file `{}`", migration_filepath.display());
|
println!("Creating migration file `{}`", migration_filepath.display());
|
||||||
// TODO: make OS agnostic
|
// TODO: make OS agnostic
|
||||||
let migration_template =
|
let migration_template =
|
||||||
@ -130,8 +153,29 @@ fn create_new_migration(migration_name: &str, migration_dir: &str) -> Result<(),
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `get_migrator_filepath` looks for a file `migration_dir/src/lib.rs`
|
||||||
|
/// and returns that path if found.
|
||||||
|
///
|
||||||
|
/// If `src` is not found, it will look directly in `migration_dir` for `lib.rs`.
|
||||||
|
///
|
||||||
|
/// If `lib.rs` is not found, it will look for `mod.rs` instead,
|
||||||
|
/// e.g. `migration_dir/mod.rs`.
|
||||||
|
///
|
||||||
|
/// This way, `src` doesn't need to be appended in the standard case where
|
||||||
|
/// migrations are in their own crate (with a file `lib.rs`). If the
|
||||||
|
/// migrations are in a submodule of another crate (with a file `mod.rs`),
|
||||||
|
/// `migration_dir` can point directly to that module.
|
||||||
|
fn get_migrator_filepath(migration_dir: &str) -> PathBuf {
|
||||||
|
let full_migration_dir = get_full_migration_dir(migration_dir);
|
||||||
|
let with_lib = full_migration_dir.join("lib.rs");
|
||||||
|
match () {
|
||||||
|
_ if with_lib.is_file() => with_lib,
|
||||||
|
_ => full_migration_dir.join("mod.rs"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn update_migrator(migration_name: &str, migration_dir: &str) -> Result<(), Box<dyn Error>> {
|
fn update_migrator(migration_name: &str, migration_dir: &str) -> Result<(), Box<dyn Error>> {
|
||||||
let migrator_filepath = Path::new(migration_dir).join("src").join("lib.rs");
|
let migrator_filepath = get_migrator_filepath(migration_dir);
|
||||||
println!(
|
println!(
|
||||||
"Adding migration `{}` to `{}`",
|
"Adding migration `{}` to `{}`",
|
||||||
migration_name,
|
migration_name,
|
||||||
@ -141,7 +185,7 @@ fn update_migrator(migration_name: &str, migration_dir: &str) -> Result<(), Box<
|
|||||||
let mut updated_migrator_content = migrator_content.clone();
|
let mut updated_migrator_content = migrator_content.clone();
|
||||||
|
|
||||||
// create a backup of the migrator file in case something goes wrong
|
// create a backup of the migrator file in case something goes wrong
|
||||||
let migrator_backup_filepath = migrator_filepath.with_file_name("lib.rs.bak");
|
let migrator_backup_filepath = migrator_filepath.with_extension("rs.bak");
|
||||||
fs::copy(&migrator_filepath, &migrator_backup_filepath)?;
|
fs::copy(&migrator_filepath, &migrator_backup_filepath)?;
|
||||||
let mut migrator_file = fs::File::create(&migrator_filepath)?;
|
let mut migrator_file = fs::File::create(&migrator_filepath)?;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user