diff --git a/migra-cli/src/config.rs b/migra-cli/src/config.rs index ab71ac9..a5d5c3f 100644 --- a/migra-cli/src/config.rs +++ b/migra-cli/src/config.rs @@ -1,38 +1,60 @@ +use migra_core::path::PathBuilder; use serde::{Deserialize, Serialize}; use std::fs; -use std::path::Path; +use std::io; +use std::path::{Path, PathBuf}; const MIGRA_TOML_FILENAME: &str = "Migra.toml"; #[derive(Debug, Serialize, Deserialize)] pub(crate) struct Config { - pub directory: String, + #[serde(skip)] + pub root: PathBuf, + pub directory: PathBuf, pub database: DatabaseConfig, } #[derive(Debug, Serialize, Deserialize)] pub(crate) struct DatabaseConfig { - pub connection: String + pub connection: String, } impl Default for Config { fn default() -> Config { Config { - directory: String::from("database"), + root: PathBuf::new(), + directory: PathBuf::from("database"), database: DatabaseConfig { connection: String::new(), - } + }, } } } - impl Config { - pub fn read() -> Config { - fs::read_to_string(MIGRA_TOML_FILENAME) - .ok() - .and_then(|content| toml::from_str(&content).ok()) - .unwrap_or_default() + pub fn read() -> io::Result { + let current_dir = std::env::current_dir()?; + + let mut read_dir = Some(current_dir.as_path()); + + loop { + if let Some(dir) = read_dir { + let migra_file_path = PathBuilder::from(dir).append(MIGRA_TOML_FILENAME).build(); + if !migra_file_path.exists() { + read_dir = dir.parent(); + continue; + } + + let content = fs::read_to_string(migra_file_path)?; + let mut config: Config = toml::from_str(&content).expect("Cannot parse Migra.toml"); + + config.root = PathBuf::from(dir); + + return Ok(config); + } else { + return Err(io::Error::from(io::ErrorKind::NotFound)); + } + } } pub fn initialize() -> Result<(), Box> { diff --git a/migra-cli/src/main.rs b/migra-cli/src/main.rs index 25a7c8e..d07e4a1 100644 --- a/migra-cli/src/main.rs +++ b/migra-cli/src/main.rs @@ -4,7 +4,7 @@ mod config; mod opts; use config::Config; -use opts::{StructOpt, AppOpt, ApplyOpt}; +use opts::{AppOpt, ApplyOpt, StructOpt}; use std::fs; fn main() -> Result<(), Box> { @@ -13,13 +13,14 @@ fn main() -> Result<(), Box> { match opt { AppOpt::Init => { Config::initialize()?; - }, + } AppOpt::Apply(ApplyOpt { file_name }) => { - let config = Config::read(); + let config = Config::read()?; let mut client = migra_core::database::connect(&config.database.connection)?; - let file_path = migra_core::path::PathBuilder::new(config.directory) + let file_path = migra_core::path::PathBuilder::from(config.root) + .append(config.directory) .append(file_name) .default_extension("sql") .build(); diff --git a/migra-cli/src/opts.rs b/migra-cli/src/opts.rs index fb419ad..8730175 100644 --- a/migra-cli/src/opts.rs +++ b/migra-cli/src/opts.rs @@ -6,9 +6,8 @@ pub(crate) enum AppOpt { Apply(ApplyOpt), } - #[derive(Debug, StructOpt)] pub(crate) struct ApplyOpt { #[structopt(parse(from_str))] - pub file_name: String + pub file_name: String, }