1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
# 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:
```rust,no_run
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:
```sh
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:
```rust,no_run
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:
```sh
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.
[crates.io]: https://crates.io
|