Commit 9e1287e
feat: filter packages with
## Summary
Add pnpm-compatible `--filter` flag to `vp run` for selecting which
packages to run tasks in.
Supports:
- **Package name**: exact (`--filter @test/app`) and glob (`--filter
@test/*`)
- **Directory**: exact (`--filter ./packages/app`), glob (`--filter
./packages/*`), relative (`.`, `..`)
- **Braced paths**: `{./path}` for traversal on paths, `name{./dir}` for
name + directory intersection
- **Dependency traversal**: `foo...` (dependencies), `...foo`
(dependents), `^` to exclude self, `...foo...` (both)
- **Exclusion**: `!foo` to exclude packages from the result
- **Multiple filters**: `--filter a --filter b` (union); `--filter "a
b"` (whitespace split, pnpm compat)
- **`-w` / `--workspace-root`**: select workspace root; additive with
`--filter`, redundant with `-r`, supports `-t` for root + transitive
deps
- **Nested expansion**: `vp run --filter .... build` inside package
scripts is expanded in the plan
### Architecture: `PackageQueryArgs` → `PackageQuery` →
`FilterResolution`
Package selection lives in `vite_workspace`, not in the task runner. Any
command that needs to pick packages can reuse it.
**Step 1 — Parse CLI flags into a query.**
`PackageQueryArgs` is a clap struct with `-r`, `-t`, `-w`, and
`--filter`. Embed it via `#[clap(flatten)]`, then call
`into_package_query()`:
```rust
// in any command definition (e.g. `vp exec`, `vp run`)
#[derive(clap::Args)]
struct MyCommand {
#[clap(flatten)]
packages: PackageQueryArgs,
}
// at runtime — package_name comes from `pkg#task` syntax (e.g. "app" in `vp run app#build`).
// commands that don't use `pkg#task` (like `vp exec`) pass None.
let query: PackageQuery = args.packages.into_package_query(package_name, &cwd)?;
```
`into_package_query` validates flag combinations (e.g. `--filter` + `-r`
is an error), splits whitespace, parses each `--filter` token, and
returns an opaque `PackageQuery`.
**Step 2 — Resolve the query against the package graph.**
```rust
let resolution: FilterResolution = indexed_package_graph.resolve_query(&query);
// resolution.package_subgraph — the selected packages + edges between them
// resolution.unmatched_selectors — filter strings that matched nothing (for warnings)
```
`PackageQuery` is opaque — callers don't inspect its internals. They
just pass it to `resolve_query` and get back the selected subgraph.
Future commands like `vp exec` only need steps 1 and 2 — they get the
selected packages without depending on the task graph at all.
**Step 3 (task runner only) — Map packages to tasks.**
The task-graph layer maps the package subgraph to task nodes,
reconnecting across packages that lack the requested task. Only `vp run`
needs this step.
### `unmatched_selectors` tracks original filter strings
Each `--filter` token is stored as a `source: Option<Str>` inside the
parsed filter. Synthetic filters (implicit cwd, `-w`) get `source: None`
since the user didn't type them. When a filter matches nothing,
`resolve_query` collects the original string into `unmatched_selectors:
Vec<Str>` so the caller can show a warning like:
```
warn: --filter "typo-pkg" matched no packages
```
This works correctly even with whitespace splitting (`--filter "a b"` →
two filters, each with its own source string).
## Test plan
- [x] 48 unit tests in `package_filter` for `parse_filter`,
`into_package_query`, `resolve_directory_pattern`, and source tracking —
covering all selector types, traversal modes, flag combinations, path
normalization, and error cases
- [x] 40 plan snapshot tests across `filter-workspace` (35) and
`transitive-skip-intermediate` (5) fixtures
- [x] Existing plan and e2e snapshot tests still pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>--filter (#176)1 parent 1128edc commit 9e1287e
File tree
107 files changed
+4278
-900
lines changed- crates
- vite_glob/src
- vite_graph_ser/src
- vite_task_bin/tests/e2e_snapshots
- fixtures
- filter-unmatched
- packages
- app
- lib
- snapshots
- task-select/snapshots
- vite_task_graph
- src
- query
- vite_task_plan
- src
- tests/plan_snapshots
- fixtures
- comprehensive-task-graph/snapshots
- conflict-test/snapshots
- cycle-dependency/snapshots
- dependency-both-topo-and-explicit/snapshots
- duplicate-package-names
- packages
- pkg-a
- pkg-b
- snapshots
- empty-package-test/snapshots
- explicit-deps-workspace/snapshots
- filter-workspace
- packages
- app
- cli
- core
- lib
- utils
- snapshots
- recursive-topological-workspace/snapshots
- transitive-skip-intermediate
- packages
- bottom
- middle
- top
- snapshots
- vite_task
- docs
- src
- cli
- session
- vite_workspace
- src
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
107 files changed
+4278
-900
lines changedSome generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
| 94 | + | |
94 | 95 | | |
95 | 96 | | |
96 | 97 | | |
| |||
145 | 146 | | |
146 | 147 | | |
147 | 148 | | |
148 | | - | |
| 149 | + | |
149 | 150 | | |
150 | 151 | | |
151 | 152 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
21 | | - | |
| 20 | + | |
| 21 | + | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
| 24 | + | |
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| 28 | + | |
| 29 | + | |
28 | 30 | | |
29 | 31 | | |
30 | | - | |
| 32 | + | |
31 | 33 | | |
32 | 34 | | |
33 | 35 | | |
| |||
45 | 47 | | |
46 | 48 | | |
47 | 49 | | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
53 | | - | |
| 50 | + | |
54 | 51 | | |
55 | 52 | | |
56 | 53 | | |
57 | | - | |
| 54 | + | |
58 | 55 | | |
59 | | - | |
| 56 | + | |
60 | 57 | | |
61 | 58 | | |
62 | 59 | | |
63 | 60 | | |
64 | | - | |
| 61 | + | |
65 | 62 | | |
66 | | - | |
| 63 | + | |
67 | 64 | | |
68 | 65 | | |
69 | 66 | | |
| |||
101 | 98 | | |
102 | 99 | | |
103 | 100 | | |
104 | | - | |
| 101 | + | |
105 | 102 | | |
106 | 103 | | |
107 | 104 | | |
108 | 105 | | |
109 | | - | |
| 106 | + | |
110 | 107 | | |
111 | 108 | | |
112 | 109 | | |
113 | 110 | | |
114 | | - | |
115 | | - | |
116 | | - | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
117 | 114 | | |
118 | 115 | | |
119 | 116 | | |
| |||
123 | 120 | | |
124 | 121 | | |
125 | 122 | | |
126 | | - | |
| 123 | + | |
127 | 124 | | |
128 | 125 | | |
129 | 126 | | |
130 | 127 | | |
131 | | - | |
| 128 | + | |
132 | 129 | | |
133 | 130 | | |
134 | 131 | | |
| |||
0 commit comments