Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "command-yarn-classic-filtered-dependencies",
"private": true,
"packageManager": "yarn@1.22.22",
"workspaces": ["packages/*"],
"dependencies": {
"lodash": "4.17.21"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "@example/app",
"version": "1.0.0",
"dependencies": {
"lodash": "4.17.21"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[[case]]
name = "command_yarn_classic_filtered_dependencies"
vp = "global"
steps = [
{ argv = ["vp", "add", "react", "--filter", "@example/app"], comment = "Classic filtered add reports an unsupported option instead of invoking foreach", continue-on-failure = true },
{ argv = ["vp", "install", "react", "--filter", "@example/app"], comment = "install with packages uses the same add guard", continue-on-failure = true },
{ argv = ["vp", "remove", "lodash", "--filter", "@example/app"], comment = "Classic filtered remove fails before changing dependencies", continue-on-failure = true },
{ argv = ["vp", "remove", "lodash", "--filter", "@example/*", "--filter", "other", "--recursive"], comment = "recursive remove must not silently discard Classic filters", continue-on-failure = true },
{ argv = ["vpt", "print-file", "package.json", "packages/web/package.json"], comment = "root and workspace manifests remain unchanged", continue-on-failure = true },
["vpt", "stat-file", "yarn.lock", "--assert", "missing"],
["vpt", "stat-file", "node_modules", "--assert", "missing"],
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# command_yarn_classic_filtered_dependencies

## `vp add react --filter @example/app`

Classic filtered add reports an unsupported option instead of invoking foreach

**Exit code:** 1

```
Invalid argument: `--filter` is not supported by Yarn Classic `add`.
```

## `vp install react --filter @example/app`

install with packages uses the same add guard

**Exit code:** 1

```
VITE+ - The Unified Toolchain for the Web

Invalid argument: `--filter` is not supported by Yarn Classic `add`.
```

## `vp remove lodash --filter @example/app`

Classic filtered remove fails before changing dependencies

**Exit code:** 1

```
Invalid argument: `--filter` is not supported by Yarn Classic `remove`.
```

## `vp remove lodash --filter @example/* --filter other --recursive`

recursive remove must not silently discard Classic filters

**Exit code:** 1

```
Invalid argument: `--filter` is not supported by Yarn Classic `remove`.
```

## `vpt print-file package.json packages/web/package.json`

root and workspace manifests remain unchanged

```
{
"name": "command-yarn-classic-filtered-dependencies",
"private": true,
"packageManager": "yarn@1.22.22",
"workspaces": ["packages/*"],
"dependencies": {
"lodash": "4.17.21"
}
}
{
"name": "@example/app",
"version": "1.0.0",
"dependencies": {
"lodash": "4.17.21"
}
}
```

## `vpt stat-file yarn.lock --assert missing`

```
yarn.lock: missing
```

## `vpt stat-file node_modules --assert missing`

```
node_modules: missing
```
30 changes: 28 additions & 2 deletions crates/vp_pm_cli/src/resolution/commands/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,13 @@ impl Resolve<AddArgs> for Yarn {

let mut cmd = CommandBuilder::new("yarn");
if !args.filter.is_empty() {
if !self.is_berry() {
return CommandResolution::InvalidArgument(
"Invalid argument: `--filter` is not supported by Yarn Classic `add`."
.to_string(),
);
}

cmd.arg("workspaces").arg("foreach").arg("--all");
cmd.repeated("--include", args.filter.iter());
}
Expand Down Expand Up @@ -433,10 +440,10 @@ mod tests {
}

#[test]
fn test_yarn_add_with_workspace() {
fn test_yarn_berry_add_with_workspace() {
let mut options = add_args(&["react"]);
options.filter = vec!["app".to_string()];
let resolution = resolve(&yarn("1.22.22"), options);
let resolution = resolve(&yarn("4.0.0"), options);
let command = expect_run(resolution.outcome);

assert_eq!(command.program, "yarn");
Expand All @@ -446,6 +453,25 @@ mod tests {
);
}

#[test]
fn test_yarn_classic_rejects_filtered_add() {
for filters in
[vec!["app".to_string()], vec!["app-*".to_string(), "@scope/web".to_string()]]
{
let mut options = add_args(&["react"]);
options.filter = filters;
let resolution = resolve(&yarn("1.22.22"), options);

assert_eq!(
resolution.outcome,
CommandResolution::InvalidArgument(
"Invalid argument: `--filter` is not supported by Yarn Classic `add`."
.to_string()
)
);
}
}

#[test]
fn test_yarn_add_workspace_root() {
let mut options = add_args(&["typescript"]);
Expand Down
53 changes: 35 additions & 18 deletions crates/vp_pm_cli/src/resolution/commands/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,18 @@ impl Resolve<RemoveArgs> for Yarn {
}

let mut cmd = CommandBuilder::new("yarn");
if !args.filter.is_empty() && !args.recursive {
cmd.arg("workspaces").arg("foreach").arg("--all");
cmd.repeated("--include", args.filter.iter());
if !args.filter.is_empty() {
if !self.is_berry() {
return CommandResolution::InvalidArgument(
"Invalid argument: `--filter` is not supported by Yarn Classic `remove`."
.to_string(),
);
}

if !args.recursive {
cmd.arg("workspaces").arg("foreach").arg("--all");
cmd.repeated("--include", args.filter.iter());
}
}
cmd.arg("remove")
.arg_if("--all", args.recursive)
Expand Down Expand Up @@ -224,17 +233,25 @@ mod tests {
}

#[test]
fn test_yarn_remove_with_workspace() {
let mut options = remove_args(&["lodash"]);
options.filter = vec!["app".to_string()];
let resolution = resolve(&yarn("1.22.0"), options);
let command = expect_run(resolution.outcome);

assert_eq!(command.program, "yarn");
assert_eq!(
command.args,
vec!["workspaces", "foreach", "--all", "--include", "app", "remove", "lodash"]
);
fn test_yarn_classic_rejects_filtered_remove() {
for filters in
[vec!["app".to_string()], vec!["app-*".to_string(), "@scope/web".to_string()]]
{
for recursive in [false, true] {
let mut options = remove_args(&["lodash"]);
options.filter = filters.clone();
options.recursive = recursive;
let resolution = resolve(&yarn("1.22.22"), options);

assert_eq!(
resolution.outcome,
CommandResolution::InvalidArgument(
"Invalid argument: `--filter` is not supported by Yarn Classic `remove`."
.to_string()
)
);
}
}
}

#[test]
Expand Down Expand Up @@ -456,10 +473,10 @@ mod tests {
}

#[test]
fn test_yarn_remove_with_multiple_filters() {
fn test_yarn_berry_remove_with_multiple_filters() {
let mut options = remove_args(&["lodash"]);
options.filter = vec!["app".to_string(), "web".to_string()];
let resolution = resolve(&yarn("1.22.0"), options);
let resolution = resolve(&yarn("4.0.0"), options);
let command = expect_run(resolution.outcome);

assert_eq!(command.program, "yarn");
Expand All @@ -480,11 +497,11 @@ mod tests {
}

#[test]
fn test_yarn_remove_with_recursive_and_multiple_filters() {
fn test_yarn_berry_remove_with_recursive_and_multiple_filters() {
let mut options = remove_args(&["lodash"]);
options.filter = vec!["app".to_string(), "web".to_string()];
options.recursive = true;
let resolution = resolve(&yarn("1.22.0"), options);
let resolution = resolve(&yarn("4.0.0"), options);
let command = expect_run(resolution.outcome);

assert_eq!(command.program, "yarn");
Expand Down
Loading