4.2 KiB
Contribution guidebook
This is a fairly free-form project, with low contribution traffic.
Maintainers:
- Félix Saparelli (@passcod) (active)
- Matt Green (@mattgreen) (original author, mostly checked out)
There are a few anti goals:
-
Calling watchexec is to be a simple exercise that remains intuitive. As a specific point, it should not involve any piping or require xargs.
-
Watchexec will not be tied to any particular ecosystem or language. Projects that themselves use watchexec (the library) can be focused on a particular domain (for example Cargo Watch for Rust), but watchexec itself will remain generic, usable for any purpose.
Debugging
To enable verbose logging in tests, run with:
$ env RUST_LOG=watchexec=trace,info RUST_TEST_THREADS=1 RUST_NOCAPTURE=1 cargo test --test testfile -- testname
To use Tokio Console:
- Add
--cfg tokio_unstable
to yourRUSTFLAGS
. - Run the CLI with the
dev-console
feature.
PR etiquette
- Maintainers are busy or may not have the bandwidth, be patient.
- Do not change the version number in the PR.
- Do not change Cargo.toml or other project metadata, unless specifically asked for, or if that's the point of the PR (like adding a crates.io category).
Apart from that, welcome and thank you for your time!
Releasing
cargo release -p crate-name --execute patch # or minor, major
When a CLI release is done, the release notes should be edited with the changelog.
Release order
Use this command to see the tree of workspace dependencies:
$ cargo tree -p watchexec-cli | rg -F '(/' --color=never | sed 's/ v[0-9].*//'
Overview
The architecture of watchexec is roughly:
- sources gather events
- events are debounced and filtered
- event(s) make it through the debounce/filters and trigger an "action"
on_action
handler is called, returning anOutcome
- outcome is processed into managing the command that watchexec is running
- outcome can also be to exit
- when a command is started, the
on_pre_spawn
andon_post_spawn
handlers are called - commands are also a source of events, so e.g. "command has finished" is handled by
on_action
And this is the startup sequence:
- init config sets basic immutable facts about the runtime
- runtime starts:
- source workers start, and are passed their runtime config
- action worker starts, and is passed its runtime config
- (unless
--postpone
is given) a synthetic event is injected to kickstart things
Guides
These are generic guides for implementing specific bits of functionality.
Adding an event source
-
add a worker for "sourcing" events. Looking at the signal source worker is probably easiest to get started here.
-
because we may not always want to enable this event source, and just to be flexible, add runtime config for the source.
-
for convenience, probably add a method on the runtime config which configures the most common usecase.
-
because watchexec is reconfigurable, in the worker you'll need to react to config changes. Look at how the fs worker does it for reference.
-
you may need to add to the event tag enum.
-
if you do, you should add support to the "tagged filterer", but this can be done in follow-up work.
Process a new event in the CLI
-
add an option to the args if necessary
-
add to the runtime config when the option is present
-
process relevant events in the action handler
vim: tw=100