feat(cli): add recursive migra config search
... in parent directories
This commit is contained in:
parent
cc6899d416
commit
942edd0f8b
3 changed files with 39 additions and 17 deletions
|
@ -1,38 +1,60 @@
|
||||||
|
use migra_core::path::PathBuilder;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::io;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
const MIGRA_TOML_FILENAME: &str = "Migra.toml";
|
const MIGRA_TOML_FILENAME: &str = "Migra.toml";
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub(crate) struct Config {
|
pub(crate) struct Config {
|
||||||
pub directory: String,
|
#[serde(skip)]
|
||||||
|
pub root: PathBuf,
|
||||||
|
pub directory: PathBuf,
|
||||||
pub database: DatabaseConfig,
|
pub database: DatabaseConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub(crate) struct DatabaseConfig {
|
pub(crate) struct DatabaseConfig {
|
||||||
pub connection: String
|
pub connection: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Config {
|
fn default() -> Config {
|
||||||
Config {
|
Config {
|
||||||
directory: String::from("database"),
|
root: PathBuf::new(),
|
||||||
|
directory: PathBuf::from("database"),
|
||||||
database: DatabaseConfig {
|
database: DatabaseConfig {
|
||||||
connection: String::new(),
|
connection: String::new(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn read() -> Config {
|
pub fn read() -> io::Result<Config> {
|
||||||
fs::read_to_string(MIGRA_TOML_FILENAME)
|
let current_dir = std::env::current_dir()?;
|
||||||
.ok()
|
|
||||||
.and_then(|content| toml::from_str(&content).ok())
|
let mut read_dir = Some(current_dir.as_path());
|
||||||
.unwrap_or_default()
|
|
||||||
|
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<dyn std::error::Error>> {
|
pub fn initialize() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod config;
|
||||||
mod opts;
|
mod opts;
|
||||||
|
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use opts::{StructOpt, AppOpt, ApplyOpt};
|
use opts::{AppOpt, ApplyOpt, StructOpt};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
@ -13,13 +13,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
match opt {
|
match opt {
|
||||||
AppOpt::Init => {
|
AppOpt::Init => {
|
||||||
Config::initialize()?;
|
Config::initialize()?;
|
||||||
},
|
}
|
||||||
AppOpt::Apply(ApplyOpt { file_name }) => {
|
AppOpt::Apply(ApplyOpt { file_name }) => {
|
||||||
let config = Config::read();
|
let config = Config::read()?;
|
||||||
|
|
||||||
let mut client = migra_core::database::connect(&config.database.connection)?;
|
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)
|
.append(file_name)
|
||||||
.default_extension("sql")
|
.default_extension("sql")
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -6,9 +6,8 @@ pub(crate) enum AppOpt {
|
||||||
Apply(ApplyOpt),
|
Apply(ApplyOpt),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, StructOpt)]
|
||||||
pub(crate) struct ApplyOpt {
|
pub(crate) struct ApplyOpt {
|
||||||
#[structopt(parse(from_str))]
|
#[structopt(parse(from_str))]
|
||||||
pub file_name: String
|
pub file_name: String,
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue