use std::time::SystemTime;
use std::time::UNIX_EPOCH;
use super::DiagnosticsError;
use super::DiagnosticsResult;
pub(super) struct ArchiveHeaderBuilder {
path: String,
mode: u32,
timestamp: Option<u64>,
}
impl ArchiveHeaderBuilder {
pub(super) fn new<P: AsRef<str>>(path: P) -> Self {
Self {
path: path.as_ref().to_string(),
mode: 0o644, timestamp: None,
}
}
pub(super) fn build_for_content(self, content: &[u8]) -> DiagnosticsResult<tokio_tar::Header> {
let mut header = tokio_tar::Header::new_gnu();
header.set_path(&self.path).map_err(|e| {
DiagnosticsError::Internal(format!("Failed to set path '{}': {}", self.path, e))
})?;
header.set_size(content.len() as u64);
header.set_mode(self.mode);
let timestamp = self.timestamp.unwrap_or_else(|| {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0)
});
header.set_mtime(timestamp);
header.set_cksum();
Ok(header)
}
}
pub(super) struct ArchiveUtils;
impl ArchiveUtils {
pub(super) async fn add_text_file<W: tokio::io::AsyncWrite + Unpin + Send + Sync>(
tar: &mut tokio_tar::Builder<W>,
path: &str,
content: &str,
) -> DiagnosticsResult<()> {
let content_bytes = content.as_bytes();
let header = ArchiveHeaderBuilder::new(path).build_for_content(content_bytes)?;
tar.append(&header, content_bytes).await.map_err(|e| {
DiagnosticsError::Internal(format!("Failed to add '{}' to archive: {}", path, e))
})
}
}
#[cfg(test)]
mod tests {
use std::io::Cursor;
use futures::StreamExt;
use super::*;
#[tokio::test]
async fn test_add_text_file() {
let buffer = Vec::new();
let cursor = Cursor::new(buffer);
let mut tar = tokio_tar::Builder::new(cursor);
ArchiveUtils::add_text_file(&mut tar, "test.txt", "Hello, World!")
.await
.unwrap();
let archive_bytes = tar.get_ref().get_ref().clone();
tar.finish().await.unwrap();
let cursor = Cursor::new(&archive_bytes);
let mut archive = tokio_tar::Archive::new(cursor);
let mut entries = archive.entries().unwrap();
let entry = entries.next().await.unwrap().unwrap();
assert_eq!(entry.path().unwrap().to_str().unwrap(), "test.txt");
assert_eq!(entry.header().size().unwrap(), 13); }
}