From ec316a7279fe50bdbb04c518a78afb03fd0d5ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Saparelli?= Date: Sat, 20 Apr 2024 23:44:21 +1200 Subject: [PATCH] Breaking changes to CLI: various removals (#819) --- completions/bash | 2 +- completions/elvish | 6 +-- completions/fish | 5 +- completions/nu | 5 +- completions/powershell | 6 +-- completions/zsh | 6 +-- crates/cli/README.md | 2 +- crates/cli/src/args.rs | 109 ++++++++++++++++--------------------- doc/watchexec.1 | 83 +++++++++++++--------------- doc/watchexec.1.md | 120 ++++++++++++++++++++--------------------- 10 files changed, 154 insertions(+), 190 deletions(-) diff --git a/completions/bash b/completions/bash index 6c73319..ccd16ef 100644 --- a/completions/bash +++ b/completions/bash @@ -19,7 +19,7 @@ _watchexec() { case "${cmd}" in watchexec) - opts="-w -c -o -r -s -k -d -p -n -E -1 -N -q -e -f -j -i -v -h -V --watch --clear --on-busy-update --restart --signal --kill --stop-signal --stop-timeout --map-signal --debounce --stdin-quit --no-vcs-ignore --no-project-ignore --no-global-ignore --no-default-ignore --no-discover-ignore --ignore-nothing --postpone --delay-run --poll --shell --no-environment --emit-events-to --only-emit-events --env --no-process-group --notify --color --timings --quiet --bell --project-origin --workdir --exts --filter --filter-file --filter-prog --ignore --ignore-file --fs-events --no-meta --print-events --verbose --log-file --manual --completions --help --version [COMMAND]..." + opts="-w -c -o -r -s -d -p -n -E -1 -N -q -e -f -j -i -v -h -V --watch --clear --on-busy-update --restart --signal --stop-signal --stop-timeout --map-signal --debounce --stdin-quit --no-vcs-ignore --no-project-ignore --no-global-ignore --no-default-ignore --no-discover-ignore --ignore-nothing --postpone --delay-run --poll --shell --no-environment --emit-events-to --only-emit-events --env --no-process-group --notify --color --timings --quiet --bell --project-origin --workdir --exts --filter --filter-file --filter-prog --ignore --ignore-file --fs-events --no-meta --print-events --verbose --log-file --manual --completions --help --version [COMMAND]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/completions/elvish b/completions/elvish index 4faa17b..48ac72b 100644 --- a/completions/elvish +++ b/completions/elvish @@ -55,8 +55,6 @@ set edit:completion:arg-completer[watchexec] = {|@words| cand --completions 'Generate a shell completions script' cand -r 'Restart the process if it''s still running' cand --restart 'Restart the process if it''s still running' - cand -k 'Hidden legacy shorthand for ''--signal=kill''' - cand --kill 'Hidden legacy shorthand for ''--signal=kill''' cand --stdin-quit 'Exit when stdin closes' cand --no-vcs-ignore 'Don''t load gitignores' cand --no-project-ignore 'Don''t load project-local ignores' @@ -66,8 +64,8 @@ set edit:completion:arg-completer[watchexec] = {|@words| cand --ignore-nothing 'Don''t ignore anything at all' cand -p 'Wait until first change before running command' cand --postpone 'Wait until first change before running command' - cand -n 'Don''t use a shell' - cand --no-environment 'Shorthand for ''--emit-events=none''' + cand -n 'Shorthand for ''--shell=none''' + cand --no-environment 'Deprecated shorthand for ''--emit-events=none''' cand --only-emit-events 'Only emit events to stdout, run no commands' cand --no-process-group 'Don''t use a process group' cand -1 'Testing only: exit Watchexec after the first run' diff --git a/completions/fish b/completions/fish index 81fc250..aa02838 100644 --- a/completions/fish +++ b/completions/fish @@ -24,7 +24,6 @@ complete -c watchexec -l fs-events -d 'Filesystem events to filter to' -r -f -a complete -c watchexec -l log-file -d 'Write diagnostic logs to a file' -r -F complete -c watchexec -l completions -d 'Generate a shell completions script' -r -f -a "{bash '',elvish '',fish '',nu '',powershell '',zsh ''}" complete -c watchexec -s r -l restart -d 'Restart the process if it\'s still running' -complete -c watchexec -s k -l kill -d 'Hidden legacy shorthand for \'--signal=kill\'' complete -c watchexec -l stdin-quit -d 'Exit when stdin closes' complete -c watchexec -l no-vcs-ignore -d 'Don\'t load gitignores' complete -c watchexec -l no-project-ignore -d 'Don\'t load project-local ignores' @@ -33,8 +32,8 @@ complete -c watchexec -l no-default-ignore -d 'Don\'t use internal default ignor complete -c watchexec -l no-discover-ignore -d 'Don\'t discover ignore files at all' complete -c watchexec -l ignore-nothing -d 'Don\'t ignore anything at all' complete -c watchexec -s p -l postpone -d 'Wait until first change before running command' -complete -c watchexec -s n -d 'Don\'t use a shell' -complete -c watchexec -l no-environment -d 'Shorthand for \'--emit-events=none\'' +complete -c watchexec -s n -d 'Shorthand for \'--shell=none\'' +complete -c watchexec -l no-environment -d 'Deprecated shorthand for \'--emit-events=none\'' complete -c watchexec -l only-emit-events -d 'Only emit events to stdout, run no commands' complete -c watchexec -l no-process-group -d 'Don\'t use a process group' complete -c watchexec -s 1 -d 'Testing only: exit Watchexec after the first run' diff --git a/completions/nu b/completions/nu index 6c577ce..583cf71 100644 --- a/completions/nu +++ b/completions/nu @@ -32,7 +32,6 @@ module completions { --on-busy-update(-o): string@"nu-complete watchexec on_busy_update" # What to do when receiving events while the command is running --restart(-r) # Restart the process if it's still running --signal(-s): string # Send a signal to the process when it's still running - --kill(-k) # Hidden legacy shorthand for '--signal=kill' --stop-signal: string # Signal to send to stop the command --stop-timeout: string # Time to wait for the command to exit gracefully --map-signal: string # Translate signals from the OS to signals to send to the command @@ -48,8 +47,8 @@ module completions { --delay-run: string # Sleep before running the command --poll: string # Poll for filesystem changes --shell: string # Use a different shell - -n # Don't use a shell - --no-environment # Shorthand for '--emit-events=none' + -n # Shorthand for '--shell=none' + --no-environment # Deprecated shorthand for '--emit-events=none' --emit-events-to: string@"nu-complete watchexec emit_events_to" # Configure event emission --only-emit-events # Only emit events to stdout, run no commands --env(-E): string # Add env vars to the command diff --git a/completions/powershell b/completions/powershell index 330890c..d2f8678 100644 --- a/completions/powershell +++ b/completions/powershell @@ -58,8 +58,6 @@ Register-ArgumentCompleter -Native -CommandName 'watchexec' -ScriptBlock { [CompletionResult]::new('--completions', 'completions', [CompletionResultType]::ParameterName, 'Generate a shell completions script') [CompletionResult]::new('-r', 'r', [CompletionResultType]::ParameterName, 'Restart the process if it''s still running') [CompletionResult]::new('--restart', 'restart', [CompletionResultType]::ParameterName, 'Restart the process if it''s still running') - [CompletionResult]::new('-k', 'k', [CompletionResultType]::ParameterName, 'Hidden legacy shorthand for ''--signal=kill''') - [CompletionResult]::new('--kill', 'kill', [CompletionResultType]::ParameterName, 'Hidden legacy shorthand for ''--signal=kill''') [CompletionResult]::new('--stdin-quit', 'stdin-quit', [CompletionResultType]::ParameterName, 'Exit when stdin closes') [CompletionResult]::new('--no-vcs-ignore', 'no-vcs-ignore', [CompletionResultType]::ParameterName, 'Don''t load gitignores') [CompletionResult]::new('--no-project-ignore', 'no-project-ignore', [CompletionResultType]::ParameterName, 'Don''t load project-local ignores') @@ -69,8 +67,8 @@ Register-ArgumentCompleter -Native -CommandName 'watchexec' -ScriptBlock { [CompletionResult]::new('--ignore-nothing', 'ignore-nothing', [CompletionResultType]::ParameterName, 'Don''t ignore anything at all') [CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Wait until first change before running command') [CompletionResult]::new('--postpone', 'postpone', [CompletionResultType]::ParameterName, 'Wait until first change before running command') - [CompletionResult]::new('-n', 'n', [CompletionResultType]::ParameterName, 'Don''t use a shell') - [CompletionResult]::new('--no-environment', 'no-environment', [CompletionResultType]::ParameterName, 'Shorthand for ''--emit-events=none''') + [CompletionResult]::new('-n', 'n', [CompletionResultType]::ParameterName, 'Shorthand for ''--shell=none''') + [CompletionResult]::new('--no-environment', 'no-environment', [CompletionResultType]::ParameterName, 'Deprecated shorthand for ''--emit-events=none''') [CompletionResult]::new('--only-emit-events', 'only-emit-events', [CompletionResultType]::ParameterName, 'Only emit events to stdout, run no commands') [CompletionResult]::new('--no-process-group', 'no-process-group', [CompletionResultType]::ParameterName, 'Don''t use a process group') [CompletionResult]::new('-1', '1', [CompletionResultType]::ParameterName, 'Testing only: exit Watchexec after the first run') diff --git a/completions/zsh b/completions/zsh index 71be820..a7ebb08 100644 --- a/completions/zsh +++ b/completions/zsh @@ -52,8 +52,6 @@ _watchexec() { '(--manual)--completions=[Generate a shell completions script]:COMPLETIONS:(bash elvish fish nu powershell zsh)' \ '(-o --on-busy-update)-r[Restart the process if it'\''s still running]' \ '(-o --on-busy-update)--restart[Restart the process if it'\''s still running]' \ -'-k[Hidden legacy shorthand for '\''--signal=kill'\'']' \ -'--kill[Hidden legacy shorthand for '\''--signal=kill'\'']' \ '--stdin-quit[Exit when stdin closes]' \ '--no-vcs-ignore[Don'\''t load gitignores]' \ '--no-project-ignore[Don'\''t load project-local ignores]' \ @@ -63,8 +61,8 @@ _watchexec() { '--ignore-nothing[Don'\''t ignore anything at all]' \ '-p[Wait until first change before running command]' \ '--postpone[Wait until first change before running command]' \ -'-n[Don'\''t use a shell]' \ -'--no-environment[Shorthand for '\''--emit-events=none'\'']' \ +'-n[Shorthand for '\''--shell=none'\'']' \ +'--no-environment[Deprecated shorthand for '\''--emit-events=none'\'']' \ '(--completions --manual)--only-emit-events[Only emit events to stdout, run no commands]' \ '--no-process-group[Don'\''t use a process group]' \ '-1[Testing only\: exit Watchexec after the first run]' \ diff --git a/crates/cli/README.md b/crates/cli/README.md index 41dd1f7..4c689e3 100644 --- a/crates/cli/README.md +++ b/crates/cli/README.md @@ -37,7 +37,7 @@ Example use cases: These variables may contain multiple paths: these are separated by the platform's path separator, as with the `PATH` system environment variable. On Unix that is `:`, and on Windows `;`. Within each variable, paths are deduplicated and sorted in binary order (i.e. neither Unicode nor locale aware). - This can be disabled or limited with `--no-environment` (doesn't set any of these variables) and `--no-meta` (ignores metadata changes). + This can be disabled with `--emit-events=none` or changed to JSON events on STDIN with `--emit-events=json-stdio`. ## Anti-Features diff --git a/crates/cli/src/args.rs b/crates/cli/src/args.rs index 93af4de..40e731f 100644 --- a/crates/cli/src/args.rs +++ b/crates/cli/src/args.rs @@ -193,10 +193,6 @@ pub struct Args { )] pub signal: Option, - /// Hidden legacy shorthand for '--signal=kill'. - #[arg(short, long, hide = true)] - pub kill: bool, - /// Signal to send to stop the command /// /// This is used by 'restart' and 'signal' modes of '--on-busy-update' (unless '--signal' is @@ -223,14 +219,15 @@ pub struct Args { /// it is forcefully terminated. /// /// Takes a unit-less value in seconds, or a time span value such as "5min 20s". + /// Providing a unit-less value is deprecated and will warn; it will be an error in the future. /// - /// The default is 60 seconds. Set to 0 to immediately force-kill the command. + /// The default is 10 seconds. Set to 0 to immediately force-kill the command. /// /// This has no practical effect on Windows as the command is always forcefully terminated; see /// '--stop-signal' for why. #[arg( long, - default_value = "60", + default_value = "10s", hide_default_value = true, value_name = "TIMEOUT" )] @@ -270,12 +267,13 @@ pub struct Args { /// every accumulated event will build up in memory. /// /// Takes a unit-less value in milliseconds, or a time span value such as "5sec 20ms". + /// Providing a unit-less value is deprecated and will warn; it will be an error in the future. /// /// The default is 50 milliseconds. Setting to 0 is highly discouraged. #[arg( long, short, - default_value = "50", + default_value = "50ms", hide_default_value = true, value_name = "TIMEOUT" )] @@ -320,14 +318,10 @@ pub struct Args { /// VCS ignore files (Git, Mercurial, Bazaar, Darcs, Fossil) are only used if the corresponding /// VCS is discovered to be in use for the project/origin. For example, a .bzrignore in a Git /// repository will be discarded. - /// - /// Note that this was previously called '--no-ignore', but that's now deprecated and its use is - /// discouraged, as it may be repurposed in the future. #[arg( long, help_heading = OPTSET_FILTERING, verbatim_doc_comment, - alias = "no-ignore", // deprecated )] pub no_project_ignore: bool, @@ -402,6 +396,7 @@ pub struct Args { /// but portable and slightly more efficient. /// /// Takes a unit-less value in seconds, or a time span value such as "2min 5s". + /// Providing a unit-less value is deprecated and will warn; it will be an error in the future. #[arg(long, value_name = "DURATION")] pub delay_run: Option, @@ -414,6 +409,7 @@ pub struct Args { /// /// Optionally takes a unit-less value in milliseconds, or a time span value such as "2s 500ms", /// to use as the polling interval. If not specified, the default is 30 seconds. + /// Providing a unit-less value is deprecated and will warn; it will be an error in the future. /// /// Aliased as '--force-poll'. #[arg( @@ -476,30 +472,28 @@ pub struct Args { )] pub shell: Option, - /// Don't use a shell - /// - /// This is a shorthand for '--shell=none'. + /// Shorthand for '--shell=none' #[arg( short = 'n', help_heading = OPTSET_COMMAND, )] pub no_shell: bool, - /// Shorthand for '--emit-events=none' + /// Deprecated shorthand for '--emit-events=none' /// /// This is the old way to disable event emission into the environment. See '--emit-events' for - /// more. + /// more. Will be removed at next major release. #[arg( long, help_heading = OPTSET_COMMAND, - // TODO: deprecate then remove + hide = true, // deprecated )] pub no_environment: bool, /// Configure event emission /// - /// Watchexec emits event information when running a command, which can be used by the command - /// to target specific changed files. + /// Watchexec can emit event information when running a command, which can be used by the child + /// process to target specific changed files. /// /// One thing to take care with is assuming inherent behaviour where there is only chance. /// Notably, it could appear as if the `RENAMED` variable contains both the original and the new @@ -510,32 +504,14 @@ pub struct Args { /// whether it was the old or new isn't known), rename events might split across two debouncing /// boundaries, and so on. /// - /// This option controls where that information is emitted. It defaults to 'environment', which - /// sets environment variables with the paths of the affected files, for filesystem events: + /// This option controls where that information is emitted. It defaults to 'none', which doesn't + /// emit event information at all. The other options are 'environment' (deprecated), 'stdio', + /// 'file', 'json-stdio', and 'json-file'. /// - /// $WATCHEXEC_COMMON_PATH is set to the longest common path of all of the below variables, - /// and so should be prepended to each path to obtain the full/real path. Then: - /// - /// - $WATCHEXEC_CREATED_PATH is set when files/folders were created - /// - $WATCHEXEC_REMOVED_PATH is set when files/folders were removed - /// - $WATCHEXEC_RENAMED_PATH is set when files/folders were renamed - /// - $WATCHEXEC_WRITTEN_PATH is set when files/folders were modified - /// - $WATCHEXEC_META_CHANGED_PATH is set when files/folders' metadata were modified - /// - $WATCHEXEC_OTHERWISE_CHANGED_PATH is set for every other kind of pathed event - /// - /// Multiple paths are separated by the system path separator, ';' on Windows and ':' on unix. - /// Within each variable, paths are deduplicated and sorted in binary order (i.e. neither - /// Unicode nor locale aware). - /// - /// This is the legacy mode and will be deprecated and removed in the future. The environment of - /// a process is a very restricted space, while also limited in what it can usefully represent. - /// Large numbers of files will either cause the environment to be truncated, or may error or - /// crash the process entirely. - /// - /// Two new modes are available: 'stdio' writes absolute paths to the stdin of the command, - /// one per line, each prefixed with `create:`, `remove:`, `rename:`, `modify:`, or `other:`, - /// then closes the handle; 'file' writes the same thing to a temporary file, and its path is - /// given with the $WATCHEXEC_EVENTS_FILE environment variable. + /// The 'stdio' and 'file' modes are text-based: 'stdio' writes absolute paths to the stdin of + /// the command, one per line, each prefixed with `create:`, `remove:`, `rename:`, `modify:`, + /// or `other:`, then closes the handle; 'file' writes the same thing to a temporary file, and + /// its path is given with the $WATCHEXEC_EVENTS_FILE environment variable. /// /// There are also two JSON modes, which are based on JSON objects and can represent the full /// set of events Watchexec handles. Here's an example of a folder being created on Linux: @@ -592,13 +568,33 @@ pub struct Args { /// events to it, and provide the path to the file with the $WATCHEXEC_EVENTS_FILE /// environment variable. /// - /// Finally, the special 'none' mode will disable event emission entirely. - // TODO: when deprecating, make the none mode the default. + /// Finally, the 'environment' mode was the default until 2.0. It sets environment variables + /// with the paths of the affected files, for filesystem events: + /// + /// $WATCHEXEC_COMMON_PATH is set to the longest common path of all of the below variables, + /// and so should be prepended to each path to obtain the full/real path. Then: + /// + /// - $WATCHEXEC_CREATED_PATH is set when files/folders were created + /// - $WATCHEXEC_REMOVED_PATH is set when files/folders were removed + /// - $WATCHEXEC_RENAMED_PATH is set when files/folders were renamed + /// - $WATCHEXEC_WRITTEN_PATH is set when files/folders were modified + /// - $WATCHEXEC_META_CHANGED_PATH is set when files/folders' metadata were modified + /// - $WATCHEXEC_OTHERWISE_CHANGED_PATH is set for every other kind of pathed event + /// + /// Multiple paths are separated by the system path separator, ';' on Windows and ':' on unix. + /// Within each variable, paths are deduplicated and sorted in binary order (i.e. neither + /// Unicode nor locale aware). + /// + /// This is the legacy mode, is deprecated, and will be removed in the future. The environment + /// is a very restricted space, while also limited in what it can usefully represent. Large + /// numbers of files will either cause the environment to be truncated, or may error or crash + /// the process entirely. The $WATCHEXEC_COMMON_PATH is also unintuitive, as demonstrated by the + /// multiple confused queries that have landed in my inbox over the years. #[arg( long, help_heading = OPTSET_COMMAND, verbatim_doc_comment, - default_value = "environment", + default_value = "none", hide_default_value = true, value_name = "MODE", required_if_eq("only_emit_events", "true"), @@ -912,7 +908,6 @@ pub struct Args { /// Use '-v' when you need more diagnostic information. #[arg( long, - alias = "changes-only", // deprecated help_heading = OPTSET_DEBUGGING, )] pub print_events: bool, @@ -988,10 +983,8 @@ pub struct Args { pub enum EmitEvents { #[default] Environment, - #[value(alias("stdin"))] Stdio, File, - #[value(alias("json-stdin"))] JsonStdio, JsonFile, None, @@ -1050,7 +1043,10 @@ impl FromStr for TimeSpan() .map_or_else( |_| humantime::parse_duration(s), - |unitless| Ok(Duration::from_nanos(unitless * UNITLESS_NANOS_MULTIPLIER)), + |unitless| { + eprintln!("Warning: unitless time span values are deprecated and will be removed in an upcoming version"); + Ok(Duration::from_nanos(unitless * UNITLESS_NANOS_MULTIPLIER)) + }, ) .map(TimeSpan) } @@ -1146,13 +1142,6 @@ pub async fn get_args() -> Result { warn!("⚠ RUST_LOG environment variable set, logging options have no effect"); } - if let Ok(filt) = std::env::var("WATCHEXEC_FILTERER") { - warn!("WATCHEXEC_FILTERER is deprecated"); - if filt == "tagged" { - eprintln!("Tagged filterer has been removed. Open an issue if you have no workaround."); - } - } - debug!("expanding @argfile arguments if any"); let args = expand_args_up_to_doubledash().expect("while expanding @argfile"); @@ -1172,10 +1161,6 @@ pub async fn get_args() -> Result { args.no_discover_ignore = true; } - if args.kill { - args.signal = Some(Signal::ForceStop); - } - if args.signal.is_some() { args.on_busy_update = OnBusyUpdate::Signal; } else if args.restart { diff --git a/doc/watchexec.1 b/doc/watchexec.1 index 4a0fdbb..714a896 100644 --- a/doc/watchexec.1 +++ b/doc/watchexec.1 @@ -4,7 +4,7 @@ .SH NAME watchexec \- Execute commands when watched files change .SH SYNOPSIS -\fBwatchexec\fR [\fB\-w\fR|\fB\-\-watch\fR] [\fB\-c\fR|\fB\-\-clear\fR] [\fB\-o\fR|\fB\-\-on\-busy\-update\fR] [\fB\-r\fR|\fB\-\-restart\fR] [\fB\-s\fR|\fB\-\-signal\fR] [\fB\-\-stop\-signal\fR] [\fB\-\-stop\-timeout\fR] [\fB\-\-map\-signal\fR] [\fB\-d\fR|\fB\-\-debounce\fR] [\fB\-\-stdin\-quit\fR] [\fB\-\-no\-vcs\-ignore\fR] [\fB\-\-no\-project\-ignore\fR] [\fB\-\-no\-global\-ignore\fR] [\fB\-\-no\-default\-ignore\fR] [\fB\-\-no\-discover\-ignore\fR] [\fB\-\-ignore\-nothing\fR] [\fB\-p\fR|\fB\-\-postpone\fR] [\fB\-\-delay\-run\fR] [\fB\-\-poll\fR] [\fB\-\-shell\fR] [\fB\-n \fR] [\fB\-\-no\-environment\fR] [\fB\-\-emit\-events\-to\fR] [\fB\-\-only\-emit\-events\fR] [\fB\-E\fR|\fB\-\-env\fR] [\fB\-\-no\-process\-group\fR] [\fB\-N\fR|\fB\-\-notify\fR] [\fB\-\-color\fR] [\fB\-\-timings\fR] [\fB\-q\fR|\fB\-\-quiet\fR] [\fB\-\-bell\fR] [\fB\-\-project\-origin\fR] [\fB\-\-workdir\fR] [\fB\-e\fR|\fB\-\-exts\fR] [\fB\-f\fR|\fB\-\-filter\fR] [\fB\-\-filter\-file\fR] [\fB\-j\fR|\fB\-\-filter\-prog\fR] [\fB\-i\fR|\fB\-\-ignore\fR] [\fB\-\-ignore\-file\fR] [\fB\-\-fs\-events\fR] [\fB\-\-no\-meta\fR] [\fB\-\-print\-events\fR] [\fB\-v\fR|\fB\-\-verbose\fR]... [\fB\-\-log\-file\fR] [\fB\-\-manual\fR] [\fB\-\-completions\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fICOMMAND\fR] +\fBwatchexec\fR [\fB\-w\fR|\fB\-\-watch\fR] [\fB\-c\fR|\fB\-\-clear\fR] [\fB\-o\fR|\fB\-\-on\-busy\-update\fR] [\fB\-r\fR|\fB\-\-restart\fR] [\fB\-s\fR|\fB\-\-signal\fR] [\fB\-\-stop\-signal\fR] [\fB\-\-stop\-timeout\fR] [\fB\-\-map\-signal\fR] [\fB\-d\fR|\fB\-\-debounce\fR] [\fB\-\-stdin\-quit\fR] [\fB\-\-no\-vcs\-ignore\fR] [\fB\-\-no\-project\-ignore\fR] [\fB\-\-no\-global\-ignore\fR] [\fB\-\-no\-default\-ignore\fR] [\fB\-\-no\-discover\-ignore\fR] [\fB\-\-ignore\-nothing\fR] [\fB\-p\fR|\fB\-\-postpone\fR] [\fB\-\-delay\-run\fR] [\fB\-\-poll\fR] [\fB\-\-shell\fR] [\fB\-n \fR] [\fB\-\-emit\-events\-to\fR] [\fB\-\-only\-emit\-events\fR] [\fB\-E\fR|\fB\-\-env\fR] [\fB\-\-no\-process\-group\fR] [\fB\-N\fR|\fB\-\-notify\fR] [\fB\-\-color\fR] [\fB\-\-timings\fR] [\fB\-q\fR|\fB\-\-quiet\fR] [\fB\-\-bell\fR] [\fB\-\-project\-origin\fR] [\fB\-\-workdir\fR] [\fB\-e\fR|\fB\-\-exts\fR] [\fB\-f\fR|\fB\-\-filter\fR] [\fB\-\-filter\-file\fR] [\fB\-j\fR|\fB\-\-filter\-prog\fR] [\fB\-i\fR|\fB\-\-ignore\fR] [\fB\-\-ignore\-file\fR] [\fB\-\-fs\-events\fR] [\fB\-\-no\-meta\fR] [\fB\-\-print\-events\fR] [\fB\-v\fR|\fB\-\-verbose\fR]... [\fB\-\-log\-file\fR] [\fB\-\-manual\fR] [\fB\-\-completions\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fICOMMAND\fR] .SH DESCRIPTION Execute commands when watched files change. .PP @@ -92,9 +92,9 @@ Time to wait for the command to exit gracefully This is used by the \*(Aqrestart\*(Aq mode of \*(Aq\-\-on\-busy\-update\*(Aq. After the graceful stop signal is sent, Watchexec will wait for the command to exit. If it hasn\*(Aqt exited after this time, it is forcefully terminated. -Takes a unit\-less value in seconds, or a time span value such as "5min 20s". +Takes a unit\-less value in seconds, or a time span value such as "5min 20s". Providing a unit\-less value is deprecated and will warn; it will be an error in the future. -The default is 60 seconds. Set to 0 to immediately force\-kill the command. +The default is 10 seconds. Set to 0 to immediately force\-kill the command. This has no practical effect on Windows as the command is always forcefully terminated; see \*(Aq\-\-stop\-signal\*(Aq for why. .TP @@ -116,7 +116,7 @@ When an event is received, Watchexec will wait for up to this amount of time bef An alternative use is to set a high value (like "30min" or longer), to save power or bandwidth on intensive tasks, like an ad\-hoc backup script. In those use cases, note that every accumulated event will build up in memory. -Takes a unit\-less value in milliseconds, or a time span value such as "5sec 20ms". +Takes a unit\-less value in milliseconds, or a time span value such as "5sec 20ms". Providing a unit\-less value is deprecated and will warn; it will be an error in the future. The default is 50 milliseconds. Setting to 0 is highly discouraged. .TP @@ -152,9 +152,6 @@ Supported project ignore files: VCS ignore files (Git, Mercurial, Bazaar, Darcs, Fossil) are only used if the corresponding VCS is discovered to be in use for the project/origin. For example, a .bzrignore in a Git repository will be discarded. - -Note that this was previously called \*(Aq\-\-no\-ignore\*(Aq, but that\*(Aqs now deprecated and its use is -discouraged, as it may be repurposed in the future. .TP \fB\-\-no\-global\-ignore\fR Don\*(Aqt load global ignores @@ -202,14 +199,14 @@ Sleep before running the command This option will cause Watchexec to sleep for the specified amount of time before running the command, after an event is detected. This is like using "sleep 5 && command" in a shell, but portable and slightly more efficient. -Takes a unit\-less value in seconds, or a time span value such as "2min 5s". +Takes a unit\-less value in seconds, or a time span value such as "2min 5s". Providing a unit\-less value is deprecated and will warn; it will be an error in the future. .TP \fB\-\-poll\fR=\fIINTERVAL\fR Poll for filesystem changes By default, and where available, Watchexec uses the operating system\*(Aqs native file system watching capabilities. This option disables that and instead uses a polling mechanism, which is less efficient but can work around issues with some file systems (like network shares) or edge cases. -Optionally takes a unit\-less value in milliseconds, or a time span value such as "2s 500ms", to use as the polling interval. If not specified, the default is 30 seconds. +Optionally takes a unit\-less value in milliseconds, or a time span value such as "2s 500ms", to use as the polling interval. If not specified, the default is 30 seconds. Providing a unit\-less value is deprecated and will warn; it will be an error in the future. Aliased as \*(Aq\-\-force\-poll\*(Aq. .TP @@ -251,20 +248,13 @@ Use with a unix shell and options: $ watchexec \-\-shell=\*(Aqzsh \-x \-o shwordsplit\*(Aq \-\- scr .TP \fB\-n\fR -Don\*(Aqt use a shell - -This is a shorthand for \*(Aq\-\-shell=none\*(Aq. -.TP -\fB\-\-no\-environment\fR -Shorthand for \*(Aq\-\-emit\-events=none\*(Aq - -This is the old way to disable event emission into the environment. See \*(Aq\-\-emit\-events\*(Aq for more. +Shorthand for \*(Aq\-\-shell=none\*(Aq .TP \fB\-\-emit\-events\-to\fR=\fIMODE\fR Configure event emission -Watchexec emits event information when running a command, which can be used by the command -to target specific changed files. +Watchexec can emit event information when running a command, which can be used by the child +process to target specific changed files. One thing to take care with is assuming inherent behaviour where there is only chance. Notably, it could appear as if the `RENAMED` variable contains both the original and the new @@ -275,32 +265,14 @@ reliably and portably know which changed path is the old or new, "half" renames whether it was the old or new isn\*(Aqt known), rename events might split across two debouncing boundaries, and so on. -This option controls where that information is emitted. It defaults to \*(Aqenvironment\*(Aq, which -sets environment variables with the paths of the affected files, for filesystem events: +This option controls where that information is emitted. It defaults to \*(Aqnone\*(Aq, which doesn\*(Aqt +emit event information at all. The other options are \*(Aqenvironment\*(Aq (deprecated), \*(Aqstdio\*(Aq, +\*(Aqfile\*(Aq, \*(Aqjson\-stdio\*(Aq, and \*(Aqjson\-file\*(Aq. -$WATCHEXEC_COMMON_PATH is set to the longest common path of all of the below variables, -and so should be prepended to each path to obtain the full/real path. Then: - - \- $WATCHEXEC_CREATED_PATH is set when files/folders were created - \- $WATCHEXEC_REMOVED_PATH is set when files/folders were removed - \- $WATCHEXEC_RENAMED_PATH is set when files/folders were renamed - \- $WATCHEXEC_WRITTEN_PATH is set when files/folders were modified - \- $WATCHEXEC_META_CHANGED_PATH is set when files/folders\*(Aq metadata were modified - \- $WATCHEXEC_OTHERWISE_CHANGED_PATH is set for every other kind of pathed event - -Multiple paths are separated by the system path separator, \*(Aq;\*(Aq on Windows and \*(Aq:\*(Aq on unix. -Within each variable, paths are deduplicated and sorted in binary order (i.e. neither -Unicode nor locale aware). - -This is the legacy mode and will be deprecated and removed in the future. The environment of -a process is a very restricted space, while also limited in what it can usefully represent. -Large numbers of files will either cause the environment to be truncated, or may error or -crash the process entirely. - -Two new modes are available: \*(Aqstdio\*(Aq writes absolute paths to the stdin of the command, -one per line, each prefixed with `create:`, `remove:`, `rename:`, `modify:`, or `other:`, -then closes the handle; \*(Aqfile\*(Aq writes the same thing to a temporary file, and its path is -given with the $WATCHEXEC_EVENTS_FILE environment variable. +The \*(Aqstdio\*(Aq and \*(Aqfile\*(Aq modes are text\-based: \*(Aqstdio\*(Aq writes absolute paths to the stdin of +the command, one per line, each prefixed with `create:`, `remove:`, `rename:`, `modify:`, +or `other:`, then closes the handle; \*(Aqfile\*(Aq writes the same thing to a temporary file, and +its path is given with the $WATCHEXEC_EVENTS_FILE environment variable. There are also two JSON modes, which are based on JSON objects and can represent the full set of events Watchexec handles. Here\*(Aqs an example of a folder being created on Linux: @@ -357,7 +329,28 @@ line, then close stdin. The \*(Aqjson\-file\*(Aq mode will create a temporary fi events to it, and provide the path to the file with the $WATCHEXEC_EVENTS_FILE environment variable. -Finally, the special \*(Aqnone\*(Aq mode will disable event emission entirely. +Finally, the \*(Aqenvironment\*(Aq mode was the default until 2.0. It sets environment variables +with the paths of the affected files, for filesystem events: + +$WATCHEXEC_COMMON_PATH is set to the longest common path of all of the below variables, +and so should be prepended to each path to obtain the full/real path. Then: + + \- $WATCHEXEC_CREATED_PATH is set when files/folders were created + \- $WATCHEXEC_REMOVED_PATH is set when files/folders were removed + \- $WATCHEXEC_RENAMED_PATH is set when files/folders were renamed + \- $WATCHEXEC_WRITTEN_PATH is set when files/folders were modified + \- $WATCHEXEC_META_CHANGED_PATH is set when files/folders\*(Aq metadata were modified + \- $WATCHEXEC_OTHERWISE_CHANGED_PATH is set for every other kind of pathed event + +Multiple paths are separated by the system path separator, \*(Aq;\*(Aq on Windows and \*(Aq:\*(Aq on unix. +Within each variable, paths are deduplicated and sorted in binary order (i.e. neither +Unicode nor locale aware). + +This is the legacy mode, is deprecated, and will be removed in the future. The environment +is a very restricted space, while also limited in what it can usefully represent. Large +numbers of files will either cause the environment to be truncated, or may error or crash +the process entirely. The $WATCHEXEC_COMMON_PATH is also unintuitive, as demonstrated by the +multiple confused queries that have landed in my inbox over the years. .TP \fB\-\-only\-emit\-events\fR Only emit events to stdout, run no commands. diff --git a/doc/watchexec.1.md b/doc/watchexec.1.md index 3e14349..71d448f 100644 --- a/doc/watchexec.1.md +++ b/doc/watchexec.1.md @@ -12,18 +12,17 @@ watchexec - Execute commands when watched files change \[**\--no-global-ignore**\] \[**\--no-default-ignore**\] \[**\--no-discover-ignore**\] \[**\--ignore-nothing**\] \[**-p**\|**\--postpone**\] \[**\--delay-run**\] \[**\--poll**\] -\[**\--shell**\] \[**-n **\] \[**\--no-environment**\] -\[**\--emit-events-to**\] \[**\--only-emit-events**\] -\[**-E**\|**\--env**\] \[**\--no-process-group**\] -\[**-N**\|**\--notify**\] \[**\--color**\] \[**\--timings**\] -\[**-q**\|**\--quiet**\] \[**\--bell**\] \[**\--project-origin**\] -\[**\--workdir**\] \[**-e**\|**\--exts**\] \[**-f**\|**\--filter**\] -\[**\--filter-file**\] \[**-j**\|**\--filter-prog**\] -\[**-i**\|**\--ignore**\] \[**\--ignore-file**\] \[**\--fs-events**\] -\[**\--no-meta**\] \[**\--print-events**\] -\[**-v**\|**\--verbose**\]\... \[**\--log-file**\] \[**\--manual**\] -\[**\--completions**\] \[**-h**\|**\--help**\] -\[**-V**\|**\--version**\] \[*COMMAND*\] +\[**\--shell**\] \[**-n **\] \[**\--emit-events-to**\] +\[**\--only-emit-events**\] \[**-E**\|**\--env**\] +\[**\--no-process-group**\] \[**-N**\|**\--notify**\] \[**\--color**\] +\[**\--timings**\] \[**-q**\|**\--quiet**\] \[**\--bell**\] +\[**\--project-origin**\] \[**\--workdir**\] \[**-e**\|**\--exts**\] +\[**-f**\|**\--filter**\] \[**\--filter-file**\] +\[**-j**\|**\--filter-prog**\] \[**-i**\|**\--ignore**\] +\[**\--ignore-file**\] \[**\--fs-events**\] \[**\--no-meta**\] +\[**\--print-events**\] \[**-v**\|**\--verbose**\]\... +\[**\--log-file**\] \[**\--manual**\] \[**\--completions**\] +\[**-h**\|**\--help**\] \[**-V**\|**\--version**\] \[*COMMAND*\] # DESCRIPTION @@ -155,9 +154,10 @@ graceful stop signal is sent, Watchexec will wait for the command to exit. If it hasnt exited after this time, it is forcefully terminated. Takes a unit-less value in seconds, or a time span value such as \"5min -20s\". +20s\". Providing a unit-less value is deprecated and will warn; it will +be an error in the future. -The default is 60 seconds. Set to 0 to immediately force-kill the +The default is 10 seconds. Set to 0 to immediately force-kill the command. This has no practical effect on Windows as the command is always @@ -204,7 +204,8 @@ script. In those use cases, note that every accumulated event will build up in memory. Takes a unit-less value in milliseconds, or a time span value such as -\"5sec 20ms\". +\"5sec 20ms\". Providing a unit-less value is deprecated and will warn; +it will be an error in the future. The default is 50 milliseconds. Setting to 0 is highly discouraged. @@ -253,10 +254,6 @@ if the corresponding VCS is discovered to be in use for the project/origin. For example, a .bzrignore in a Git repository will be discarded. -Note that this was previously called \--no-ignore, but thats now -deprecated and its use is discouraged, as it may be repurposed in the -future. - **\--no-global-ignore** : Dont load global ignores @@ -326,7 +323,8 @@ like using \"sleep 5 && command\" in a shell, but portable and slightly more efficient. Takes a unit-less value in seconds, or a time span value such as \"2min -5s\". +5s\". Providing a unit-less value is deprecated and will warn; it will +be an error in the future. **\--poll**=*INTERVAL* @@ -340,7 +338,8 @@ cases. Optionally takes a unit-less value in milliseconds, or a time span value such as \"2s 500ms\", to use as the polling interval. If not specified, -the default is 30 seconds. +the default is 30 seconds. Providing a unit-less value is deprecated and +will warn; it will be an error in the future. Aliased as \--force-poll. @@ -396,23 +395,14 @@ Use with a unix shell and options: **-n** -: Dont use a shell - -This is a shorthand for \--shell=none. - -**\--no-environment** - -: Shorthand for \--emit-events=none - -This is the old way to disable event emission into the environment. See -\--emit-events for more. +: Shorthand for \--shell=none **\--emit-events-to**=*MODE* : Configure event emission -Watchexec emits event information when running a command, which can be -used by the command to target specific changed files. +Watchexec can emit event information when running a command, which can +be used by the child process to target specific changed files. One thing to take care with is assuming inherent behaviour where there is only chance. Notably, it could appear as if the \`RENAMED\` variable @@ -426,36 +416,14 @@ the old or new isnt known), rename events might split across two debouncing boundaries, and so on. This option controls where that information is emitted. It defaults to -environment, which sets environment variables with the paths of the -affected files, for filesystem events: +none, which doesnt emit event information at all. The other options are +environment (deprecated), stdio, file, json-stdio, and json-file. -\$WATCHEXEC_COMMON_PATH is set to the longest common path of all of the -below variables, and so should be prepended to each path to obtain the -full/real path. Then: - -\- \$WATCHEXEC_CREATED_PATH is set when files/folders were created - -\$WATCHEXEC_REMOVED_PATH is set when files/folders were removed - -\$WATCHEXEC_RENAMED_PATH is set when files/folders were renamed - -\$WATCHEXEC_WRITTEN_PATH is set when files/folders were modified - -\$WATCHEXEC_META_CHANGED_PATH is set when files/folders metadata were -modified - \$WATCHEXEC_OTHERWISE_CHANGED_PATH is set for every other -kind of pathed event - -Multiple paths are separated by the system path separator, ; on Windows -and : on unix. Within each variable, paths are deduplicated and sorted -in binary order (i.e. neither Unicode nor locale aware). - -This is the legacy mode and will be deprecated and removed in the -future. The environment of a process is a very restricted space, while -also limited in what it can usefully represent. Large numbers of files -will either cause the environment to be truncated, or may error or crash -the process entirely. - -Two new modes are available: stdio writes absolute paths to the stdin of -the command, one per line, each prefixed with \`create:\`, \`remove:\`, -\`rename:\`, \`modify:\`, or \`other:\`, then closes the handle; file -writes the same thing to a temporary file, and its path is given with -the \$WATCHEXEC_EVENTS_FILE environment variable. +The stdio and file modes are text-based: stdio writes absolute paths to +the stdin of the command, one per line, each prefixed with \`create:\`, +\`remove:\`, \`rename:\`, \`modify:\`, or \`other:\`, then closes the +handle; file writes the same thing to a temporary file, and its path is +given with the \$WATCHEXEC_EVENTS_FILE environment variable. There are also two JSON modes, which are based on JSON objects and can represent the full set of events Watchexec handles. Heres an example of @@ -490,7 +458,33 @@ command, one per line, then close stdin. The json-file mode will create a temporary file, write the events to it, and provide the path to the file with the \$WATCHEXEC_EVENTS_FILE environment variable. -Finally, the special none mode will disable event emission entirely. +Finally, the environment mode was the default until 2.0. It sets +environment variables with the paths of the affected files, for +filesystem events: + +\$WATCHEXEC_COMMON_PATH is set to the longest common path of all of the +below variables, and so should be prepended to each path to obtain the +full/real path. Then: + +\- \$WATCHEXEC_CREATED_PATH is set when files/folders were created - +\$WATCHEXEC_REMOVED_PATH is set when files/folders were removed - +\$WATCHEXEC_RENAMED_PATH is set when files/folders were renamed - +\$WATCHEXEC_WRITTEN_PATH is set when files/folders were modified - +\$WATCHEXEC_META_CHANGED_PATH is set when files/folders metadata were +modified - \$WATCHEXEC_OTHERWISE_CHANGED_PATH is set for every other +kind of pathed event + +Multiple paths are separated by the system path separator, ; on Windows +and : on unix. Within each variable, paths are deduplicated and sorted +in binary order (i.e. neither Unicode nor locale aware). + +This is the legacy mode, is deprecated, and will be removed in the +future. The environment is a very restricted space, while also limited +in what it can usefully represent. Large numbers of files will either +cause the environment to be truncated, or may error or crash the process +entirely. The \$WATCHEXEC_COMMON_PATH is also unintuitive, as +demonstrated by the multiple confused queries that have landed in my +inbox over the years. **\--only-emit-events**