use anyhow::{Context, Result};
use std::{os::unix::net::UnixStream, path::Path, sync::mpsc, thread};
use crate::{PackerProgress, image::LayerBlob, overlay::merge_layers_into_streaming};
pub fn write_dir_with_progress(
receiver: mpsc::Receiver<Result<LayerBlob>>,
total_layers: usize,
output_dir: &Path,
progress_tx: Option<std::sync::mpsc::SyncSender<PackerProgress>>,
) -> Result<()> {
std::fs::create_dir_all(output_dir)
.with_context(|| format!("creating output directory {}", output_dir.display()))?;
let (reader, writer) = UnixStream::pair().context("creating socket pair for tar pipe")?;
let merge_handle = thread::spawn(move || {
merge_layers_into_streaming(receiver, total_layers, writer, progress_tx.as_ref())
});
let unpack_result = {
let mut archive = tar::Archive::new(reader);
archive.set_preserve_permissions(true);
archive.set_preserve_mtime(true);
archive
.unpack(output_dir)
.context("unpacking merged tar into output directory")
};
let merge_result = merge_handle.join().expect("merge thread panicked");
merge_result.and(unpack_result)
}
pub fn write_dir(
receiver: mpsc::Receiver<Result<LayerBlob>>,
total_layers: usize,
output_dir: &Path,
) -> Result<()> {
write_dir_with_progress(receiver, total_layers, output_dir, None)
}