posthog_cli/utils/
files.rs1use anyhow::{Context, Result};
2use sha2::Digest;
3use std::path::PathBuf;
4
5use crate::sourcemaps::content::SourceMapContent;
6
7pub struct SourceFile<T: SourceContent> {
8 pub path: PathBuf,
9 pub content: T,
10}
11
12impl<T: SourceContent> SourceFile<T> {
13 pub fn new(path: PathBuf, content: T) -> Self {
14 SourceFile { path, content }
15 }
16
17 pub fn load(path: &PathBuf) -> Result<Self> {
18 let content = std::fs::read(path)?;
19 Ok(SourceFile::new(path.clone(), T::parse(content)?))
20 }
21
22 pub fn save(&self, dest: Option<PathBuf>) -> Result<()> {
24 let final_path = dest.unwrap_or(self.path.clone());
25 std::fs::write(&final_path, &self.content.serialize()?)?;
26 Ok(())
27 }
28}
29
30pub trait SourceContent {
31 fn parse(content: Vec<u8>) -> Result<Self>
32 where
33 Self: Sized;
34
35 fn serialize(&self) -> Result<Vec<u8>>;
36}
37
38impl SourceContent for String {
39 fn parse(content: Vec<u8>) -> Result<Self> {
40 Ok(String::from_utf8(content)?)
41 }
42
43 fn serialize(&self) -> Result<Vec<u8>> {
44 Ok(self.clone().into_bytes())
45 }
46}
47
48impl SourceContent for SourceMapContent {
49 fn parse(content: Vec<u8>) -> Result<Self> {
50 Ok(serde_json::from_slice(&content)?)
51 }
52
53 fn serialize(&self) -> Result<Vec<u8>> {
54 Ok(serde_json::to_vec(self)?)
55 }
56}
57
58impl SourceContent for Vec<u8> {
59 fn parse(content: Vec<u8>) -> Result<Self> {
60 Ok(content)
61 }
62
63 fn serialize(&self) -> Result<Vec<u8>> {
64 Ok(self.clone())
65 }
66}
67
68pub fn delete_files(paths: Vec<PathBuf>) -> Result<()> {
69 for path in paths {
71 if path.exists() {
72 std::fs::remove_file(&path)
73 .context(format!("Failed to delete file: {}", path.display()))?;
74 }
75 }
76 Ok(())
77}
78
79pub fn content_hash<Iter, Item: AsRef<[u8]>>(upload_data: Iter) -> String
82where
83 Iter: IntoIterator<Item = Item>,
84{
85 let mut hasher = sha2::Sha512::new();
86 for data in upload_data {
87 hasher.update(data.as_ref());
88 }
89 format!("{:x}", hasher.finalize())
90}