ingredients

Crates.ioingredients
lib.rsingredients
version0.2.2
created_at2025-12-22 18:54:43.538869+00
updated_at2026-01-22 17:20:59.337323+00
descriptionCheck ingredients of published Rust crates
homepage
repositoryhttps://codeberg.org/decathorpe/ingredients
max_upload_size
id2000128
size197,866
Fabio Valentini (decathorpe)

documentation

README

Check ingredients of published Rust crates

This crate implements two modes for checking ingredients of Rust crates:

  • report: Comparing published crate sources from crates.io with the associated contents of the project's version control system.
  • diff: Compare contents of two different, published versions of the same crate.

report mode

This comparison mode reads crate metadata (from Cargo.toml and from the .cargo_vcs_info.json file that is embedded by cargo during the publishing process), fetches the corresponding git repository, and compares the contents of the published crate with the contents of the project repository at the ref that is recorded in .cargo_vcs_info.json.

Any actual differences in file contents or crate metadata are considered to be errors. Issues that prevent checking for differences (like missing metadata or an invalid git repository) are considered fatal.

Example using the Rust API:

use ingredients::Crate;

#[tokio::main]
async fn main() {
    let krate = Crate::download("syn", "2.0.111").await.unwrap();
    let report = krate.report().await.unwrap();
    println!("{report}");
}

Example using the CLI:

ingredients report syn 2.0.111

Some differences are "expected" and are not reported:

  • The Cargo.toml file is processed and rewritten during the publishing process. Instead, the Cargo.toml contents from the repository is compared to Cargo.toml.orig, which contains the original, unmodified file contents.
  • Instead, crate metadata is compared by parsing Cargo.toml contents and checking for semantic equivalence instead of byte-for-byte equivalence.
  • Dependencies that are "path"-based are stripped by cargo during the publishing process. Differences in crate dependencies that are solely due to "path"-based dependencies having been stripped are ignored and not reported.
  • Symbolic links present in the project repository are resolved during the publishing process, cargo includes actual files in published crates instead.

diff mode

This mode compares crate metadata and contents between two source archives that were published to crates.io. It is much less strict than the "report" mode (because differences are expected when comparing two different versions of a crate), but will report differences with more granularity than just reporting an error on any difference. As such, the only difference that actually triggers a lint with "error" severity is if the crate name is different. This should only ever happen when comparing two different crates (but which might be useful to do in cases where a crate is "renamed", i.e. new versions are published under a different name).

Example using the Rust API:

use ingredients::Crate;

#[tokio::main]
async fn main() {
    let old_krate = Crate::download("syn", "2.0.110").await.unwrap();
    let new_krate = Crate::download("syn", "2.0.111").await.unwrap();
    let diff = old_krate.diff(&new_krate).unwrap();
    println!("{diff}");
}

Example using the CLI:

ingredients diff syn 2.0.110 2.0.111

Features

  • cli (disabled by default)

Almost all functionality from the crate API is also available from the command-line interface. To build the ingredients command-line program, compile with the cli feature enabled.

Installation

From crates.io: cargo install -F cli ingredients

External dependencies

Building:

  • cargo (refer to package.rust-version in Cargo.toml for the minimum supported Rust version)
  • openssl development headers must be available (for reqwest/native-tls)

Runtime:

  • cargo must be available in $PATH

Loading and parsing crate metadata is implemented based on the cargo_metadata crate, which calls cargo metadata internally.

  • git must be available in $PATH for "report" mode

The git command is used for checking out git repositories in Crate::report, and in turn, it is also required by the ingredients report subcommand.

Moving to a solution for cloning / checkout out git repositories that does not rely on an external git command is planned, but currently blocked by missing support for shallow clones / cloning non-branch refs in gitoxide (see https://github.com/GitoxideLabs/gitoxide/discussions/2309), among other issues.

Commit count: 76

cargo fmt