release_kit/commands/
payload.rs1use crate::cli::payload::PayloadArgs;
14use crate::error::RkError;
15use crate::output::Output;
16use crate::release::{CrateReleaseSource, EmbeddedReleaseSource, ReleaseManifest, ReleaseSource};
17
18pub type Report = ReleaseManifest;
21
22#[must_use]
24pub fn report() -> Report {
25 EmbeddedReleaseSource::manifest_ref().clone()
26}
27
28pub fn run(args: &PayloadArgs) -> Result<(), RkError> {
36 let out = Output::new(args.json);
37 let (report, source_line) = match args.release.as_deref() {
38 None => (report(), None),
39 Some(selector) => {
40 let source = CrateReleaseSource::new(selector)?;
41 let manifest = source.manifest()?;
42 let resolved = source.resolve()?;
43 let line = format!(
44 "source crates {} ({}, {})",
45 resolved.version,
46 if resolved.index_fetched {
47 "index fetched"
48 } else {
49 "index cached"
50 },
51 if resolved.archive_fetched {
52 "archive fetched and verified"
53 } else {
54 "archive cached"
55 }
56 );
57 (manifest, Some(line))
58 }
59 };
60 out.result_line(format!("release-kit {}", report.release_kit_version));
61 if let Some(line) = source_line {
62 out.result_line(line);
63 }
64 out.result_line(format!("payload sha256 {}", report.payload_sha256));
65 for root in crate::payload_roots::PAYLOAD_ROOTS {
66 let count = report
67 .artifacts
68 .iter()
69 .filter(|a| a.path == root || a.path.starts_with(&format!("{root}/")))
70 .count();
71 let noun = if count == 1 { "file" } else { "files" };
72 out.result_line(format!("{root}: {count} {noun}"));
73 }
74 out.emit(&report)
75}
76
77#[cfg(test)]
78mod tests {
79 use super::{Report, report};
80 use crate::digest::Digest;
81 use crate::release::{Artifact, aggregate};
82
83 #[test]
86 fn the_payload_report_schema_snapshot_holds() {
87 let fixture = Report::new(
88 "0.0.0".into(),
89 1,
90 vec![Artifact {
91 path: "versions.toml".into(),
92 sha256: Digest::of(b""),
93 }],
94 );
95 assert_eq!(
96 fixture.payload_sha256,
97 aggregate(&fixture.artifacts),
98 "the aggregate is computed, never supplied"
99 );
100 let mut fixture = fixture;
101 fixture.payload_sha256 = Digest::of(b"");
102 assert_eq!(
103 serde_json::to_string(&fixture).expect("a report serializes"),
104 r#"{"release_kit_version":"0.0.0","payload_schema":1,"payload_sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","artifacts":[{"path":"versions.toml","sha256":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}]}"#
105 );
106 }
107
108 #[test]
109 fn the_report_names_the_cargo_version_and_every_artifact() {
110 let report = report();
111 assert_eq!(report.release_kit_version, env!("CARGO_PKG_VERSION"));
112 assert_eq!(report.payload_schema, crate::release::PAYLOAD_SCHEMA);
113 assert!(!report.artifacts.is_empty());
114 assert_eq!(report.payload_sha256, aggregate(&report.artifacts));
115 }
116
117 #[test]
119 fn the_aggregate_covers_paths_and_order() {
120 let mut artifacts = report().artifacts;
121 let original = aggregate(&artifacts);
122 artifacts.reverse();
123 assert_ne!(original, aggregate(&artifacts));
124 }
125}