Add --env and --workdir options

This commit is contained in:
Félix Saparelli 2022-04-15 15:30:00 +12:00 committed by Félix Saparelli
parent 6f3cdac9fd
commit f60a623a44
2 changed files with 66 additions and 13 deletions

View File

@ -47,7 +47,7 @@ pub fn get_args(tagged_filterer: bool) -> Result<ArgMatches<'static>> {
.multiple(true)
.takes_value(true))
.arg(Arg::with_name("clear")
.help_heading(Some(OPTSET_BEHAVIOUR))
.help_heading(Some(OPTSET_OUTPUT))
.help("Clear screen before executing command")
.short("c")
.long("clear"))
@ -135,7 +135,7 @@ pub fn get_args(tagged_filterer: bool) -> Result<ArgMatches<'static>> {
.short("n")
.long("no-shell"))
.arg(Arg::with_name("no-environment")
.help_heading(Some(OPTSET_OUTPUT))
.help_heading(Some(OPTSET_COMMAND))
.help("Do not set WATCHEXEC_*_PATH environment variables for the command")
.long("no-environment"))
.arg(Arg::with_name("no-process-group")
@ -158,7 +158,20 @@ pub fn get_args(tagged_filterer: bool) -> Result<ArgMatches<'static>> {
.help_heading(Some(OPTSET_FILTERING))
.help("Override the project origin: the directory from which ignore files are detected")
.value_name("path")
.long("project-origin"));
.long("project-origin"))
.arg(Arg::with_name("command-workdir")
.help_heading(Some(OPTSET_COMMAND))
.help("Change the working directory of the command")
.value_name("path")
.long("workdir"))
.arg(Arg::with_name("command-env")
.help_heading(Some(OPTSET_COMMAND))
.help("Add an environment variable to the command")
.value_name("name=value")
.long("env")
.short("E")
.number_of_values(1)
.multiple(true));
let app = if tagged_filterer {
app.arg(

View File

@ -1,8 +1,12 @@
use std::{convert::Infallible, env::current_dir, path::Path, str::FromStr, time::Duration};
use std::{
collections::HashMap, convert::Infallible, env::current_dir, ffi::OsString, path::Path,
str::FromStr, time::Duration,
};
use clap::ArgMatches;
use miette::{IntoDiagnostic, Result};
use miette::{miette, IntoDiagnostic, Result};
use notify_rust::Notification;
use tracing::debug;
use watchexec::{
action::{Action, Outcome, PostSpawn, PreSpawn},
command::Shell,
@ -196,18 +200,54 @@ pub fn runtime(args: &ArgMatches<'static>) -> Result<RuntimeConfig> {
fut
});
let mut add_envs = HashMap::new();
for pair in args.values_of_lossy("command-env").unwrap_or_default() {
if let Some((k, v)) = pair.split_once('=') {
add_envs.insert(k.to_owned(), OsString::from(v));
} else {
return Err(miette!("{pair} is not in key=value format"));
}
}
debug!(
?add_envs,
"additional environment variables to add to command"
);
let workdir = args
.value_of_os("command-workdir")
.map(|wkd| Path::new(wkd).to_owned());
let no_env = args.is_present("no-environment");
config.on_pre_spawn(move |prespawn: PreSpawn| async move {
if !no_env {
let envs = summarise_events_to_env(prespawn.events.iter());
if let Some(mut command) = prespawn.command().await {
for (k, v) in envs {
command.env(format!("WATCHEXEC_{}_PATH", k), v);
config.on_pre_spawn(move |prespawn: PreSpawn| {
let add_envs = add_envs.clone();
let workdir = workdir.clone();
async move {
if !no_env || !add_envs.is_empty() || workdir.is_some() {
if let Some(mut command) = prespawn.command().await {
let mut envs = add_envs.clone();
if !no_env {
envs.extend(
summarise_events_to_env(prespawn.events.iter())
.into_iter()
.map(|(k, v)| (format!("WATCHEXEC_{}_PATH", k), v)),
);
}
for (k, v) in envs {
debug!(?k, ?v, "inserting environment variable");
command.env(k, v);
}
if let Some(ref workdir) = workdir {
debug!(?workdir, "set command workdir");
command.current_dir(workdir);
}
}
}
}
Ok::<(), Infallible>(())
Ok::<(), Infallible>(())
}
});
config.on_post_spawn(SyncFnHandler::from(move |postspawn: PostSpawn| {