Skip to main content

battery_pack/
lib.rs

1//! battery-pack: Framework for building and using battery packs.
2//!
3//! Battery packs are curated collections of crates that work well together.
4//! The CLI (`cargo bp`) syncs real dependencies into your Cargo.toml,
5//! and this library provides build-time validation to detect drift.
6//!
7//! # For Battery Pack Authors
8//!
9//! Your lib.rs should look like this:
10//!
11//! ```rust,ignore
12//! const SELF_MANIFEST: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml"));
13//!
14//! pub fn validate() {
15//!     battery_pack::validate(SELF_MANIFEST);
16//! }
17//! ```
18//!
19//! # For Battery Pack Users
20//!
21//! Your build.rs should call validate:
22//!
23//! ```rust,ignore
24//! fn main() {
25//!     cli_battery_pack::validate();
26//! }
27//! ```
28
29pub use bphelper_manifest::{BatteryPackSpec, DepSpec, assert_no_regular_deps};
30
31/// Validate that the calling crate's dependencies match a battery pack's specs.
32///
33/// Call this from your battery pack's `validate()` function, passing
34/// the embedded manifest string. This reads the user's Cargo.toml via
35/// the runtime `CARGO_MANIFEST_DIR` env var (which, in build.rs, points
36/// to the user's crate) and compares against the battery pack specs.
37///
38/// Emits `cargo:warning` messages for any drift. Never fails the build.
39pub fn validate(self_manifest: &str) {
40    let bp_spec = match bphelper_manifest::parse_battery_pack(self_manifest) {
41        Ok(spec) => spec,
42        Err(e) => {
43            println!("cargo:warning=battery-pack: failed to parse battery pack manifest: {e}");
44            return;
45        }
46    };
47
48    let user_toml_path = match std::env::var("CARGO_MANIFEST_DIR") {
49        Ok(dir) => format!("{dir}/Cargo.toml"),
50        Err(_) => {
51            println!("cargo:warning=battery-pack: CARGO_MANIFEST_DIR not set, skipping validation");
52            return;
53        }
54    };
55
56    let user_manifest = match std::fs::read_to_string(&user_toml_path) {
57        Ok(content) => content,
58        Err(e) => {
59            println!("cargo:warning=battery-pack: failed to read {user_toml_path}: {e}");
60            return;
61        }
62    };
63
64    let user = match bphelper_manifest::parse_user_manifest(&user_manifest) {
65        Ok(u) => u,
66        Err(e) => {
67            println!("cargo:warning=battery-pack: failed to parse user manifest: {e}");
68            return;
69        }
70    };
71
72    bphelper_manifest::check_drift(&bp_spec, &user);
73
74    // Rerun validation when user's Cargo.toml changes
75    println!("cargo:rerun-if-changed={user_toml_path}");
76}