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}