this repo has no description
at main 2.1 kB view raw
1use color_eyre::Result; 2use serde::de::Deserializer; 3use serde::Deserialize; 4use std::{ 5 borrow::Cow, 6 collections::BTreeMap, 7 path::{Path, PathBuf}, 8 process::Command, 9}; 10 11#[derive(Deserialize, Debug)] 12pub struct DiffRoot { 13 pub packages: BTreeMap<String, DiffPackage>, 14 15 #[expect(dead_code)] 16 pub schema: String, 17} 18 19#[derive(Deserialize, Debug)] 20#[serde(rename_all = "camelCase")] 21pub struct DiffPackage { 22 pub size_delta: i64, 23 24 #[serde(deserialize_with = "version_deserializer")] 25 pub versions_before: Vec<String>, 26 27 #[serde(deserialize_with = "version_deserializer")] 28 pub versions_after: Vec<String>, 29} 30 31fn version_deserializer<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error> 32where 33 D: Deserializer<'de>, 34{ 35 let vec = Vec::<Cow<'de, str>>::deserialize(deserializer)?; 36 Ok(vec 37 .into_iter() 38 .map(|s| { 39 if s.is_empty() { 40 "<none>".to_string() 41 } else { 42 s.into_owned() 43 } 44 }) 45 .collect()) 46} 47 48impl DiffRoot { 49 pub fn new(lix_path: Option<PathBuf>, before: &Path, after: &Path) -> Result<DiffRoot> { 50 let lix_exe; 51 if let Some(lix_path) = lix_path { 52 lix_exe = lix_path; 53 } else { 54 lix_exe = "nix".into(); 55 } 56 57 let raw_diff = Command::new(lix_exe) 58 .args(["store", "diff-closures", "--json"]) 59 .args([before, after]) 60 .output()?; 61 62 if !raw_diff.status.success() { 63 eprintln!("{}", String::from_utf8_lossy(&raw_diff.stderr)); 64 std::process::exit(1); 65 } 66 67 let stdout = raw_diff.stdout; 68 if stdout.is_empty() { 69 eprintln!("No differences found."); 70 std::process::exit(0); 71 } 72 73 // Assume nix output is valid UTF-8 74 let diff_out = String::from_utf8(stdout)?; 75 76 let diff_root = serde_json::from_str::<DiffRoot>(&diff_out).map_err(|e| { 77 eprintln!("Failed to parse JSON: {e}"); 78 std::process::exit(1); 79 })?; 80 81 Ok(diff_root) 82 } 83}