git_internal/internal/pack/encode/
output.rs1use std::path::PathBuf;
9
10use chrono::Utc;
11use tokio::{fs::File, io::AsyncWriteExt as TokioAsyncWriteExt, sync::mpsc};
12
13use super::PackEncoder;
14use crate::{
15 errors::GitError,
16 internal::{
17 metadata::{EntryMeta, MetaAttached},
18 pack::entry::Entry,
19 },
20};
21
22pub async fn encode_and_output_to_files(
33 raw_entries_rx: mpsc::Receiver<MetaAttached<Entry, EntryMeta>>,
34 object_number: usize,
35 output_dir: PathBuf,
36 window_size: usize,
37) -> Result<(), GitError> {
38 let (pack_tx, mut pack_rx) = mpsc::channel(1024);
39 let (idx_tx, mut idx_rx) = mpsc::channel(1024);
40 let mut pack_encoder = PackEncoder::new_with_idx(object_number, window_size, pack_tx, idx_tx);
41
42 let now = Utc::now();
44 let timestamp = now.format("%Y%m%d%H%M%S%.3f").to_string();
45 let tmp_path = output_dir.join(format!("{}objects.pack.tmp", timestamp));
46 let mut pack_file = File::create(&tmp_path).await?;
47
48 let pack_writer = tokio::spawn(async move {
50 while let Some(chunk) = pack_rx.recv().await {
51 TokioAsyncWriteExt::write_all(&mut pack_file, &chunk).await?;
52 }
53 TokioAsyncWriteExt::flush(&mut pack_file).await?;
54 Ok::<(), GitError>(())
55 });
56
57 pack_encoder.encode(raw_entries_rx).await?;
58
59 let pack_write_result = pack_writer
61 .await
62 .map_err(|e| GitError::PackEncodeError(format!("pack writer task join error: {e}")))?;
63 pack_write_result?;
64
65 let final_pack_name =
66 output_dir.join(format!("pack-{}.pack", pack_encoder.final_hash.unwrap()));
67 let final_idx_name = output_dir.join(format!("pack-{}.idx", pack_encoder.final_hash.unwrap()));
68 tokio::fs::rename(tmp_path, &final_pack_name).await?;
69
70 let mut idx_file = File::create(&final_idx_name).await?;
71 let idx_writer = tokio::spawn(async move {
72 while let Some(chunk) = idx_rx.recv().await {
73 TokioAsyncWriteExt::write_all(&mut idx_file, &chunk).await?;
74 }
75 TokioAsyncWriteExt::flush(&mut idx_file).await?;
76 Ok::<(), GitError>(())
77 });
78
79 pack_encoder.encode_idx_file().await?;
81
82 let idx_write_result = idx_writer
83 .await
84 .map_err(|e| GitError::PackEncodeError(format!("idx writer task join error: {e}")))?;
85 idx_write_result?;
86
87 Ok(())
88}