2021-10-13 14:26:15 +02:00
|
|
|
use std::{
|
|
|
|
collections::HashSet,
|
|
|
|
env::{self, var},
|
|
|
|
path::PathBuf,
|
|
|
|
};
|
2020-06-24 16:17:59 +02:00
|
|
|
|
2021-10-13 13:38:56 +02:00
|
|
|
use dunce::canonicalize;
|
2021-10-09 07:43:51 +02:00
|
|
|
use miette::{IntoDiagnostic, Result};
|
2021-10-13 13:38:56 +02:00
|
|
|
use tracing::{debug, warn};
|
|
|
|
use watchexec::{
|
|
|
|
event::Event,
|
|
|
|
filter::tagged::{Filter, Matcher, Op, Pattern, Regex},
|
|
|
|
ignore_files::{self, IgnoreFile},
|
|
|
|
project::{self, ProjectType},
|
|
|
|
Watchexec,
|
|
|
|
};
|
2021-05-10 12:44:35 +02:00
|
|
|
|
2021-04-10 15:33:40 +02:00
|
|
|
mod args;
|
2021-08-24 10:23:37 +02:00
|
|
|
mod config;
|
2016-09-14 15:30:59 +02:00
|
|
|
|
2021-08-24 10:23:37 +02:00
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<()> {
|
2021-09-28 14:47:18 +02:00
|
|
|
#[cfg(feature = "dev-console")]
|
|
|
|
console_subscriber::init();
|
|
|
|
|
|
|
|
if var("RUST_LOG").is_ok() && cfg!(not(feature = "dev-console")) {
|
2021-08-24 10:23:37 +02:00
|
|
|
tracing_subscriber::fmt::init();
|
|
|
|
}
|
2021-05-10 12:44:35 +02:00
|
|
|
|
2021-08-24 10:23:37 +02:00
|
|
|
let args = args::get_args()?;
|
|
|
|
|
2021-10-13 13:38:56 +02:00
|
|
|
tracing_subscriber::fmt()
|
|
|
|
.with_env_filter(match args.occurrences_of("verbose") {
|
|
|
|
0 => "watchexec-cli=warn",
|
|
|
|
1 => "watchexec=debug,watchexec-cli=debug",
|
|
|
|
2 => "watchexec=trace,watchexec-cli=trace",
|
|
|
|
_ => "trace",
|
|
|
|
})
|
|
|
|
.try_init()
|
|
|
|
.ok();
|
|
|
|
|
|
|
|
let mut origins = HashSet::new();
|
|
|
|
for path in args.values_of("paths").unwrap_or_default().into_iter() {
|
|
|
|
let path = canonicalize(path).into_diagnostic()?;
|
|
|
|
origins.extend(project::origins(&path).await);
|
|
|
|
}
|
|
|
|
|
|
|
|
debug!(?origins, "resolved all project origins");
|
|
|
|
|
|
|
|
let project_origin = project::common_prefix(&origins).unwrap_or_else(|| PathBuf::from("."));
|
|
|
|
debug!(?project_origin, "resolved common/project origin");
|
|
|
|
|
|
|
|
let vcs_types = project::types(&project_origin)
|
|
|
|
.await
|
|
|
|
.into_iter()
|
|
|
|
.filter(|pt| pt.is_vcs())
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
debug!(?vcs_types, "resolved vcs types");
|
|
|
|
|
|
|
|
let (mut ignores, _errors) = ignore_files::from_origin(&project_origin).await;
|
|
|
|
// TODO: handle errors
|
|
|
|
debug!(?ignores, "discovered ignore files from project origin");
|
|
|
|
|
|
|
|
let mut skip_git_global_excludes = false;
|
|
|
|
if !vcs_types.is_empty() {
|
|
|
|
ignores = ignores
|
|
|
|
.into_iter()
|
|
|
|
.filter(|ig| match ig.applies_to {
|
|
|
|
Some(pt) if pt.is_vcs() => vcs_types.contains(&pt),
|
|
|
|
_ => true,
|
|
|
|
})
|
|
|
|
.inspect(|ig| {
|
|
|
|
if let IgnoreFile {
|
|
|
|
applies_to: Some(ProjectType::Git),
|
|
|
|
applies_in: None,
|
|
|
|
..
|
|
|
|
} = ig
|
|
|
|
{
|
|
|
|
warn!("project git config overrides the global excludes");
|
|
|
|
skip_git_global_excludes = true;
|
|
|
|
}
|
2021-08-24 12:45:31 +02:00
|
|
|
})
|
2021-10-13 13:38:56 +02:00
|
|
|
.collect::<Vec<_>>();
|
|
|
|
debug!(?ignores, "filtered ignores to only those for project vcs");
|
|
|
|
// TODO: use drain_ignore when that stabilises
|
|
|
|
}
|
|
|
|
|
|
|
|
let (mut global_ignores, _errors) = ignore_files::from_environment().await;
|
|
|
|
// TODO: handle errors
|
|
|
|
debug!(?global_ignores, "discovered ignore files from environment");
|
|
|
|
|
|
|
|
if skip_git_global_excludes {
|
|
|
|
global_ignores = global_ignores
|
|
|
|
.into_iter()
|
|
|
|
.filter(|gig| {
|
|
|
|
!matches!(
|
|
|
|
gig,
|
|
|
|
IgnoreFile {
|
|
|
|
applies_to: Some(ProjectType::Git),
|
|
|
|
applies_in: None,
|
|
|
|
..
|
|
|
|
}
|
|
|
|
)
|
|
|
|
})
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
debug!(
|
|
|
|
?global_ignores,
|
|
|
|
"filtered global ignores to exclude global git ignores"
|
|
|
|
);
|
|
|
|
// TODO: use drain_ignore when that stabilises
|
|
|
|
}
|
|
|
|
|
|
|
|
if !vcs_types.is_empty() {
|
|
|
|
ignores.extend(global_ignores.into_iter().filter(|ig| match ig.applies_to {
|
|
|
|
Some(pt) if pt.is_vcs() => vcs_types.contains(&pt),
|
|
|
|
_ => true,
|
|
|
|
}));
|
|
|
|
debug!(?ignores, "combined and applied final filter over ignores");
|
2021-08-24 10:23:37 +02:00
|
|
|
}
|
|
|
|
|
2021-10-12 13:48:42 +02:00
|
|
|
let mut filters = Vec::new();
|
2021-09-28 11:24:06 +02:00
|
|
|
|
2021-10-13 14:26:15 +02:00
|
|
|
// TODO: move into config
|
|
|
|
let workdir = env::current_dir()
|
|
|
|
.and_then(|wd| wd.canonicalize())
|
|
|
|
.into_diagnostic()?;
|
2021-09-28 11:24:06 +02:00
|
|
|
for filter in args.values_of("filter").unwrap_or_default() {
|
2021-10-13 14:26:15 +02:00
|
|
|
let mut filter: Filter = filter.parse()?;
|
|
|
|
filter.in_path = Some(workdir.clone());
|
|
|
|
filters.push(filter);
|
2021-09-28 11:24:06 +02:00
|
|
|
}
|
2021-08-24 10:23:37 +02:00
|
|
|
|
2021-10-13 13:38:56 +02:00
|
|
|
for ext in args
|
|
|
|
.values_of("extensions")
|
|
|
|
.unwrap_or_default()
|
|
|
|
.map(|s| s.split(',').map(|s| s.trim()))
|
|
|
|
.flatten()
|
|
|
|
{
|
2021-10-12 13:48:42 +02:00
|
|
|
filters.push(Filter {
|
2021-10-09 07:45:32 +02:00
|
|
|
in_path: None,
|
|
|
|
on: Matcher::Path,
|
2021-10-13 13:38:56 +02:00
|
|
|
op: Op::Regex,
|
|
|
|
pat: Pattern::Regex(Regex::new(&format!("[.]{}$", ext)).into_diagnostic()?),
|
2021-10-09 07:45:32 +02:00
|
|
|
negate: false,
|
2021-10-12 13:48:42 +02:00
|
|
|
});
|
2021-10-09 07:45:32 +02:00
|
|
|
}
|
|
|
|
|
2021-10-13 14:26:15 +02:00
|
|
|
debug!(?filters, "parsed filters and extensions");
|
|
|
|
|
2021-10-12 13:48:42 +02:00
|
|
|
let (init, runtime, filterer) = config::new(&args)?;
|
|
|
|
filterer.add_filters(&filters).await?;
|
|
|
|
|
2021-10-13 13:38:56 +02:00
|
|
|
for ignore in &ignores {
|
|
|
|
filterer.add_ignore_file(ignore).await?;
|
|
|
|
}
|
|
|
|
|
2021-08-24 10:23:37 +02:00
|
|
|
let wx = Watchexec::new(init, runtime)?;
|
|
|
|
|
2021-08-24 12:45:31 +02:00
|
|
|
if !args.is_present("postpone") {
|
|
|
|
wx.send_event(Event::default()).await?;
|
|
|
|
}
|
|
|
|
|
2021-10-09 07:43:51 +02:00
|
|
|
wx.main().await.into_diagnostic()??;
|
2021-08-24 10:23:37 +02:00
|
|
|
|
|
|
|
Ok(())
|
2020-06-24 16:17:59 +02:00
|
|
|
}
|