fix(config): Move file-based config into a table

This commit is contained in:
Ed Page 2019-08-07 11:05:19 -05:00
parent f9a1600513
commit a923f93ec5
2 changed files with 103 additions and 58 deletions

View file

@ -1,6 +1,10 @@
use std::io::Read; use std::io::Read;
pub trait ConfigSource { pub trait ConfigSource {
fn walk(&self) -> Option<&dyn WalkSource>;
}
pub trait WalkSource {
/// Skip hidden files and directories. /// Skip hidden files and directories.
fn ignore_hidden(&self) -> Option<bool> { fn ignore_hidden(&self) -> Option<bool> {
None None
@ -36,12 +40,7 @@ pub trait ConfigSource {
#[serde(deny_unknown_fields, default)] #[serde(deny_unknown_fields, default)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub struct Config { pub struct Config {
pub ignore_hidden: Option<bool>, pub files: Walk,
pub ignore_files: Option<bool>,
pub ignore_dot: Option<bool>,
pub ignore_vcs: Option<bool>,
pub ignore_global: Option<bool>,
pub ignore_parent: Option<bool>,
} }
impl Config { impl Config {
@ -66,6 +65,32 @@ impl Config {
} }
pub fn update(&mut self, source: &dyn ConfigSource) { pub fn update(&mut self, source: &dyn ConfigSource) {
if let Some(walk) = source.walk() {
self.files.update(walk);
}
}
}
impl ConfigSource for Config {
fn walk(&self) -> Option<&dyn WalkSource> {
Some(&self.files)
}
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
#[serde(deny_unknown_fields, default)]
#[serde(rename_all = "kebab-case")]
pub struct Walk {
pub ignore_hidden: Option<bool>,
pub ignore_files: Option<bool>,
pub ignore_dot: Option<bool>,
pub ignore_vcs: Option<bool>,
pub ignore_global: Option<bool>,
pub ignore_parent: Option<bool>,
}
impl Walk {
pub fn update(&mut self, source: &dyn WalkSource) {
if let Some(source) = source.ignore_hidden() { if let Some(source) = source.ignore_hidden() {
self.ignore_hidden = Some(source); self.ignore_hidden = Some(source);
} }
@ -121,7 +146,7 @@ impl Config {
} }
} }
impl ConfigSource for Config { impl WalkSource for Walk {
fn ignore_hidden(&self) -> Option<bool> { fn ignore_hidden(&self) -> Option<bool> {
self.ignore_hidden self.ignore_hidden
} }

View file

@ -89,49 +89,8 @@ struct Options {
#[structopt(long, raw(overrides_with = r#""binary""#), raw(hidden = "true"))] #[structopt(long, raw(overrides_with = r#""binary""#), raw(hidden = "true"))]
no_binary: bool, no_binary: bool,
#[structopt(long, raw(overrides_with = r#""no-hidden""#))] #[structopt(flatten)]
/// Search hidden files and directories. config: ConfigArgs,
hidden: bool,
#[structopt(long, raw(overrides_with = r#""hidden""#), raw(hidden = "true"))]
no_hidden: bool,
#[structopt(long, raw(overrides_with = r#""ignore""#))]
/// Don't respect ignore files.
no_ignore: bool,
#[structopt(long, raw(overrides_with = r#""no-ignore""#), raw(hidden = "true"))]
ignore: bool,
#[structopt(long, raw(overrides_with = r#""ignore-dot""#))]
/// Don't respect .ignore files.
no_ignore_dot: bool,
#[structopt(long, raw(overrides_with = r#""no-ignore-dot""#), raw(hidden = "true"))]
ignore_dot: bool,
#[structopt(long, raw(overrides_with = r#""ignore-global""#))]
/// Don't respect global ignore files.
no_ignore_global: bool,
#[structopt(
long,
raw(overrides_with = r#""no-ignore-global""#),
raw(hidden = "true")
)]
ignore_global: bool,
#[structopt(long, raw(overrides_with = r#""ignore-parent""#))]
/// Don't respect ignore files in parent directories.
no_ignore_parent: bool,
#[structopt(
long,
raw(overrides_with = r#""no-ignore-parent""#),
raw(hidden = "true")
)]
ignore_parent: bool,
#[structopt(long, raw(overrides_with = r#""ignore-vcs""#))]
/// Don't respect ignore files in vcs directories.
no_ignore_vcs: bool,
#[structopt(long, raw(overrides_with = r#""no-ignore-vcs""#), raw(hidden = "true"))]
ignore_vcs: bool,
#[structopt(flatten)] #[structopt(flatten)]
verbose: clap_verbosity_flag::Verbosity, verbose: clap_verbosity_flag::Verbosity,
@ -179,7 +138,68 @@ impl Options {
} }
} }
impl config::ConfigSource for Options { #[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
struct ConfigArgs {
#[structopt(flatten)]
walk: WalkArgs,
}
impl config::ConfigSource for ConfigArgs {
fn walk(&self) -> Option<&dyn config::WalkSource> {
Some(&self.walk)
}
}
#[derive(Debug, StructOpt)]
#[structopt(rename_all = "kebab-case")]
struct WalkArgs {
#[structopt(long, raw(overrides_with = r#""no-hidden""#))]
/// Search hidden files and directories.
hidden: bool,
#[structopt(long, raw(overrides_with = r#""hidden""#), raw(hidden = "true"))]
no_hidden: bool,
#[structopt(long, raw(overrides_with = r#""ignore""#))]
/// Don't respect ignore files.
no_ignore: bool,
#[structopt(long, raw(overrides_with = r#""no-ignore""#), raw(hidden = "true"))]
ignore: bool,
#[structopt(long, raw(overrides_with = r#""ignore-dot""#))]
/// Don't respect .ignore files.
no_ignore_dot: bool,
#[structopt(long, raw(overrides_with = r#""no-ignore-dot""#), raw(hidden = "true"))]
ignore_dot: bool,
#[structopt(long, raw(overrides_with = r#""ignore-global""#))]
/// Don't respect global ignore files.
no_ignore_global: bool,
#[structopt(
long,
raw(overrides_with = r#""no-ignore-global""#),
raw(hidden = "true")
)]
ignore_global: bool,
#[structopt(long, raw(overrides_with = r#""ignore-parent""#))]
/// Don't respect ignore files in parent directories.
no_ignore_parent: bool,
#[structopt(
long,
raw(overrides_with = r#""no-ignore-parent""#),
raw(hidden = "true")
)]
ignore_parent: bool,
#[structopt(long, raw(overrides_with = r#""ignore-vcs""#))]
/// Don't respect ignore files in vcs directories.
no_ignore_vcs: bool,
#[structopt(long, raw(overrides_with = r#""no-ignore-vcs""#), raw(hidden = "true"))]
ignore_vcs: bool,
}
impl config::WalkSource for WalkArgs {
fn ignore_hidden(&self) -> Option<bool> { fn ignore_hidden(&self) -> Option<bool> {
match (self.hidden, self.no_hidden) { match (self.hidden, self.no_hidden) {
(true, false) => Some(false), (true, false) => Some(false),
@ -295,16 +315,16 @@ fn run() -> Result<i32, failure::Error> {
let derived = config::Config::derive(cwd)?; let derived = config::Config::derive(cwd)?;
config.update(&derived); config.update(&derived);
} }
config.update(&options); config.update(&options.config);
let config = config; let config = config;
let mut walk = ignore::WalkBuilder::new(path); let mut walk = ignore::WalkBuilder::new(path);
walk.hidden(config.ignore_hidden()) walk.hidden(config.files.ignore_hidden())
.ignore(config.ignore_dot()) .ignore(config.files.ignore_dot())
.git_global(config.ignore_global()) .git_global(config.files.ignore_global())
.git_ignore(config.ignore_vcs()) .git_ignore(config.files.ignore_vcs())
.git_exclude(config.ignore_vcs()) .git_exclude(config.files.ignore_vcs())
.parents(config.ignore_parent()); .parents(config.files.ignore_parent());
for entry in walk.build() { for entry in walk.build() {
let entry = entry?; let entry = entry?;
if entry.file_type().map(|t| t.is_file()).unwrap_or(true) { if entry.file_type().map(|t| t.is_file()).unwrap_or(true) {