1use crate::error::Result;
4use serde::{Deserialize, Serialize};
5use std::path::Path;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct InstallReceipt {
10 pub homebrew_version: String,
11 pub installed_as_dependency: bool,
12 pub installed_on_request: bool,
13 pub install_time: u64,
14 pub source: ReceiptSource,
15 #[serde(default)]
16 pub runtime_dependencies: Vec<RuntimeDependency>,
17 #[serde(default)]
18 pub poured_from_bottle: bool,
19 #[serde(default)]
20 pub changed_files: Vec<String>,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct ReceiptSource {
25 pub tap: String,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 pub path: Option<String>,
28}
29
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct RuntimeDependency {
32 pub full_name: String,
33 pub version: String,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub revision: Option<u32>,
36}
37
38impl InstallReceipt {
39 pub fn new_bottle(
41 tap: &str,
42 on_request: bool,
43 dependencies: Vec<RuntimeDependency>,
44 ) -> Self {
45 let now = std::time::SystemTime::now()
46 .duration_since(std::time::UNIX_EPOCH)
47 .unwrap()
48 .as_secs();
49
50 Self {
51 homebrew_version: "4.0.0".to_string(), installed_as_dependency: !on_request,
53 installed_on_request: on_request,
54 install_time: now,
55 source: ReceiptSource {
56 tap: tap.to_string(),
57 path: None,
58 },
59 runtime_dependencies: dependencies,
60 poured_from_bottle: true,
61 changed_files: Vec::new(),
62 }
63 }
64
65 pub fn new_source(
67 tap: &str,
68 on_request: bool,
69 dependencies: Vec<RuntimeDependency>,
70 ) -> Self {
71 let now = std::time::SystemTime::now()
72 .duration_since(std::time::UNIX_EPOCH)
73 .unwrap()
74 .as_secs();
75
76 Self {
77 homebrew_version: "4.0.0".to_string(),
78 installed_as_dependency: !on_request,
79 installed_on_request: on_request,
80 install_time: now,
81 source: ReceiptSource {
82 tap: tap.to_string(),
83 path: None,
84 },
85 runtime_dependencies: dependencies,
86 poured_from_bottle: false, changed_files: Vec::new(),
88 }
89 }
90}
91
92pub fn write_receipt(install_path: impl AsRef<Path>, receipt: &InstallReceipt) -> Result<()> {
94 let path = install_path.as_ref().join("INSTALL_RECEIPT.json");
95 let json = serde_json::to_string_pretty(receipt)?;
96 std::fs::write(&path, json)?;
97 Ok(())
98}
99
100pub fn read_receipt(install_path: impl AsRef<Path>) -> Result<InstallReceipt> {
102 let path = install_path.as_ref().join("INSTALL_RECEIPT.json");
103 let json = std::fs::read_to_string(&path)?;
104 let receipt: InstallReceipt = serde_json::from_str(&json)?;
105 Ok(receipt)
106}