Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cargo remove should clean up removed dependencies from the cache #647

Open
AuracleTech opened this issue Feb 23, 2022 · 4 comments
Open
Labels

Comments

@AuracleTech
Copy link

After installing cargo-edit I can cargo add crate_name, great
But now to remove one, cargo rm doesn't seem to delete the crate and its dependencies
image
Like, there's no logging, there's no progress, did it remove all packages, or just unlinked them?

Also, why cargo add
But cargo rm

Why cut the word? Put both option at least, the convention for rust is using the whole word, I don't understand why this one is an exception.

@epage
Copy link
Collaborator

epage commented Feb 23, 2022

But now to remove one, cargo rm doesn't seem to delete the crate and its dependencies

What are you observing that leads you to say this?

I just went into a project with the following lines in Cargo.toml:

[dependencies]
cargo_metadata = "0.14"

I then ran

$ cargo rm cargo_metadata
    Removing cargo_metadata from dependencies

and now my Cargo.toml file does not list it.

Why cut the word? Put both option at least, the convention for rust is using the whole word, I don't understand why this one is an exception.

I'm not aware of any such convention. Rust regularly uses abbreviations (Buf, str, etc). Rust has also preferred un-rust-like naming conventions when there is strong enough precedence in other ecosystems (can't remember which function but there is some integer or float functions that have no _ in them between words).

However, it seems the precedence among related tools is to use remove despite the unix utility rms precedence (after surveying all other commands that have an add).

This is s topic we'll review when we are working on merging cargo-rm into cargo. Right now, the focus is on cargo-add.

@AuracleTech
Copy link
Author

and now my Cargo.toml file does not list it.

What I meant is the dependencies might not be on the cargo.toml anymore, but they're still downloaded. Node.js as example deletes the packages and their dependencies from the disk, liberating space.

However, it seems the precedence among related tools is to use remove despite the unix utility rms precedence (after surveying all other commands that have an add).

Happy to hear we might be able to use cargo remove eventually! 😄

@epage
Copy link
Collaborator

epage commented Feb 23, 2022

What I meant is the dependencies might not be on the cargo.toml anymore, but they're still downloaded. Node.js as example deletes the packages and their dependencies from the disk, liberating space.

The cases for clean up I can think of

  • The downloaded crate: this is global for the user, so we don't have a way to garbage collect this
  • Crate-specific intermediate build artifacts: this is global to workspace and we'd to check if that dependency is no longer in the lock file. Overall, I see this as a low priority nice to have since removing dependencies is usually not a common workflow for space savings.
  • Vendored dependencies (ie copied into the git repo): we've not really explored how these tools should interact with cargo vendor though this one makes sense to do.

@epage
Copy link
Collaborator

epage commented Feb 23, 2022

Forgot to add, of those, what are your expectations and care abouts?

@epage epage added the cargo-rm label Mar 29, 2022
@epage epage changed the title cargo remove cargo remove should clean up removed dependencies Mar 29, 2022
@epage epage mentioned this issue Mar 29, 2022
14 tasks
@epage epage changed the title cargo remove should clean up removed dependencies cargo remove should clean up removed dependencies from the cache Apr 20, 2022
bors added a commit to rust-lang/cargo that referenced this issue Oct 6, 2022
Import `cargo remove` into cargo

## What does this PR try to resolve?

