fix: watch cwds of dependencies#10054
Conversation
When I changed watch mode to also watch dependencies' sources, I didn't
take into account the fact that the `sources` will be used _as-is_ (i.e.
not resolved to anything).
This meant the following would happen:
- `build:a` has `["src/*.ts"]`
- `build:b` has `["lib/*.js"]` and depends on `build:a`
- We pass `["src/*.ts", "lib/*.js"]` to watchexec _in the directory of
`build:b`_
This made `lib/*.js` basically no-op, or worse, watch the wrong files.
This change resolves the paths to their owning directory so we end up
with `["wherever-builda-lives/src/*.ts",
"wherever-buildb-lives/lib/*.js"]`.
**Notable Changes:**
- Instead of passing relative globs to watchexec, we now pass resolved
ones (relative to the root)
- We now pass `--project-origin` to watchexec which comes with some perf
gains but also means globs are now relative to it
- We pass `--watch {cwd}` for the cwd of each dependency
- This new `resolve_source` function is basically turning a source glob
into a relative-to-the-root glob while retaining negations
There was a problem hiding this comment.
Code Review
This pull request introduces logic to calculate a "filter anchor" for watchexec by determining the common ancestor of task working directories, ensuring glob filters are correctly interpreted relative to a project origin. It adds utility functions for finding common path ancestors and resolving source patterns, including support for negations and escaped characters. Review feedback focused on optimizing the common_ancestor function by using AsRef to avoid unnecessary cloning and reducing memory allocations during path component comparisons.
Greptile SummaryThis PR fixes watch mode incorrectly applying dependency source globs relative to the wrong task's working directory. Sources are now resolved to absolute paths, re-expressed relative to a computed anchor (
Confidence Score: 4/5Safe to merge; the core bug fix is correct and the three concerns raised in prior review threads are addressed. Two non-blocking edge cases remain in the new path-resolution helpers. The path manipulation pipeline works correctly for the common cases and is well-covered by the new unit tests. The normalize_path function silently alters patterns that contain .. after glob wildcards, and the anchor is set to the full configured project root even when the actual common ancestor of all sources is narrower, expanding watchexec gitignore scanning scope. Neither issue causes incorrect file watching in typical configurations. src/cli/watch.rs — specifically the normalize_path function and the (Some(mut cfg), Some(common)) anchor-selection branch. Important Files Changed
Reviews (5): Last reviewed commit: "fix: handle windows escapes" | Re-trigger Greptile |
|
This mostly looks good, but I think there is one missed case before merge. When a source escapes the task cwd, the filter anchor is widened correctly, but the watched paths are still only the task cwds. For example: [tasks.build]
dir = "packages/foo"
sources = ["../../shared/src/*.ts"]This becomes roughly: The filter now points at Could we either watch the computed anchor/common ancestor, or add watch dirs for source paths that fall outside their task cwd? A regression test for This comment was generated by an AI coding assistant. |
When I changed watch mode to also watch dependencies' sources, I didn't
take into account the fact that the
sourceswill be used as-is (i.e.not resolved to anything).
This meant the following would happen:
build:ahas["src/*.ts"]build:bhas["lib/*.js"]and depends onbuild:a["src/*.ts", "lib/*.js"]to watchexec in the directory ofbuild:bThis made
lib/*.jsbasically no-op, or worse, watch the wrong files.This change resolves the paths to their owning directory so we end up
with
["wherever-builda-lives/src/*.ts", "wherever-buildb-lives/lib/*.js"].Notable Changes:
ones (relative to the root)
--project-originto watchexec which comes with some perfgains but also means globs are now relative to it
--watch {cwd}for the cwd of each dependencyresolve_sourcefunction is basically turning a source globinto a relative-to-the-root glob while retaining negations
common_ancestorfunction tries to find the common ancestor of two directoriescc @jdx i don't usually delve into rust so i'd love some help here if you can.
especially if there's a better way to find the common ancestor, or if you think we should deal with that differently.
basically, watchexec doesn't seem to support absolute paths, so we have to set the
project-originto something above all globs. which is why this new function tries to find a common root (if not the configured one)