use crate::cli::{Format, Metric, TreemapArgs};
use crate::diff::DiffNode;
use crate::model::Meta;
use crate::util::{human_bytes, signed_bytes};
use anyhow::{Context, Result};
use std::cmp::Reverse;
use std::path::{Path, PathBuf};
fn delta_of(n: &DiffNode, m: Metric) -> i64 {
match m {
Metric::Data => n.delta_data(),
Metric::Gzip => n.delta_gzip(),
_ => n.delta_text(),
}
}
fn base_of(n: &DiffNode, m: Metric) -> u64 {
match m {
Metric::Data => n.base_data,
Metric::Gzip => n.base_gzip,
_ => n.base_text,
}
}
fn head_of(n: &DiffNode, m: Metric) -> u64 {
match m {
Metric::Data => n.head_data,
Metric::Gzip => n.head_gzip,
_ => n.head_text,
}
}
pub fn emit(diff: &DiffNode, meta: &Meta, base_path: &Path, args: &TreemapArgs) -> Result<()> {
match args.format {
Format::Table => {
table(diff, base_path, args.metric);
Ok(())
}
Format::Json => {
let text = serde_json::to_string_pretty(diff)?;
match &args.output {
Some(p) => {
std::fs::write(p, text).with_context(|| format!("writing {}", p.display()))?;
eprintln!("cargo-treemap: wrote {}", p.display());
}
None => println!("{text}"),
}
Ok(())
}
Format::Html => {
let html = super::diffhtml::render(diff, meta, base_path, args.metric);
let path = args
.output
.clone()
.unwrap_or_else(|| PathBuf::from("cargo-treemap-diff.html"));
std::fs::write(&path, html).with_context(|| format!("writing {}", path.display()))?;
let abs = std::fs::canonicalize(&path).unwrap_or(path);
eprintln!("cargo-treemap: wrote {}", abs.display());
if args.open {
super::open_in_browser(&abs);
}
Ok(())
}
}
}
fn table(diff: &DiffNode, base_path: &Path, metric: Metric) {
let mut rows: Vec<&DiffNode> = diff.groups.iter().collect();
rows.sort_by_key(|n| Reverse(delta_of(n, metric).abs()));
println!(
"\n Size comparison ({}): {} (base) vs current build\n",
metric.field(),
base_path.display()
);
println!(" {:>11} {:>9} {:>9} crate", "change", "base", "head");
println!(" {}", "-".repeat(52));
let mut unchanged = 0;
for n in &rows {
let d = delta_of(n, metric);
if d == 0 {
unchanged += 1;
continue;
}
println!(
" {:>11} {:>9} {:>9} {}{}",
signed_bytes(d),
human_bytes(base_of(n, metric)),
human_bytes(head_of(n, metric)),
n.label,
tag(n, metric),
);
}
println!(" {}", "-".repeat(52));
println!(
" {:>11} {:>9} {:>9} (total)",
signed_bytes(delta_of(diff, metric)),
human_bytes(base_of(diff, metric)),
human_bytes(head_of(diff, metric)),
);
if unchanged > 0 {
println!("\n {unchanged} crates unchanged");
}
println!();
}
fn tag(n: &DiffNode, m: Metric) -> &'static str {
if base_of(n, m) == 0 {
" (new)"
} else if head_of(n, m) == 0 {
" (removed)"
} else {
""
}
}