This PR merges `cargo remove` from [cargo-edit](https://github.com/killercup/cargo-edit) into cargo.

### Motivation

- General approval from community, see #5586 and #10520.
- Satisfying symmetry between add and remove.
- Help users clean up their manifests (for example, when users forget to remove optional dependencies from feature lists).

With #10472, cargo-add was added to cargo. As part of that discussion, it was also proposed that `cargo rm` (now `cargo remove`) eventually be added as well.

### Drawbacks

- Additional code always opens the door for more bugs and features
  - The scope of this command is fairly small though
  - Known bugs and most known features were resolved before this merge proposal

### Behavior

`cargo remove` operates on one or more dependencies from a manifest, removing them from a specified dependencies section (using the same flags as `cargo-add`) and from `[features]` activations if the dependency is optional. Feature lists themselves are not automatically removed when made empty.  Like with cargo-add, the lock file is automatically updated.

Note: like `cargo add`, `cargo remove` refers to dependency names, rather than crate names, which can be different with the presence of the `name` field.

Note: `cargo rm` has been renamed to `cargo remove`, based on prior art and user feedback (see [discussion](#10520)). Although this renaming is arguably an improvement, adding an `rm` alias could make the switch easier for existing users of cargo-edit (at the cost of a naming conflict which would merit insta-stabilization).

#### Help output

<details>

  ```shell
  $ cargo run -- remove --help
  cargo-remove
  Remove dependencies from a Cargo.toml manifest file

  USAGE:
      cargo remove [OPTIONS] <DEP_ID>...

  ARGS:
      <DEP_ID>...    Dependencies to be removed

  OPTIONS:
      -p, --package [<SPEC>...]     Package to remove from
      -v, --verbose                 Use verbose output (-vv very verbose/build.rs output)
          --manifest-path <PATH>    Path to Cargo.toml
          --offline                 Run without accessing the network
      -q, --quiet                   Do not print cargo log messages
          --dry-run                 Don't actually write the manifest
      -Z <FLAG>                     Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
      -h, --help                    Print help information

  SECTION:
          --dev                Remove as development dependency
          --build              Remove as build dependency
          --target <TARGET>    Remove as dependency from the given target platform
  ```

</details>

#### Example usage

```
cargo remove serde
cargo remove criterion httpmock --dev
cargo remove winhttp --target x86_64-pc-windows-gnu
cargo remove --package core toml
```

## How should we test and review this PR?

This is following the pattern from cargo-add which was implemented in three different PRs (implementation, documentation, and completions), in the interest of reducing the focusing discussions in each PR and allowing cargo-add's behavior to settle to avoid documentation churn.

1. #10472
2. #10578
3. #10577

The remaining changes (documentation and shell completions) will follow shortly after.

Some work has already begun on this feature in #11059.

Work on this feature was carried out on the [`merge-rm`](killercup/cargo-edit@master...merge-rm) branch of cargo-edit with PRs reviewed by `@epage.` If you are interested in seeing how this feature evolved to better match cargo's internals, you might find the commit history there to be helpful. As this PR is reviewed, changes will be made both here and on that branch, with the commit history being fully maintained on the latter.

`cargo remove` is structured like most other subcommands:

- `src/bin/cargo/commands/remove.rs` contains the cli handling and top-level execution.
- `src/cargo/ops/cargo_remove.rs` contains the implementation of the feature itself.

In order to support this feature, the `remove_from_table` util was added to `util::toml_mut::manifest::LocalManifest`.

Tests are split out into a separate commit to make it easier to review the production code and tests.  Tests have been implemented with `snapbox`, structured similarly to the tests of `cargo add`.

### Prior art

- Python: [`poetry remove`](https://python-poetry.org/docs/cli/#remove)
  - Supports dry run
- JavaScript: [`yarn remove`](https://yarnpkg.com/cli/remove)
  - Supports wildcards
- JavaScript: [`pnpm remove`](https://pnpm.io/cli/remove)
- Go: [`go get`](https://go.dev/ref/mod#go-get)
  - `go get foo@none` to remove
- Julia: [`pkg rm`](https://docs.julialang.org/en/v1/stdlib/Pkg/)
  - Supports `--all` to remove all dependencies
- Ruby: [`bundle remove`](https://bundler.io/v2.2/man/bundle-remove.1.html)
- Dart: [`dart pub remove`](https://dart.dev/tools/pub/cmd/pub-remove)
  - Supports dry run
- Lua: [`luarocks remove`](https://github.com/luarocks/luarocks/wiki/remove)
  - Supports force remove
- .NET: [`Uninstall-Package`](https://docs.microsoft.com/en-us/nuget/reference/ps-reference/ps-ref-uninstall-package)
  - Supports dry run
  - Supports removal of dependencies
  - Supports force remove (disregards dependencies)
- Haxe: [`haxelib remove`](https://lib.haxe.org/documentation/using-haxelib/#remove)
- Racket: [`raco pkg remove`](https://docs.racket-lang.org/pkg/cmdline.html#%28part._raco-pkg-remove%29)
  - Supports dry run
  - Supports force remove (disregards dependencies)
  - Supports demotion to weak dependency (sort of a corollary of force remove)

### Insta-stabilization

In the discussion of `cargo add`'s stabilization story ([Zulip stream](https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo/topic/Stablizing.20cargo-add)), it was brought up that the feature might benefit from being insta-stabilized to avoid making the cargo-edit version of the binary hard to access. Since `cargo rm` (from cargo-edit) was renamed to `cargo remove` here, [such a conflict no longer exists](https://crates.io/search?q=cargo%20remove), so this is less of a concern.

Since this feature is already has a had a long run of user testing in cargo-edit and doesn't have unsettled UI questions like cargo-add did, it might still be a candidate for insta-stabilization.

### Deferred work

Necessary future work:

- Add documentation.
- Add shell completions.
- Perform GC on workspace dependencies when they are no longer used (see #8415).
  - This is inspired by a feature from the RFC that was dropped (unused dependencies triggering a warning)
  - This was deferred out to avoid challenges with testing nightly features

It was found in the review of `cargo add` that it was best to defer these first two items to focus the discussion and as there was still behavior churn during the review of cargo-add.

### Future Possibilities

The following are features which we might want to add to `cargo remove` in the future:

- Add a `cargo rm` alias to ease transition for current cargo-edit users
- Automatically convert between dash and underscores in deps: killercup/cargo-edit#690
- Remove unused dependencies: killercup/cargo-edit#415
- Clean up caches: killercup/cargo-edit#647

### Additional information

Fixes #10520.
bors added a commit to rust-lang/cargo that referenced this issue Oct 6, 2022
Import `cargo remove` into cargo

## What does this PR try to resolve?

This PR merges `cargo remove` from [cargo-edit](https://github.com/killercup/cargo-edit) into cargo.

### Motivation

- General approval from community, see #5586 and #10520.
- Satisfying symmetry between add and remove.
- Help users clean up their manifests (for example, when users forget to remove optional dependencies from feature lists).

With #10472, cargo-add was added to cargo. As part of that discussion, it was also proposed that `cargo rm` (now `cargo remove`) eventually be added as well.

### Drawbacks

- Additional code always opens the door for more bugs and features
  - The scope of this command is fairly small though
  - Known bugs and most known features were resolved before this merge proposal

### Behavior

`cargo remove` operates on one or more dependencies from a manifest, removing them from a specified dependencies section (using the same flags as `cargo-add`) and from `[features]` activations if the dependency is optional. Feature lists themselves are not automatically removed when made empty.  Like with cargo-add, the lock file is automatically updated.

Note: like `cargo add`, `cargo remove` refers to dependency names, rather than crate names, which can be different with the presence of the `name` field.

Note: `cargo rm` has been renamed to `cargo remove`, based on prior art and user feedback (see [discussion](#10520)). Although this renaming is arguably an improvement, adding an `rm` alias could make the switch easier for existing users of cargo-edit (at the cost of a naming conflict which would merit insta-stabilization).

#### Help output

<details>

  ```shell
  $ cargo run -- remove --help
  cargo-remove
  Remove dependencies from a Cargo.toml manifest file

  USAGE:
      cargo remove [OPTIONS] <DEP_ID>...

  ARGS:
      <DEP_ID>...    Dependencies to be removed

  OPTIONS:
      -p, --package [<SPEC>...]     Package to remove from
      -v, --verbose                 Use verbose output (-vv very verbose/build.rs output)
          --manifest-path <PATH>    Path to Cargo.toml
          --offline                 Run without accessing the network
      -q, --quiet                   Do not print cargo log messages
          --dry-run                 Don't actually write the manifest
      -Z <FLAG>                     Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
      -h, --help                    Print help information

  SECTION:
          --dev                Remove as development dependency
          --build              Remove as build dependency
          --target <TARGET>    Remove as dependency from the given target platform
  ```

</details>

#### Example usage

```
cargo remove serde
cargo remove criterion httpmock --dev
cargo remove winhttp --target x86_64-pc-windows-gnu
cargo remove --package core toml
```

## How should we test and review this PR?

This is following the pattern from cargo-add which was implemented in three different PRs (implementation, documentation, and completions), in the interest of reducing the focusing discussions in each PR and allowing cargo-add's behavior to settle to avoid documentation churn.

1. #10472
2. #10578
3. #10577

The remaining changes (documentation and shell completions) will follow shortly after.

Some work has already begun on this feature in #11059.

Work on this feature was carried out on the [`merge-rm`](killercup/cargo-edit@master...merge-rm) branch of cargo-edit with PRs reviewed by `@epage.` If you are interested in seeing how this feature evolved to better match cargo's internals, you might find the commit history there to be helpful. As this PR is reviewed, changes will be made both here and on that branch, with the commit history being fully maintained on the latter.

`cargo remove` is structured like most other subcommands:

- `src/bin/cargo/commands/remove.rs` contains the cli handling and top-level execution.
- `src/cargo/ops/cargo_remove.rs` contains the implementation of the feature itself.

In order to support this feature, the `remove_from_table` util was added to `util::toml_mut::manifest::LocalManifest`.

Tests are split out into a separate commit to make it easier to review the production code and tests.  Tests have been implemented with `snapbox`, structured similarly to the tests of `cargo add`.

### Prior art

- Python: [`poetry remove`](https://python-poetry.org/docs/cli/#remove)
  - Supports dry run
- JavaScript: [`yarn remove`](https://yarnpkg.com/cli/remove)
  - Supports wildcards
- JavaScript: [`pnpm remove`](https://pnpm.io/cli/remove)
- Go: [`go get`](https://go.dev/ref/mod#go-get)
  - `go get foo@none` to remove
- Julia: [`pkg rm`](https://docs.julialang.org/en/v1/stdlib/Pkg/)
  - Supports `--all` to remove all dependencies
- Ruby: [`bundle remove`](https://bundler.io/v2.2/man/bundle-remove.1.html)
- Dart: [`dart pub remove`](https://dart.dev/tools/pub/cmd/pub-remove)
  - Supports dry run
- Lua: [`luarocks remove`](https://github.com/luarocks/luarocks/wiki/remove)
  - Supports force remove
- .NET: [`Uninstall-Package`](https://docs.microsoft.com/en-us/nuget/reference/ps-reference/ps-ref-uninstall-package)
  - Supports dry run
  - Supports removal of dependencies
  - Supports force remove (disregards dependencies)
- Haxe: [`haxelib remove`](https://lib.haxe.org/documentation/using-haxelib/#remove)
- Racket: [`raco pkg remove`](https://docs.racket-lang.org/pkg/cmdline.html#%28part._raco-pkg-remove%29)
  - Supports dry run
  - Supports force remove (disregards dependencies)
  - Supports demotion to weak dependency (sort of a corollary of force remove)

### Insta-stabilization

In the discussion of `cargo add`'s stabilization story ([Zulip stream](https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo/topic/Stablizing.20cargo-add)), it was brought up that the feature might benefit from being insta-stabilized to avoid making the cargo-edit version of the binary hard to access. Since `cargo rm` (from cargo-edit) was renamed to `cargo remove` here, [such a conflict no longer exists](https://crates.io/search?q=cargo%20remove), so this is less of a concern.

Since this feature is already has a had a long run of user testing in cargo-edit and doesn't have unsettled UI questions like cargo-add did, it might still be a candidate for insta-stabilization.

### Deferred work

Necessary future work:

- Add documentation.
- Add shell completions.
- Perform GC on workspace dependencies when they are no longer used (see #8415).
  - This is inspired by a feature from the RFC that was dropped (unused dependencies triggering a warning)
  - This was deferred out to avoid challenges with testing nightly features

It was found in the review of `cargo add` that it was best to defer these first two items to focus the discussion and as there was still behavior churn during the review of cargo-add.

### Future Possibilities

The following are features which we might want to add to `cargo remove` in the future:

- Add a `cargo rm` alias to ease transition for current cargo-edit users
- Automatically convert between dash and underscores in deps: killercup/cargo-edit#690
- Remove unused dependencies: killercup/cargo-edit#415
- Clean up caches: killercup/cargo-edit#647

### Additional information

Fixes #10520.
bors added a commit to rust-lang/cargo that referenced this issue Oct 6, 2022
Import `cargo remove` into cargo

## What does this PR try to resolve?

This PR merges `cargo remove` from [cargo-edit](https://github.com/killercup/cargo-edit) into cargo.

### Motivation

- General approval from community, see #5586 and #10520.
- Satisfying symmetry between add and remove.
- Help users clean up their manifests (for example, when users forget to remove optional dependencies from feature lists).

With #10472, cargo-add was added to cargo. As part of that discussion, it was also proposed that `cargo rm` (now `cargo remove`) eventually be added as well.

### Drawbacks

- Additional code always opens the door for more bugs and features
  - The scope of this command is fairly small though
  - Known bugs and most known features were resolved before this merge proposal

### Behavior

`cargo remove` operates on one or more dependencies from a manifest, removing them from a specified dependencies section (using the same flags as `cargo-add`) and from `[features]` activations if the dependency is optional. Feature lists themselves are not automatically removed when made empty.  Like with cargo-add, the lock file is automatically updated.

Note: like `cargo add`, `cargo remove` refers to dependency names, rather than crate names, which can be different with the presence of the `name` field.

Note: `cargo rm` has been renamed to `cargo remove`, based on prior art and user feedback (see [discussion](#10520)). Although this renaming is arguably an improvement, adding an `rm` alias could make the switch easier for existing users of cargo-edit (at the cost of a naming conflict which would merit insta-stabilization).

#### Help output

<details>

  ```shell
  $ cargo run -- remove --help
  cargo-remove
  Remove dependencies from a Cargo.toml manifest file

  USAGE:
      cargo remove [OPTIONS] <DEP_ID>...

  ARGS:
      <DEP_ID>...    Dependencies to be removed

  OPTIONS:
      -p, --package [<SPEC>...]     Package to remove from
      -v, --verbose                 Use verbose output (-vv very verbose/build.rs output)
          --manifest-path <PATH>    Path to Cargo.toml
          --offline                 Run without accessing the network
      -q, --quiet                   Do not print cargo log messages
          --dry-run                 Don't actually write the manifest
      -Z <FLAG>                     Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
      -h, --help                    Print help information

  SECTION:
          --dev                Remove as development dependency
          --build              Remove as build dependency
          --target <TARGET>    Remove as dependency from the given target platform
  ```

</details>

#### Example usage

```
cargo remove serde
cargo remove criterion httpmock --dev
cargo remove winhttp --target x86_64-pc-windows-gnu
cargo remove --package core toml
```

## How should we test and review this PR?

This is following the pattern from cargo-add which was implemented in three different PRs (implementation, documentation, and completions), in the interest of reducing the focusing discussions in each PR and allowing cargo-add's behavior to settle to avoid documentation churn.

1. #10472
2. #10578
3. #10577

The remaining changes (documentation and shell completions) will follow shortly after.

Some work has already begun on this feature in #11059.

Work on this feature was carried out on the [`merge-rm`](killercup/cargo-edit@master...merge-rm) branch of cargo-edit with PRs reviewed by `@epage.` If you are interested in seeing how this feature evolved to better match cargo's internals, you might find the commit history there to be helpful. As this PR is reviewed, changes will be made both here and on that branch, with the commit history being fully maintained on the latter.

`cargo remove` is structured like most other subcommands:

- `src/bin/cargo/commands/remove.rs` contains the cli handling and top-level execution.
- `src/cargo/ops/cargo_remove.rs` contains the implementation of the feature itself.

In order to support this feature, the `remove_from_table` util was added to `util::toml_mut::manifest::LocalManifest`.

Tests are split out into a separate commit to make it easier to review the production code and tests.  Tests have been implemented with `snapbox`, structured similarly to the tests of `cargo add`.

### Prior art

- Python: [`poetry remove`](https://python-poetry.org/docs/cli/#remove)
  - Supports dry run
- JavaScript: [`yarn remove`](https://yarnpkg.com/cli/remove)
  - Supports wildcards
- JavaScript: [`pnpm remove`](https://pnpm.io/cli/remove)
- Go: [`go get`](https://go.dev/ref/mod#go-get)
  - `go get foo@none` to remove
- Julia: [`pkg rm`](https://docs.julialang.org/en/v1/stdlib/Pkg/)
  - Supports `--all` to remove all dependencies
- Ruby: [`bundle remove`](https://bundler.io/v2.2/man/bundle-remove.1.html)
- Dart: [`dart pub remove`](https://dart.dev/tools/pub/cmd/pub-remove)
  - Supports dry run
- Lua: [`luarocks remove`](https://github.com/luarocks/luarocks/wiki/remove)
  - Supports force remove
- .NET: [`Uninstall-Package`](https://docs.microsoft.com/en-us/nuget/reference/ps-reference/ps-ref-uninstall-package)
  - Supports dry run
  - Supports removal of dependencies
  - Supports force remove (disregards dependencies)
- Haxe: [`haxelib remove`](https://lib.haxe.org/documentation/using-haxelib/#remove)
- Racket: [`raco pkg remove`](https://docs.racket-lang.org/pkg/cmdline.html#%28part._raco-pkg-remove%29)
  - Supports dry run
  - Supports force remove (disregards dependencies)
  - Supports demotion to weak dependency (sort of a corollary of force remove)

### Insta-stabilization

In the discussion of `cargo add`'s stabilization story ([Zulip stream](https://rust-lang.zulipchat.com/#narrow/stream/246057-t-cargo/topic/Stablizing.20cargo-add)), it was brought up that the feature might benefit from being insta-stabilized to avoid making the cargo-edit version of the binary hard to access. Since `cargo rm` (from cargo-edit) was renamed to `cargo remove` here, [such a conflict no longer exists](https://crates.io/search?q=cargo%20remove), so this is less of a concern.

Since this feature is already has a had a long run of user testing in cargo-edit and doesn't have unsettled UI questions like cargo-add did, it might still be a candidate for insta-stabilization.

### Deferred work

Necessary future work:

- Add documentation.
- Add shell completions.
- Perform GC on workspace dependencies when they are no longer used (see #8415).
  - This is inspired by a feature from the RFC that was dropped (unused dependencies triggering a warning)
  - This was deferred out to avoid challenges with testing nightly features

It was found in the review of `cargo add` that it was best to defer these first two items to focus the discussion and as there was still behavior churn during the review of cargo-add.

### Future Possibilities

The following are features which we might want to add to `cargo remove` in the future:

- Add a `cargo rm` alias to ease transition for current cargo-edit users
- Automatically convert between dash and underscores in deps: killercup/cargo-edit#690
- Remove unused dependencies: killercup/cargo-edit#415
- Clean up caches: killercup/cargo-edit#647

### Additional information

Fixes #10520.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants