mirror of
https://github.com/watchexec/watchexec.git
synced 2024-09-28 22:21:33 +02:00
Move Args and builder to Config, and deprecate old names
This commit is contained in:
parent
31fd818247
commit
cd3b8c6cba
98
src/cli.rs
98
src/cli.rs
@ -1,12 +1,12 @@
|
||||
//! CLI arguments and library Args struct
|
||||
//! CLI arguments and library Config struct
|
||||
//!
|
||||
//! The [`Args`] struct is not constructable, use [`ArgsBuilder`].
|
||||
//! The [`Config`] struct is not constructable, use [`ConfigBuilder`].
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```
|
||||
//! # use watchexec::cli::ArgsBuilder;
|
||||
//! ArgsBuilder::default()
|
||||
//! # use watchexec::cli::ConfigBuilder;
|
||||
//! ConfigBuilder::default()
|
||||
//! .cmd(vec!["echo hello world".into()])
|
||||
//! .paths(vec![".".into()])
|
||||
//! .build()
|
||||
@ -22,85 +22,13 @@ use std::{
|
||||
process::Command,
|
||||
};
|
||||
|
||||
/// Arguments to the watcher
|
||||
#[derive(Builder, Clone, Debug)]
|
||||
#[builder(setter(into, strip_option))]
|
||||
#[builder(build_fn(validate = "Self::validate"))]
|
||||
#[non_exhaustive]
|
||||
pub struct Args {
|
||||
/// Command to execute in popen3 format (first program, rest arguments).
|
||||
pub cmd: Vec<String>,
|
||||
/// List of paths to watch for changes.
|
||||
pub paths: Vec<PathBuf>,
|
||||
/// Positive filters (trigger only on matching changes). Glob format.
|
||||
#[builder(default)]
|
||||
pub filters: Vec<String>,
|
||||
/// Negative filters (do not trigger on matching changes). Glob format.
|
||||
#[builder(default)]
|
||||
pub ignores: Vec<String>,
|
||||
/// Clear the screen before each run.
|
||||
#[builder(default)]
|
||||
pub clear_screen: bool,
|
||||
/// If Some, send that signal (e.g. SIGHUP) to the child on change.
|
||||
#[builder(default)]
|
||||
pub signal: Option<String>,
|
||||
/// If true, kill the child if it's still running when a change comes in.
|
||||
#[builder(default)]
|
||||
pub restart: bool,
|
||||
/// Interval to debounce the changes. (milliseconds)
|
||||
#[builder(default = "500")]
|
||||
pub debounce: u64,
|
||||
/// Run the commands right after starting.
|
||||
#[builder(default = "true")]
|
||||
pub run_initially: bool,
|
||||
/// Do not wrap the commands in a shell.
|
||||
#[builder(default)]
|
||||
pub no_shell: bool,
|
||||
/// Ignore metadata changes.
|
||||
#[builder(default)]
|
||||
pub no_meta: bool,
|
||||
/// Do not set WATCHEXEC_*_PATH environment variables for child process.
|
||||
#[builder(default)]
|
||||
pub no_environment: bool,
|
||||
/// Skip auto-loading .gitignore files
|
||||
#[builder(default)]
|
||||
pub no_vcs_ignore: bool,
|
||||
/// Skip auto-loading .ignore files
|
||||
#[builder(default)]
|
||||
pub no_ignore: bool,
|
||||
/// For testing only, always set to false.
|
||||
#[builder(setter(skip))]
|
||||
#[builder(default)]
|
||||
#[doc(hidden)]
|
||||
pub once: bool,
|
||||
/// Force using the polling backend.
|
||||
#[builder(default)]
|
||||
pub poll: bool,
|
||||
/// Interval for polling. (milliseconds)
|
||||
#[builder(default = "1000")]
|
||||
pub poll_interval: u32,
|
||||
#[builder(default)]
|
||||
pub watch_when_idle: bool,
|
||||
}
|
||||
use crate::config::{Config, ConfigBuilder};
|
||||
|
||||
impl ArgsBuilder {
|
||||
fn validate(&self) -> Result<(), String> {
|
||||
if self.cmd.as_ref().map_or(true, Vec::is_empty) {
|
||||
return Err("cmd must not be empty".into());
|
||||
}
|
||||
#[deprecated(since = "1.15.0", note = "Config has moved to config::Config")]
|
||||
pub type Args = Config;
|
||||
|
||||
if self.paths.as_ref().map_or(true, Vec::is_empty) {
|
||||
return Err("paths must not be empty".into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[deprecated(since = "1.15.0", note = "does nothing. set the log level instead")]
|
||||
pub fn debug(&mut self, _: impl Into<bool>) -> &mut Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
#[deprecated(since = "1.15.0", note = "ConfigBuilder has moved to config::ConfigBuilder")]
|
||||
pub type ArgsBuilder = ConfigBuilder;
|
||||
|
||||
/// Clear the screen.
|
||||
#[cfg(target_family = "windows")]
|
||||
@ -120,12 +48,12 @@ pub fn clear_screen() {
|
||||
}
|
||||
|
||||
#[deprecated(since = "1.15.0", note = "this will be removed from the library API. use the builder")]
|
||||
pub fn get_args() -> error::Result<(Args, LevelFilter)> {
|
||||
pub fn get_args() -> error::Result<(Config, LevelFilter)> {
|
||||
get_args_impl(None::<&[&str]>)
|
||||
}
|
||||
|
||||
#[deprecated(since = "1.15.0", note = "this will be removed from the library API. use the builder")]
|
||||
pub fn get_args_from<I, T>(from: I) -> error::Result<(Args, LevelFilter)>
|
||||
pub fn get_args_from<I, T>(from: I) -> error::Result<(Config, LevelFilter)>
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone,
|
||||
@ -133,7 +61,7 @@ where
|
||||
get_args_impl(Some(from))
|
||||
}
|
||||
|
||||
fn get_args_impl<I, T>(from: Option<I>) -> error::Result<(Args, LevelFilter)>
|
||||
fn get_args_impl<I, T>(from: Option<I>) -> error::Result<(Config, LevelFilter)>
|
||||
where
|
||||
I: IntoIterator<Item = T>,
|
||||
T: Into<OsString> + Clone,
|
||||
@ -243,7 +171,7 @@ where
|
||||
Some(i) => app.get_matches_from(i),
|
||||
};
|
||||
|
||||
let mut builder = ArgsBuilder::default();
|
||||
let mut builder = ConfigBuilder::default();
|
||||
|
||||
let cmd: Vec<String> = values_t!(args.values_of("command"), String).map_err(|err| err.to_string())?;
|
||||
builder.cmd(cmd);
|
||||
|
96
src/config.rs
Normal file
96
src/config.rs
Normal file
@ -0,0 +1,96 @@
|
||||
//! Configuration for watchexec.
|
||||
//!
|
||||
//! The [`Config`] struct is not constructable, use [`ConfigBuilder`].
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```
|
||||
//! # use watchexec::config::ConfigBuilder;
|
||||
//! ConfigBuilder::default()
|
||||
//! .cmd(vec!["echo hello world".into()])
|
||||
//! .paths(vec![".".into()])
|
||||
//! .build()
|
||||
//! .expect("mission failed");
|
||||
//! ```
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Arguments to the watcher
|
||||
#[derive(Builder, Clone, Debug)]
|
||||
#[builder(setter(into, strip_option))]
|
||||
#[builder(build_fn(validate = "Self::validate"))]
|
||||
#[non_exhaustive]
|
||||
pub struct Config {
|
||||
/// Command to execute in popen3 format (first program, rest arguments).
|
||||
pub cmd: Vec<String>,
|
||||
/// List of paths to watch for changes.
|
||||
pub paths: Vec<PathBuf>,
|
||||
/// Positive filters (trigger only on matching changes). Glob format.
|
||||
#[builder(default)]
|
||||
pub filters: Vec<String>,
|
||||
/// Negative filters (do not trigger on matching changes). Glob format.
|
||||
#[builder(default)]
|
||||
pub ignores: Vec<String>,
|
||||
/// Clear the screen before each run.
|
||||
#[builder(default)]
|
||||
pub clear_screen: bool,
|
||||
/// If Some, send that signal (e.g. SIGHUP) to the child on change.
|
||||
#[builder(default)]
|
||||
pub signal: Option<String>,
|
||||
/// If true, kill the child if it's still running when a change comes in.
|
||||
#[builder(default)]
|
||||
pub restart: bool,
|
||||
/// Interval to debounce the changes. (milliseconds)
|
||||
#[builder(default = "500")]
|
||||
pub debounce: u64,
|
||||
/// Run the commands right after starting.
|
||||
#[builder(default = "true")]
|
||||
pub run_initially: bool,
|
||||
/// Do not wrap the commands in a shell.
|
||||
#[builder(default)]
|
||||
pub no_shell: bool,
|
||||
/// Ignore metadata changes.
|
||||
#[builder(default)]
|
||||
pub no_meta: bool,
|
||||
/// Do not set WATCHEXEC_*_PATH environment variables for child process.
|
||||
#[builder(default)]
|
||||
pub no_environment: bool,
|
||||
/// Skip auto-loading .gitignore files
|
||||
#[builder(default)]
|
||||
pub no_vcs_ignore: bool,
|
||||
/// Skip auto-loading .ignore files
|
||||
#[builder(default)]
|
||||
pub no_ignore: bool,
|
||||
/// For testing only, always set to false.
|
||||
#[builder(setter(skip))]
|
||||
#[builder(default)]
|
||||
#[doc(hidden)]
|
||||
pub once: bool,
|
||||
/// Force using the polling backend.
|
||||
#[builder(default)]
|
||||
pub poll: bool,
|
||||
/// Interval for polling. (milliseconds)
|
||||
#[builder(default = "1000")]
|
||||
pub poll_interval: u32,
|
||||
#[builder(default)]
|
||||
pub watch_when_idle: bool,
|
||||
}
|
||||
|
||||
impl ConfigBuilder {
|
||||
fn validate(&self) -> Result<(), String> {
|
||||
if self.cmd.as_ref().map_or(true, Vec::is_empty) {
|
||||
return Err("cmd must not be empty".into());
|
||||
}
|
||||
|
||||
if self.paths.as_ref().map_or(true, Vec::is_empty) {
|
||||
return Err("paths must not be empty".into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[deprecated(since = "1.15.0", note = "does nothing. set the log level instead")]
|
||||
pub fn debug(&mut self, _: impl Into<bool>) -> &mut Self {
|
||||
self
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ extern crate log;
|
||||
extern crate lazy_static;
|
||||
|
||||
pub mod cli;
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
mod gitignore;
|
||||
mod ignore;
|
||||
@ -34,5 +35,10 @@ pub mod run;
|
||||
mod signal;
|
||||
mod watcher;
|
||||
|
||||
pub use cli::{Args, ArgsBuilder};
|
||||
pub use run::{run, watch, Handler};
|
||||
|
||||
#[deprecated(since = "1.15.0", note = "Config has moved to config::Config")]
|
||||
pub type Args = config::Config;
|
||||
|
||||
#[deprecated(since = "1.15.0", note = "ConfigBuilder has moved to config::ConfigBuilder")]
|
||||
pub type ArgsBuilder = config::ConfigBuilder;
|
||||
|
15
src/run.rs
15
src/run.rs
@ -1,4 +1,5 @@
|
||||
use crate::cli::{clear_screen, Args};
|
||||
use crate::cli::{clear_screen};
|
||||
use crate::config::Config;
|
||||
use crate::error::{Error, Result};
|
||||
use crate::gitignore;
|
||||
use crate::ignore;
|
||||
@ -48,9 +49,9 @@ pub trait Handler {
|
||||
///
|
||||
/// Not called again; any changes will never be picked up.
|
||||
///
|
||||
/// The `Args` instance should be created using `ArgsBuilder` rather than direct initialisation
|
||||
/// The `Config` instance should be created using `ConfigBuilder` rather than direct initialisation
|
||||
/// to resist potential breaking changes (see semver policy on crate root).
|
||||
fn args(&self) -> Args;
|
||||
fn args(&self) -> Config;
|
||||
}
|
||||
|
||||
/// Starts watching, and calls a handler when something happens.
|
||||
@ -130,13 +131,13 @@ where
|
||||
}
|
||||
|
||||
pub struct ExecHandler {
|
||||
args: Args,
|
||||
args: Config,
|
||||
signal: Option<Signal>,
|
||||
child_process: Arc<RwLock<Option<Process>>>,
|
||||
}
|
||||
|
||||
impl ExecHandler {
|
||||
pub fn new(args: Args) -> Result<Self> {
|
||||
pub fn new(args: Config) -> Result<Self> {
|
||||
let child_process: Arc<RwLock<Option<Process>>> = Arc::new(RwLock::new(None));
|
||||
let weak_child = Arc::downgrade(&child_process);
|
||||
|
||||
@ -190,7 +191,7 @@ impl ExecHandler {
|
||||
}
|
||||
|
||||
impl Handler for ExecHandler {
|
||||
fn args(&self) -> Args {
|
||||
fn args(&self) -> Config {
|
||||
self.args.clone()
|
||||
}
|
||||
|
||||
@ -267,7 +268,7 @@ impl Handler for ExecHandler {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(args: Args) -> Result<()> {
|
||||
pub fn run(args: Config) -> Result<()> {
|
||||
watch(&ExecHandler::new(args)?)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user