Merged
Conversation
--filter
e3ac798 to
f013ff7
Compare
fengmk2
approved these changes
Feb 28, 2026
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ensures snapshots fail when the info header (cwd/args) doesn't match, preventing silently stale metadata after rebases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…stem The CLI only accepts a single task specifier, but the underlying TaskQueryKind still used FxHashSet for multiple specifiers. Simplify to singular fields and delete the unused CLITaskQuery module. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add pnpm-style --filter/-F flag for fine-grained package selection. Topological ordering is now computed at query time from the package subgraph rather than pre-computed in the task graph, which correctly handles per-query skip-intermediate reconnection. - Add package_filter module (types, parsing, unit tests) to vite_workspace - Move IndexedPackageGraph to vite_workspace with resolve_query/resolve_filters - Replace TaskQueryKind with two-stage model: PackageQuery → package subgraph → task mapping - Simplify TaskDependencyType to explicit-only (topological edges removed from task graph) - Add --filter/-F to CLI with conflict validation against -r/-t - Add filter-workspace and transitive-skip-intermediate test fixtures - Add task-query.md documenting the data flow and design decisions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SerializeByKey now serializes only neighbor keys, ignoring edge weights. This removes the redundant `null` that appeared for every TaskDependencyType edge in task graph snapshots. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Test `-t` combined with `package#task` syntax for both cases: - package has the task (selects it + transitive deps) - package lacks the task (skip-intermediate, only deps run) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement pnpm v7+ glob-dir semantics: plain directory paths are exact-match only, `*`/`**` opt in to descendant matching. Adds DirectoryPattern enum (Exact/Glob) and splits glob paths into a resolved base + wax::Glob pattern for matching. Also adds pnpm GitHub permalink references to all existing pnpm comments and a test for `..` normalization in glob base paths. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`--filter "a b"` is now equivalent to `--filter a --filter b`, matching pnpm's behavior of treating space-separated tokens within a single --filter value as independent selectors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…patterns Upgrade wax 0.6.0 → 0.7.0 and adapt to breaking changes: Pattern → Program trait, WalkError moved to wax::walk, walk() takes Into<PathBuf>, Entry trait methods require explicit import. Replace manual base/glob splitting in resolve_directory_pattern with wax::Glob::partition(), and use the Option<Glob> return to decide between Exact and Glob variants instead of a manual metacharacter check. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add plan snapshot tests for: - directory filter with dependency expansion (./packages/app...) - dot with deps from package cwd (.... from packages/app) - dotdot with deps from subdir (..... from packages/app/src) - nested vp run --filter in package script (deploy expands inline) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use `path_clean::clean()` (Plan 9 cleanname / Go path.Clean port) for lexical `.`/`..` resolution instead of the manual `normalize_absolute_path` function. Add direct unit tests for `resolve_directory_pattern`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… match Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove unused `vec1` and `clap` deps from vite_task_graph (cargo shear) - Remove unfulfilled `#[expect(clippy::disallowed_types)]` on resolve_filter_path - Replace wildcard match arms with explicit `DirectoryPattern::Exact` variant - Make test `abs()` helper cross-platform by prepending `C:` on Windows Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move package-query CLI fields (recursive, transitive, filter) and their validation logic from vite_task::cli::RunFlags into a new PackageQueryArgs struct in vite_workspace::package_filter. This makes the package-query concept self-contained next to PackageQuery and PackageFilter. Also make PackageQuery opaque (pub struct wrapping pub(crate) enum) and make PackageFilter, PackageSelector, and related sub-types pub(crate) so they are no longer part of the public API. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…, and exclusion edge cases Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lters Replace manual `contains(['*', '?', '['])` check with wax's own partition method, consistent with how DirectoryPattern already works. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
pnpm silently discards `...` traversal modifiers on unbraced path
selectors like `./packages/app...` due to syntactic ambiguity between
`..` (parent dir) and `...` (traversal). Only braced paths like
`{./packages/app}...` preserve traversal (pnpm issue #1651, PR #2254).
`parse_core_selector` now returns a `supports_traversal` flag that is
`false` for unbraced `.`-prefix paths, causing `parse_filter` to
discard any stripped `...`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a new PackageSelector::WorkspaceRoot variant that targets the package with empty relative path (workspace root). The flag follows pnpm's conflict rules: - -w alone: selects only the workspace root - -w --filter: additive (workspace root unioned with filter matches) - -w -r: redundant (all packages already includes root) - -w -t: workspace root with transitive dependencies - -w with package name: error (conflicting target) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- mixed traversal filters: change @test/app... to @test/lib... so result
({lib, core, cli}) is distinct from recursive and shows cross-boundary
cli→core edge
- workspace root with recursive: change build→check so root appears in
output, proving -r already covers it
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`unmatched_selectors` was `Vec<usize>` (indices into the internal filter list), but those indices don't map back to CLI args after whitespace splitting and synthetic filter injection. Change to `Vec<Str>` by storing the original `--filter` token as `source: Option<Str>` in each `PackageFilter`. Synthetic filters (implicit cwd, `-w`) get `None` so they are never reported as unmatched. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Print "No packages matched the filter: <filter>" to stderr for each inclusion filter that resolves to zero packages. Exclusion filters and synthetic filters (implicit cwd, -w) are not reported. Add e2e snapshot tests covering: partial match, multiple unmatched, whitespace-split tokens, exclusion filters, glob filters, and directory filters. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace wildcard match arms in test code with explicit `PackageQueryKind::All` to satisfy `match_wildcard_for_single_variants`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove `pub` from all fields. External crates interact only through `#[clap(flatten)]` (parsing) and `into_package_query()` (conversion). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The flags are shared by `vp run` and future commands like `vp exec`, so the help text should not mention "tasks". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fa3c8ac to
d5e4d4f
Compare
d5e4d4f to
42c822f
Compare
…ty filters Replace nested if-chains with a single match on (recursive, transitive, workspace_root, Option<Vec1<Str>>) to ensure no flag combination is missed. Rename `filter` field to `filters`, reject empty/whitespace-only --filter values with EmptyFilter error, and add tests for the new validation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add package_name as the 5th element of the match tuple, replacing inner `if let Some(package_name)` checks with dedicated match arms. Each arm is commented with its CLI args. The last combined arm is split into three: `<pkg>#<task>`, `--transitive`, and bare invocation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Error arms now only match the conflicting fields (wildcards for the rest); success arms explicitly match every field with no wildcards. Adds section-header comments separating the two groups. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When `vp run pkg#task` resolves to multiple packages sharing the same name, emit an `AmbiguousPackageName` error instead of silently running all of them. `--filter` with the same name continues to match all packages. Adds a `unique: bool` flag to `PackageNamePattern::Exact` — true for `pkg#task` specifiers, false for `--filter`. The resolution chain (`resolve_query` → `resolve_filters` → `match_by_name_pattern`) is now fallible, propagating through `query_tasks` to `plan_query_request`. Also renames the CLI flag from `--filters` to `--filter` (field name stays `filters`), and adds plan snapshot tests for the duplicate package name scenario. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use `Path::display()` instead of `Debug` formatting for package paths in the `AmbiguousPackageName` error message, avoiding platform-specific quoting differences that break Windows CI snapshots. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Add pnpm-compatible
--filterflag tovp runfor selecting which packages to run tasks in.Supports:
--filter @test/app) and glob (--filter @test/*)--filter ./packages/app), glob (--filter ./packages/*), relative (.,..){./path}for traversal on paths,name{./dir}for name + directory intersectionfoo...(dependencies),...foo(dependents),^to exclude self,...foo...(both)!footo exclude packages from the result--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-tfor root + transitive depsvp run --filter .... buildinside package scripts is expanded in the planArchitecture:
PackageQueryArgs→PackageQuery→FilterResolutionPackage 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.
PackageQueryArgsis a clap struct with-r,-t,-w, and--filter. Embed it via#[clap(flatten)], then callinto_package_query():into_package_queryvalidates flag combinations (e.g.--filter+-ris an error), splits whitespace, parses each--filtertoken, and returns an opaquePackageQuery.Step 2 — Resolve the query against the package graph.
PackageQueryis opaque — callers don't inspect its internals. They just pass it toresolve_queryand get back the selected subgraph.Future commands like
vp execonly 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 runneeds this step.unmatched_selectorstracks original filter stringsEach
--filtertoken is stored as asource: Option<Str>inside the parsed filter. Synthetic filters (implicit cwd,-w) getsource: Nonesince the user didn't type them. When a filter matches nothing,resolve_querycollects the original string intounmatched_selectors: Vec<Str>so the caller can show a warning like:This works correctly even with whitespace splitting (
--filter "a b"→ two filters, each with its own source string).Test plan
package_filterforparse_filter,into_package_query,resolve_directory_pattern, and source tracking — covering all selector types, traversal modes, flag combinations, path normalization, and error casesfilter-workspace(35) andtransitive-skip-intermediate(5) fixtures🤖 Generated with Claude Code