mod diffhtml;
mod diffout;
mod html;
mod json;
mod table;
use crate::apiusage::DepValue;
use crate::cli::{Format, TreemapArgs};
use crate::diff::DiffNode;
use crate::model::{Meta, Node};
use crate::parity::CrateRow;
use anyhow::{Context, Result};
use std::path::{Path, PathBuf};
pub fn emit_diff(diff: &DiffNode, meta: &Meta, base_path: &Path, args: &TreemapArgs) -> Result<()> {
diffout::emit(diff, meta, base_path, args)
}
pub(crate) fn safe_json<T: serde::Serialize + ?Sized>(v: &T) -> String {
serde_json::to_string(v)
.unwrap_or_else(|_| "null".to_string())
.replace("</", "<\\/")
}
pub fn emit(
root: &Node,
meta: &Meta,
deps: &[DepValue],
crates: &[CrateRow],
args: &TreemapArgs,
) -> Result<()> {
match args.format {
Format::Table => {
table::render(root, meta, deps, crates, args.metric);
Ok(())
}
Format::Json => {
let text = json::render(root, meta, deps, crates)?;
match &args.output {
Some(path) => {
std::fs::write(path, text)
.with_context(|| format!("writing {}", path.display()))?;
eprintln!("cargo-treemap: wrote {}", path.display());
}
None => println!("{text}"),
}
Ok(())
}
Format::Html => {
let html = html::render(root, meta, deps, crates, args.metric);
let path = args
.output
.clone()
.unwrap_or_else(|| PathBuf::from("cargo-treemap.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 {
open_in_browser(&abs);
} else {
eprintln!("cargo-treemap: open it with `--open`, or load the file in a browser");
}
Ok(())
}
}
}
fn open_in_browser(path: &std::path::Path) {
#[cfg(target_os = "macos")]
let cmd = "open";
#[cfg(target_os = "windows")]
let cmd = "explorer";
#[cfg(all(not(target_os = "macos"), not(target_os = "windows")))]
let cmd = "xdg-open";
if let Err(e) = std::process::Command::new(cmd).arg(path).spawn() {
eprintln!("cargo-treemap: could not open browser ({e}); open {} manually", path.display());
}
}