use crate::error::CobbleResult;
use async_zip::read::seek::ZipFileReader;
use std::path::{Path, PathBuf};
use time::OffsetDateTime;
use tokio::fs::{remove_file, File};
#[cfg_attr(doc_cfg, doc(cfg(feature = "log-files")))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Debug)]
pub struct LogFile {
pub name: String,
pub path: PathBuf,
pub _type: LogFileType,
#[cfg_attr(feature = "serde", serde(with = "time::serde::rfc3339::option"))]
pub modified: Option<OffsetDateTime>,
}
impl LogFile {
#[instrument(
name = "remove_log_file",
level = "trace",
skip_all,
fields(
path = %self.path.to_string_lossy(),
)
)]
pub async fn remove(self) -> CobbleResult<()> {
remove_file(&self.path).await?;
Ok(())
}
#[instrument(
name = "extract_log_file",
level = "trace",
skip_all,
fields(
source = %self.path.to_string_lossy(),
target = %target.as_ref().to_string_lossy(),
)
)]
pub async fn unpack(&self, target: impl AsRef<Path> + Send) -> CobbleResult<()> {
match self._type {
LogFileType::Plain => {
trace!("Copying file to target location");
tokio::fs::copy(&self.path, target).await?;
}
LogFileType::GzipCompressed => {
trace!("Extracting log file to target location");
let mut file = File::open(&self.path).await?;
let mut archive = ZipFileReader::new(&mut file).await?;
let entry_reader = archive.entry_reader(0).await?;
let mut out_file = File::create(target).await?;
entry_reader.copy_to_end_crc(&mut out_file, 64000).await?;
}
}
Ok(())
}
}
#[cfg_attr(doc_cfg, doc(cfg(feature = "log-files")))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[derive(Clone, Copy, Debug)]
pub enum LogFileType {
Plain,
GzipCompressed,
}