Skip to content
Open
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
3 changes: 3 additions & 0 deletions .spelling
Original file line number Diff line number Diff line change
Expand Up @@ -521,3 +521,6 @@ deprecations
parallelization
remediate
recency
symlink
symlinked
symlinks
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ Please see each crate's change log below:
- [`cargo-each`](./crates/cargo-each/CHANGELOG.md)
- [`cargo-ensure-no-cyclic-deps`](./crates/cargo_ensure_no_cyclic_deps/CHANGELOG.md)
- [`cargo-ensure-no-default-features`](./crates/cargo-ensure-no-default-features/CHANGELOG.md)
- [`cargo-ensure-no-unused-workspace-deps`](./crates/cargo-ensure-no-unused-workspace-deps/CHANGELOG.md)
- [`cargo-heather`](./crates/cargo-heather/CHANGELOG.md)
Comment thread
martin-kolinek marked this conversation as resolved.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ These are the crates built out of this repo:
- [`cargo-each`](./crates/cargo-each/README.md) - A cargo subcommand that runs a command over a cargo-style selection of workspace members
- [`cargo-ensure-no-cyclic-deps`](./crates/cargo_ensure_no_cyclic_deps/README.md) - A cargo subcommand to detect cyclic dependencies in workspace crates
- [`cargo-ensure-no-default-features`](./crates/cargo-ensure-no-default-features/README.md) - A cargo subcommand that ensures dependencies are declared with default-features = false
- [`cargo-ensure-no-unused-workspace-deps`](./crates/cargo-ensure-no-unused-workspace-deps/README.md) - A cargo subcommand that ensures every [workspace.dependencies] entry is inherited by a workspace member
- [`cargo-heather`](./crates/cargo-heather/README.md) - A cargo subcommand to validate license headers in Rust, TOML, PowerShell, Just, and env source files

## About this Repo
Expand Down
1 change: 1 addition & 0 deletions crates/cargo-ensure-no-unused-workspace-deps/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Changelog
Comment thread
martin-kolinek marked this conversation as resolved.
41 changes: 41 additions & 0 deletions crates/cargo-ensure-no-unused-workspace-deps/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

[package]
name = "cargo-ensure-no-unused-workspace-deps"
Comment thread
martin-kolinek marked this conversation as resolved.
description = "A cargo subcommand that ensures every [workspace.dependencies] entry is inherited by a workspace member"
version = "0.1.0"
readme = "README.md"
keywords = ["oxidizer", "cargo", "subcommand", "dependencies", "ci"]
categories = ["command-line-utilities", "development-tools::cargo-plugins"]

edition.workspace = true
rust-version.workspace = true
authors.workspace = true
license.workspace = true
homepage.workspace = true
repository = "https://github.com/microsoft/ox-tools/tree/main/crates/cargo-ensure-no-unused-workspace-deps"

[package.metadata.docs.rs]
all-features = true

[package.metadata.cargo_check_external_types]
# `anyhow::Error` leaks through the `run` entry point that `main` calls. Mirrors the
# allowlist entry in `cargo-ensure-no-default-features`, which has the same shape.
allowed_external_types = ["anyhow::Result"]

[[bin]]
name = "cargo-ensure-no-unused-workspace-deps"
path = "src/main.rs"

[dependencies]
anyhow = { workspace = true, features = ["std"] }
cargo_metadata = { workspace = true }
clap = { workspace = true, features = ["std", "derive", "color", "help", "error-context", "usage"] }
tempfile = { workspace = true }
toml_edit = { workspace = true }

# >>> anvil-managed: anvil-lints
[lints]
workspace = true
# <<< anvil-managed: anvil-lints
101 changes: 101 additions & 0 deletions crates/cargo-ensure-no-unused-workspace-deps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<div align="center">
<img src="./logo.png" alt="Cargo-Ensure-No-Unused-Workspace-Deps Logo" width="96">

# Cargo-Ensure-No-Unused-Workspace-Deps

[![crates.io](https://img.shields.io/crates/v/cargo-ensure-no-unused-workspace-deps.svg)](https://crates.io/crates/cargo-ensure-no-unused-workspace-deps)
[![docs.rs](https://docs.rs/cargo-ensure-no-unused-workspace-deps/badge.svg)](https://docs.rs/cargo-ensure-no-unused-workspace-deps)
[![MSRV](https://img.shields.io/crates/msrv/cargo-ensure-no-unused-workspace-deps)](https://crates.io/crates/cargo-ensure-no-unused-workspace-deps)
[![CI](https://github.com/microsoft/ox-tools/actions/workflows/main.yml/badge.svg?event=push)](https://github.com/microsoft/ox-tools/actions/workflows/main.yml)
[![Coverage](https://codecov.io/gh/microsoft/ox-tools/graph/badge.svg?token=FCUG0EL5TI)](https://codecov.io/gh/microsoft/ox-tools)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](../../LICENSE)
<a href="../.."><img src="../../logo.svg" alt="This crate was developed as part of the Oxidizer project" width="20"></a>

</div>

A cargo sub-command that ensures every `[workspace.dependencies]` entry is
inherited by at least one workspace member.

A workspace root declares a dependency catalog that members draw from with
`dep = { workspace = true }`. Nothing requires an entry to be drawn from, so
an entry nobody inherits stays in the manifest forever: it never enters the
dependency graph, and no build fails because of it. It still carries a
version requirement, so it keeps attracting dependency-bump traffic and keeps
misleading readers about what the workspace depends on.

Unused-dependency tools resolve the crate graph and ask which *declared*
dependencies go unused, so an entry that no member declares is invisible to
them. This tool answers the prior question – is the entry inherited at all?
– from the manifests alone, which makes it free of false positives and cheap
enough to run on every pull request.

## Usage

Run in a cargo workspace:

```bash
cargo ensure-no-unused-workspace-deps
```

Remove what it finds:

```bash
cargo ensure-no-unused-workspace-deps --fix
```

`--manifest-path` points at an explicit workspace root, defaulting to the
`Cargo.toml` in the current directory. A manifest with no `[workspace]` table
declares no catalog and passes with a note; `--require-workspace` turns that
into an error for callers that know they are pointing at a workspace root.

## Configuration

An entry kept on purpose is exempted in the workspace manifest:

```toml
[workspace.metadata.ensure-no-unused-workspace-deps]
allowed = ["kept-on-purpose"]
```

An `allowed` name that suppresses nothing is reported as stale, on stderr,
without failing the run.

## Fixing

`--fix` replaces the manifest atomically – a temporary file in the same
directory, renamed over the original, carrying the permissions of the
manifest it replaces and following a symlinked manifest to its target – and
refuses to write at all if the file changed after it was read, so a
concurrent edit is never clobbered.

Comments on a removed entry are carried to the next surviving entry, which
keeps a group header attached to the group it introduces. A note about one
specific dependency is indistinguishable from such a header, so every move
is reported on stderr: check that carried text still describes the entry it
landed on. Comments that cannot be placed – the removal emptied the table,
or left a trailing survivor with nothing to append to – are reported as
dropped.

## Installation

```bash
cargo install cargo-ensure-no-unused-workspace-deps
```

## Example output

```text
Found 2 unused workspace dependencies in Cargo.toml:

- once_cell
- smallvec

Re-run with --fix to remove them.
```


<hr/>
<sub>
This crate was developed as part of <a href="../..">The Oxidizer Project</a>. Browse this crate's <a href="https://github.com/microsoft/ox-tools/tree/main/crates/cargo-ensure-no-unused-workspace-deps">source code</a>.
</sub>

Loading
Loading