feat: add migrations config to manifest
- added migrations directory path - added migrations table name
This commit is contained in:
parent
83a4155d76
commit
11874bd8a4
7 changed files with 142 additions and 44 deletions
|
@ -10,7 +10,7 @@ pub(crate) fn apply_sql(app: &App, cmd_opts: ApplyCommandOpt) -> StdResult<()> {
|
|||
let mut connection_manager = DatabaseConnectionManager::connect(&config.database)?;
|
||||
let conn = connection_manager.connection();
|
||||
|
||||
let migration_manager = MigrationManager::new();
|
||||
let migration_manager = MigrationManager::from(&config);
|
||||
|
||||
let file_contents = cmd_opts
|
||||
.file_paths
|
||||
|
|
|
@ -10,7 +10,7 @@ pub(crate) fn rollback_applied_migrations(app: &App, opts: DowngradeCommandOpt)
|
|||
let config = app.config()?;
|
||||
let mut connection_manager = DatabaseConnectionManager::connect(&config.database)?;
|
||||
let conn = connection_manager.connection();
|
||||
let migration_manager = MigrationManager::new();
|
||||
let migration_manager = MigrationManager::from(&config);
|
||||
|
||||
let applied_migrations = migration_manager.applied_migration_names(conn)?;
|
||||
let migrations = config.migrations()?;
|
||||
|
|
|
@ -16,7 +16,7 @@ pub(crate) fn print_migration_lists(app: &App) -> StdResult<()> {
|
|||
)?;
|
||||
let conn = connection_manager.connection();
|
||||
|
||||
let migration_manager = MigrationManager::new();
|
||||
let migration_manager = MigrationManager::from(&config);
|
||||
let applied_migration_names = migration_manager.applied_migration_names(conn)?;
|
||||
|
||||
show_applied_migrations(&applied_migration_names);
|
||||
|
|
|
@ -10,7 +10,7 @@ pub(crate) fn upgrade_pending_migrations(app: &App, opts: UpgradeCommandOpt) ->
|
|||
let mut connection_manager = DatabaseConnectionManager::connect(&config.database)?;
|
||||
let conn = connection_manager.connection();
|
||||
|
||||
let migration_manager = MigrationManager::new();
|
||||
let migration_manager = MigrationManager::from(&config);
|
||||
|
||||
let applied_migration_names = migration_manager.applied_migration_names(conn)?;
|
||||
let migrations = config.migrations()?;
|
||||
|
|
|
@ -4,11 +4,31 @@ use serde::{Deserialize, Serialize};
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::{env, fs, io};
|
||||
|
||||
pub(crate) const MIGRA_TOML_FILENAME: &str = "Migra.toml";
|
||||
pub(crate) const DEFAULT_DATABASE_CONNECTION_ENV: &str = "$DATABASE_URL";
|
||||
//===========================================================================//
|
||||
// Default values for optional manifest variables //
|
||||
//===========================================================================//
|
||||
|
||||
fn default_database_connection_env() -> String {
|
||||
DEFAULT_DATABASE_CONNECTION_ENV.to_owned()
|
||||
pub(crate) const MIGRA_TOML_FILENAME: &str = "Migra.toml";
|
||||
|
||||
//===========================================================================//
|
||||
// Internal Config Utils / Macros //
|
||||
//===========================================================================//
|
||||
|
||||
fn search_for_directory_containing_file(path: &Path, file_name: &str) -> MigraResult<PathBuf> {
|
||||
let file_path = path.join(file_name);
|
||||
if file_path.is_file() {
|
||||
Ok(path.to_owned())
|
||||
} else {
|
||||
path.parent()
|
||||
.ok_or(Error::RootNotFound)
|
||||
.and_then(|p| search_for_directory_containing_file(p, file_name))
|
||||
}
|
||||
}
|
||||
|
||||
fn recursive_find_project_root() -> MigraResult<PathBuf> {
|
||||
let current_dir = std::env::current_dir()?;
|
||||
|
||||
search_for_directory_containing_file(¤t_dir, MIGRA_TOML_FILENAME)
|
||||
}
|
||||
|
||||
#[cfg(any(not(feature = "postgres"), not(feature = "mysql")))]
|
||||
|
@ -24,15 +44,12 @@ cargo install migra-cli --features ${database_name}"#,
|
|||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub(crate) struct Config {
|
||||
#[serde(skip)]
|
||||
manifest_root: PathBuf,
|
||||
//===========================================================================//
|
||||
// Database config //
|
||||
//===========================================================================//
|
||||
|
||||
root: PathBuf,
|
||||
|
||||
#[serde(default)]
|
||||
pub database: DatabaseConfig,
|
||||
fn default_database_connection_env() -> String {
|
||||
String::from("$DATABASE_URL")
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
@ -56,7 +73,7 @@ impl Default for SupportedDatabaseClient {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct DatabaseConfig {
|
||||
pub client: Option<SupportedDatabaseClient>,
|
||||
|
||||
|
@ -64,6 +81,15 @@ pub(crate) struct DatabaseConfig {
|
|||
pub connection: String,
|
||||
}
|
||||
|
||||
impl Default for DatabaseConfig {
|
||||
fn default() -> Self {
|
||||
DatabaseConfig {
|
||||
connection: default_database_connection_env(),
|
||||
client: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DatabaseConfig {
|
||||
pub fn client(&self) -> SupportedDatabaseClient {
|
||||
self.client.clone().unwrap_or_else(|| {
|
||||
|
@ -103,36 +129,97 @@ impl DatabaseConfig {
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
// Migrations config //
|
||||
//===========================================================================//
|
||||
|
||||
fn default_migrations_directory() -> String {
|
||||
String::from("migrations")
|
||||
}
|
||||
|
||||
fn default_migrations_table_name() -> String {
|
||||
String::from("migrations")
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct MigrationsConfig {
|
||||
#[serde(rename = "directory", default = "default_migrations_directory")]
|
||||
directory: String,
|
||||
|
||||
#[serde(default = "default_migrations_table_name")]
|
||||
table_name: String,
|
||||
}
|
||||
|
||||
impl Default for MigrationsConfig {
|
||||
fn default() -> Self {
|
||||
MigrationsConfig {
|
||||
directory: default_migrations_directory(),
|
||||
table_name: default_migrations_table_name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MigrationsConfig {
|
||||
pub fn directory(&self) -> String {
|
||||
if let Some(directory_env) = self.directory.strip_prefix("$") {
|
||||
env::var(directory_env).unwrap_or_else(|_| {
|
||||
println!(
|
||||
"WARN: Cannot read {} variable and use {} directory by default",
|
||||
directory_env,
|
||||
default_migrations_directory()
|
||||
);
|
||||
default_migrations_directory()
|
||||
})
|
||||
} else {
|
||||
self.directory.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn table_name(&self) -> String {
|
||||
if let Some(table_name_env) = self.table_name.strip_prefix("$") {
|
||||
env::var(table_name_env).unwrap_or_else(|_| {
|
||||
println!(
|
||||
"WARN: Cannot read {} variable and use {} table_name by default",
|
||||
table_name_env,
|
||||
default_migrations_table_name()
|
||||
);
|
||||
default_migrations_table_name()
|
||||
})
|
||||
} else {
|
||||
self.table_name.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================//
|
||||
// Main config //
|
||||
//===========================================================================//
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub(crate) struct Config {
|
||||
#[serde(skip)]
|
||||
manifest_root: PathBuf,
|
||||
|
||||
root: PathBuf,
|
||||
|
||||
#[serde(default)]
|
||||
pub(crate) database: DatabaseConfig,
|
||||
|
||||
#[serde(default)]
|
||||
pub(crate) migrations: MigrationsConfig,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Config {
|
||||
Config {
|
||||
manifest_root: PathBuf::default(),
|
||||
root: PathBuf::from("database"),
|
||||
database: DatabaseConfig {
|
||||
connection: default_database_connection_env(),
|
||||
..Default::default()
|
||||
},
|
||||
database: DatabaseConfig::default(),
|
||||
migrations: MigrationsConfig::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn search_for_directory_containing_file(path: &Path, file_name: &str) -> MigraResult<PathBuf> {
|
||||
let file_path = path.join(file_name);
|
||||
if file_path.is_file() {
|
||||
Ok(path.to_owned())
|
||||
} else {
|
||||
path.parent()
|
||||
.ok_or(Error::RootNotFound)
|
||||
.and_then(|p| search_for_directory_containing_file(p, file_name))
|
||||
}
|
||||
}
|
||||
|
||||
fn recursive_find_project_root() -> MigraResult<PathBuf> {
|
||||
let current_dir = std::env::current_dir()?;
|
||||
|
||||
search_for_directory_containing_file(¤t_dir, MIGRA_TOML_FILENAME)
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn read(config_path: Option<&PathBuf>) -> MigraResult<Config> {
|
||||
let config_path = match config_path {
|
||||
|
@ -160,15 +247,13 @@ impl Config {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn directory_path(&self) -> PathBuf {
|
||||
self.manifest_root.join(&self.root)
|
||||
}
|
||||
|
||||
pub fn migration_dir_path(&self) -> PathBuf {
|
||||
self.directory_path().join("migrations")
|
||||
self.directory_path().join(self.migrations.directory())
|
||||
}
|
||||
|
||||
pub fn migrations(&self) -> MigraResult<Vec<Migration>> {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::connection::AnyConnection;
|
||||
use crate::Config;
|
||||
use crate::StdResult;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -54,10 +55,10 @@ pub struct MigrationManager {
|
|||
migrations_table_name: String,
|
||||
}
|
||||
|
||||
impl MigrationManager {
|
||||
pub fn new() -> Self {
|
||||
impl From<&Config> for MigrationManager {
|
||||
fn from(config: &Config) -> Self {
|
||||
MigrationManager {
|
||||
migrations_table_name: String::from("migrations"),
|
||||
migrations_table_name: config.migrations.table_name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ mod init {
|
|||
fn init_manifest_with_default_config() -> TestResult {
|
||||
let manifest_path = "Migra.toml";
|
||||
|
||||
fs::remove_file(&manifest_path).ok();
|
||||
|
||||
Command::cargo_bin("migra")?
|
||||
.arg("init")
|
||||
.assert()
|
||||
|
@ -58,6 +60,10 @@ mod init {
|
|||
|
||||
[database]
|
||||
connection = "$DATABASE_URL"
|
||||
|
||||
[migrations]
|
||||
directory = "migrations"
|
||||
table_name = "migrations"
|
||||
"#
|
||||
);
|
||||
|
||||
|
@ -70,6 +76,8 @@ connection = "$DATABASE_URL"
|
|||
fn init_manifest_in_custom_path() -> TestResult {
|
||||
let manifest_path = path_to_file("Migra.toml");
|
||||
|
||||
fs::remove_file(&manifest_path).ok();
|
||||
|
||||
Command::cargo_bin("migra")?
|
||||
.arg("-c")
|
||||
.arg(&manifest_path)
|
||||
|
@ -86,6 +94,10 @@ connection = "$DATABASE_URL"
|
|||
|
||||
[database]
|
||||
connection = "$DATABASE_URL"
|
||||
|
||||
[migrations]
|
||||
directory = "migrations"
|
||||
table_name = "migrations"
|
||||
"#
|
||||
);
|
||||
|
||||
|
|
Reference in a new issue