From be938767b5e64be3281500462dbcb2e3bfba3454 Mon Sep 17 00:00:00 2001 From: JongKyung Lee Date: Tue, 15 Sep 2026 15:45:29 +0900 Subject: [PATCH 1/2] fix(pm): respect filters for recursive removal on Yarn Berry --- .../snapshots.toml | 4 +- .../command_remove_yarn4_with_workspace.md | 89 ++++++++++++++++++- .../src/resolution/commands/remove.rs | 23 +++-- 3 files changed, 107 insertions(+), 9 deletions(-) diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots.toml index f26b4b0223..ec6931f5d3 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots.toml @@ -8,11 +8,13 @@ steps = [ { argv = ["vp", "add", "test-vite-plus-install", "--filter=*", "--filter=@vite-plus-test/utils"], snapshot = false }, { argv = ["vp", "add", "test-vite-plus-package-optional", "-O", "--filter=*", "--filter=@vite-plus-test/utils"], snapshot = false, continue-on-failure = true }, { argv = ["vpt", "print-file", "package.json", "packages/app/package.json", "packages/admin/package.json", "packages/utils/package.json"], comment = "prepare packages", continue-on-failure = true }, + { argv = ["vp", "remove", "testnpm2", "-r", "--filter=app", "--filter=@vite-plus-test/utils"], comment = "recursive remove affects only app and utils" }, + { argv = ["vpt", "print-file", "package.json", "packages/app/package.json", "packages/admin/package.json", "packages/utils/package.json"], comment = "root and admin keep testnpm2" }, { argv = ["vp", "remove", "testnpm2", "-r"], comment = "should remove package from all workspaces and root" }, { argv = ["vpt", "print-file", "package.json", "packages/app/package.json", "packages/admin/package.json", "packages/utils/package.json"], continue-on-failure = true }, { argv = ["vp", "remove", "-O", "test-vite-plus-package-optional", "-r"], comment = "should remove optional package from all workspaces" }, { argv = ["vpt", "print-file", "package.json", "packages/app/package.json", "packages/admin/package.json", "packages/utils/package.json"], continue-on-failure = true }, - { argv = ["vp", "remove", "test-vite-plus-install", "--filter=app"], comment = "should remove package by filter=app" }, + { argv = ["vp", "remove", "test-vite-plus-install", "-r", "--filter=app"], comment = "recursive remove affects only app" }, { argv = ["vpt", "print-file", "package.json", "packages/app/package.json", "packages/admin/package.json", "packages/utils/package.json"], continue-on-failure = true }, { argv = ["vp", "add", "test-vite-plus-install", "--filter=app"], comment = "should remove package by filter=*" }, ["vp", "remove", "test-vite-plus-install", "--filter=*"], diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots/command_remove_yarn4_with_workspace.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots/command_remove_yarn4_with_workspace.md index af098d5d41..a3196cad10 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots/command_remove_yarn4_with_workspace.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots/command_remove_yarn4_with_workspace.md @@ -75,6 +75,91 @@ prepare packages } ``` +## `vp remove testnpm2 -r --filter=app --filter=@vite-plus-test/utils` + +recursive remove affects only app and utils + +``` +[app]: Process started +[app]: ➤ YN0000: · Yarn +[app]: ➤ YN0000: ┌ Resolution step +[app]: ➤ YN0000: └ Completed +[app]: ➤ YN0000: ┌ Fetch step +[app]: ➤ YN0000: └ Completed +[app]: ➤ YN0000: ┌ Link step +[app]: ➤ YN0000: └ Completed +[app]: ➤ YN0000: · Done in +[app]: Process exited (exit code 0), completed in + +[@vite-plus-test/utils]: Process started +[@vite-plus-test/utils]: ➤ YN0000: · Yarn +[@vite-plus-test/utils]: ➤ YN0000: ┌ Resolution step +[@vite-plus-test/utils]: ➤ YN0000: └ Completed +[@vite-plus-test/utils]: ➤ YN0000: ┌ Fetch step +[@vite-plus-test/utils]: ➤ YN0000: └ Completed +[@vite-plus-test/utils]: ➤ YN0000: ┌ Link step +[@vite-plus-test/utils]: ➤ YN0000: └ Completed +[@vite-plus-test/utils]: ➤ YN0000: · Done in +[@vite-plus-test/utils]: Process exited (exit code 0), completed in + +Done in +``` + +## `vpt print-file package.json packages/app/package.json packages/admin/package.json packages/utils/package.json` + +root and admin keep testnpm2 + +``` +{ + "name": "command-remove-yarn4-with-workspace", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ], + "packageManager": "yarn@4.10.3", + "devDependencies": { + "testnpm2": "^1.0.1" + }, + "dependencies": { + "test-vite-plus-install": "^1.0.0" + }, + "optionalDependencies": { + "test-vite-plus-package-optional": "^1.0.0" + } +} +{ + "name": "app", + "dependencies": { + "test-vite-plus-install": "^1.0.0" + }, + "optionalDependencies": { + "test-vite-plus-package-optional": "^1.0.0" + } +} +{ + "name": "admin", + "devDependencies": { + "testnpm2": "^1.0.1" + }, + "dependencies": { + "test-vite-plus-install": "^1.0.0" + }, + "optionalDependencies": { + "test-vite-plus-package-optional": "^1.0.0" + } +} +{ + "name": "@vite-plus-test/utils", + "version": "1.0.0", + "dependencies": { + "test-vite-plus-install": "^1.0.0" + }, + "optionalDependencies": { + "test-vite-plus-package-optional": "^1.0.0" + } +} +``` + ## `vp remove testnpm2 -r` should remove package from all workspaces and root @@ -189,9 +274,9 @@ should remove optional package from all workspaces } ``` -## `vp remove test-vite-plus-install --filter=app` +## `vp remove test-vite-plus-install -r --filter=app` -should remove package by filter=app +recursive remove affects only app ``` [app]: Process started diff --git a/crates/vp_pm_cli/src/resolution/commands/remove.rs b/crates/vp_pm_cli/src/resolution/commands/remove.rs index 0888888a68..a48745254b 100644 --- a/crates/vp_pm_cli/src/resolution/commands/remove.rs +++ b/crates/vp_pm_cli/src/resolution/commands/remove.rs @@ -111,13 +111,11 @@ impl Resolve for Yarn { ); } - if !args.recursive { - cmd.arg("workspaces").arg("foreach").arg("--all"); - cmd.repeated("--include", args.filter.iter()); - } + cmd.arg("workspaces").arg("foreach").arg("--all"); + cmd.repeated("--include", args.filter.iter()); } cmd.arg("remove") - .arg_if("--all", args.recursive) + .arg_if("--all", args.recursive && args.filter.is_empty()) .extend(args.pass_through_args.iter()) .extend(args.packages.iter()); cmd.into() @@ -505,7 +503,20 @@ mod tests { let command = expect_run(resolution.outcome); assert_eq!(command.program, "yarn"); - assert_eq!(command.args, vec!["remove", "--all", "lodash"]); + assert_eq!( + command.args, + vec![ + "workspaces", + "foreach", + "--all", + "--include", + "app", + "--include", + "web", + "remove", + "lodash" + ] + ); } #[test] From 4750b0c55a8ea880b230ec761c4cab46a6b24b78 Mon Sep 17 00:00:00 2001 From: JongKyung Lee Date: Tue, 15 Sep 2026 16:28:01 +0900 Subject: [PATCH 2/2] fix(pm): warn on unsupported workspace-root in Yarn remove --- .../snapshots.toml | 2 +- .../command_remove_yarn4_with_workspace.md | 3 ++- .../src/resolution/commands/remove.rs | 21 ++++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots.toml b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots.toml index ec6931f5d3..7a199434d0 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots.toml +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots.toml @@ -8,7 +8,7 @@ steps = [ { argv = ["vp", "add", "test-vite-plus-install", "--filter=*", "--filter=@vite-plus-test/utils"], snapshot = false }, { argv = ["vp", "add", "test-vite-plus-package-optional", "-O", "--filter=*", "--filter=@vite-plus-test/utils"], snapshot = false, continue-on-failure = true }, { argv = ["vpt", "print-file", "package.json", "packages/app/package.json", "packages/admin/package.json", "packages/utils/package.json"], comment = "prepare packages", continue-on-failure = true }, - { argv = ["vp", "remove", "testnpm2", "-r", "--filter=app", "--filter=@vite-plus-test/utils"], comment = "recursive remove affects only app and utils" }, + { argv = ["vp", "remove", "testnpm2", "-r", "--workspace-root", "--filter=app", "--filter=@vite-plus-test/utils"], comment = "recursive remove affects only app and utils" }, { argv = ["vpt", "print-file", "package.json", "packages/app/package.json", "packages/admin/package.json", "packages/utils/package.json"], comment = "root and admin keep testnpm2" }, { argv = ["vp", "remove", "testnpm2", "-r"], comment = "should remove package from all workspaces and root" }, { argv = ["vpt", "print-file", "package.json", "packages/app/package.json", "packages/admin/package.json", "packages/utils/package.json"], continue-on-failure = true }, diff --git a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots/command_remove_yarn4_with_workspace.md b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots/command_remove_yarn4_with_workspace.md index a3196cad10..df6ae81533 100644 --- a/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots/command_remove_yarn4_with_workspace.md +++ b/crates/vp_cli_snapshots/tests/cli_snapshots/fixtures/command_remove_yarn4_with_workspace/snapshots/command_remove_yarn4_with_workspace.md @@ -75,11 +75,12 @@ prepare packages } ``` -## `vp remove testnpm2 -r --filter=app --filter=@vite-plus-test/utils` +## `vp remove testnpm2 -r --workspace-root --filter=app --filter=@vite-plus-test/utils` recursive remove affects only app and utils ``` +warn: yarn does not support --workspace-root. [app]: Process started [app]: ➤ YN0000: · Yarn [app]: ➤ YN0000: ┌ Resolution step diff --git a/crates/vp_pm_cli/src/resolution/commands/remove.rs b/crates/vp_pm_cli/src/resolution/commands/remove.rs index a48745254b..b46a19f2a6 100644 --- a/crates/vp_pm_cli/src/resolution/commands/remove.rs +++ b/crates/vp_pm_cli/src/resolution/commands/remove.rs @@ -24,7 +24,7 @@ pub struct RemoveArgs { pub(crate) filter: Vec, /// Remove from workspace root - #[arg(short = 'w', long, not_supported(bun))] + #[arg(short = 'w', long, not_supported(yarn, bun))] pub(crate) workspace_root: bool, /// Remove recursively from all workspace packages @@ -230,6 +230,25 @@ mod tests { assert_eq!(command.args, vec!["remove", "lodash"]); } + #[test] + fn yarn_drops_unsupported_workspace_root() { + for version in ["1.22.22", "4.0.0"] { + let mut options = remove_args(&["lodash"]); + options.workspace_root = true; + let resolution = resolve(&yarn(version), options); + let command = expect_run(resolution.outcome); + + assert_eq!(command.program, "yarn"); + assert_eq!(command.args, vec!["remove", "lodash"]); + let messages = resolution + .diagnostics + .iter() + .map(|entry| entry.message.as_str()) + .collect::>(); + assert_eq!(messages, vec!["yarn does not support --workspace-root."]); + } + } + #[test] fn test_yarn_classic_rejects_filtered_remove() { for filters in