1pub mod errors;
4pub mod hash;
5pub mod internal;
6pub mod utils;
7mod zstdelta;
8mod delta;
9
10pub mod test_utils {
12 use reqwest::Client;
13 use ring::digest::{Context, SHA256};
14 use std::collections::HashMap;
15 use std::env;
16 use std::fs::File;
17 use std::io::copy;
18 use std::path::PathBuf;
19 use tokio::io::{AsyncReadExt, AsyncSeekExt};
20 use tokio::sync::OnceCell;
21
22 static FILES_READY: OnceCell<HashMap<String, PathBuf>> = OnceCell::const_new();
23
24 pub async fn setup_lfs_file() -> HashMap<String, PathBuf> {
25 FILES_READY
26 .get_or_init(|| async {
27 let files_to_download = vec![(
28 "git-2d187177923cd618a75da6c6db45bb89d92bd504.pack",
29 "0d1f01ac02481427e83ba6c110c7a3a75edd4264c5af8014d12d6800699c8409",
30 )];
31
32 let mut map = HashMap::new();
33 let mut base_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
34 base_dir.pop();
35 base_dir.push("tests/data/packs");
36 for (name, sha256) in files_to_download {
37 let file_path = base_dir.join(name);
38 download_lfs_file_if_not_exist(name, &file_path, sha256).await;
39
40 map.insert(name.to_string(), file_path);
41 }
42
43 map
44 })
45 .await
46 .clone()
47 }
48
49 async fn calculate_checksum(file: &mut tokio::fs::File, checksum: &mut Context) {
50 file.seek(tokio::io::SeekFrom::Start(0)).await.unwrap();
51 let mut buf = [0u8; 8192];
52 loop {
53 let n = file.read(&mut buf).await.unwrap();
54 if n == 0 {
55 break;
56 }
57 checksum.update(&buf[..n]);
58 }
59 }
60
61 async fn download_file(
62 url: &str,
63 output_path: &PathBuf,
64 ) -> Result<(), Box<dyn std::error::Error>> {
65 let response = Client::new().get(url).send().await?;
66 let mut file = File::create(output_path)?;
67 let content = response.bytes().await?;
68 let mut content = content.as_ref();
69 copy(&mut content, &mut file)?;
70 Ok(())
71 }
72
73 async fn check_file_hash(output_path: &PathBuf, sha256: &str) -> bool {
74 if output_path.exists() {
75 let mut ring_context = Context::new(&SHA256);
76 let mut file = tokio::fs::File::open(output_path).await.unwrap();
77 calculate_checksum(&mut file, &mut ring_context).await;
78 let checksum = hex::encode(ring_context.finish().as_ref());
79 checksum == sha256
80 } else {
81 false
82 }
83 }
84
85 async fn download_lfs_file_if_not_exist(file_name: &str, output_path: &PathBuf, sha256: &str) {
86 let url = format!(
87 "https://file.gitmega.com/packs/{file_name}",
88 );
91 if !check_file_hash(output_path, sha256).await {
92 download_file(&url, output_path).await.unwrap();
93 }
94 }
95}