diff --git a/migra-cli/src/config.rs b/migra-cli/src/config.rs index a5d5c3f..76d419f 100644 --- a/migra-cli/src/config.rs +++ b/migra-cli/src/config.rs @@ -31,31 +31,47 @@ impl Default for Config { } } -impl Config { - pub fn read() -> io::Result { - let current_dir = std::env::current_dir()?; +fn recursive_find_config_file() -> io::Result { + let current_dir = std::env::current_dir()?; - let mut read_dir = Some(current_dir.as_path()); + 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)); + 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; } + + return Ok(migra_file_path); + } else { + return Err(io::Error::from(io::ErrorKind::NotFound)); } } +} + +impl Config { + pub fn read(config_path: Option) -> io::Result { + let config_path = match config_path { + Some(mut config_path) if config_path.is_dir() => { + config_path.push(MIGRA_TOML_FILENAME); + config_path + }, + Some(config_path) => config_path, + None => recursive_find_config_file()?, + }; + + let content = fs::read_to_string(&config_path)?; + + let mut config: Config = toml::from_str(&content).expect("Cannot parse Migra.toml"); + config.root = config_path + .parent() + .unwrap_or_else(|| Path::new("")) + .to_path_buf(); + + Ok(config) + } pub fn initialize() -> Result<(), Box> { if Path::new(MIGRA_TOML_FILENAME).exists() { diff --git a/migra-cli/src/main.rs b/migra-cli/src/main.rs index d07e4a1..6619206 100644 --- a/migra-cli/src/main.rs +++ b/migra-cli/src/main.rs @@ -4,18 +4,18 @@ mod config; mod opts; use config::Config; -use opts::{AppOpt, ApplyOpt, StructOpt}; +use opts::{AppOpt, ApplyCommandOpt, Command, StructOpt}; use std::fs; fn main() -> Result<(), Box> { let opt = AppOpt::from_args(); - match opt { - AppOpt::Init => { + match opt.command { + Command::Init => { Config::initialize()?; } - AppOpt::Apply(ApplyOpt { file_name }) => { - let config = Config::read()?; + Command::Apply(ApplyCommandOpt { file_name }) => { + let config = Config::read(opt.config)?; let mut client = migra_core::database::connect(&config.database.connection)?; @@ -36,6 +36,9 @@ fn main() -> Result<(), Box> { } } } + Command::List => { + unimplemented!(); + } } Ok(()) diff --git a/migra-cli/src/opts.rs b/migra-cli/src/opts.rs index 8730175..de4a90f 100644 --- a/migra-cli/src/opts.rs +++ b/migra-cli/src/opts.rs @@ -1,13 +1,28 @@ +use std::path::PathBuf; pub use structopt::StructOpt; #[derive(Debug, StructOpt)] -pub(crate) enum AppOpt { - Init, - Apply(ApplyOpt), +#[structopt(bin_name = "migra", name = "Migra")] +pub(crate) struct AppOpt { + #[structopt(short, long)] + pub config: Option, + + #[structopt(subcommand)] + pub command: Command, } #[derive(Debug, StructOpt)] -pub(crate) struct ApplyOpt { +pub(crate) enum Command { + Init, + + Apply(ApplyCommandOpt), + + #[structopt(name = "list", visible_alias = "ls")] + List, +} + +#[derive(Debug, StructOpt)] +pub(crate) struct ApplyCommandOpt { #[structopt(parse(from_str))] pub file_name: String, }