2023-11-10 00:20:59 +00:00
|
|
|
use std::{
|
|
|
|
ops::Deref,
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
sync::Arc,
|
|
|
|
};
|
2023-12-23 03:01:19 +00:00
|
|
|
|
2021-10-23 19:14:12 +00:00
|
|
|
use uuid::Uuid;
|
|
|
|
|
2023-12-23 17:58:20 +00:00
|
|
|
use crate::process::Extras;
|
|
|
|
|
2023-10-07 00:42:24 +00:00
|
|
|
pub(crate) type ArcTmpDir = Arc<TmpDir>;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub(crate) struct TmpDir {
|
2023-10-07 16:36:49 +00:00
|
|
|
path: Option<PathBuf>,
|
2023-10-07 00:42:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl TmpDir {
|
2023-11-24 17:48:45 +00:00
|
|
|
pub(crate) async fn init<P: AsRef<Path>>(path: P) -> std::io::Result<Arc<Self>> {
|
2023-12-23 17:58:20 +00:00
|
|
|
let path = path.as_ref().join(Uuid::now_v7().to_string());
|
2023-10-07 00:42:24 +00:00
|
|
|
tokio::fs::create_dir(&path).await?;
|
2023-10-07 16:36:49 +00:00
|
|
|
Ok(Arc::new(TmpDir { path: Some(path) }))
|
2023-10-07 00:42:24 +00:00
|
|
|
}
|
|
|
|
|
2023-12-23 17:58:20 +00:00
|
|
|
fn build_tmp_file(&self, ext: Option<&str>) -> PathBuf {
|
2023-10-07 00:42:24 +00:00
|
|
|
if let Some(ext) = ext {
|
2023-12-23 17:58:20 +00:00
|
|
|
self.path
|
|
|
|
.as_ref()
|
|
|
|
.expect("tmp path exists")
|
|
|
|
.join(format!("{}{}", Uuid::now_v7(), ext))
|
2023-10-07 00:42:24 +00:00
|
|
|
} else {
|
2023-12-23 17:58:20 +00:00
|
|
|
self.path
|
|
|
|
.as_ref()
|
|
|
|
.expect("tmp path exists")
|
|
|
|
.join(Uuid::now_v7().to_string())
|
2023-10-07 00:42:24 +00:00
|
|
|
}
|
|
|
|
}
|
2023-10-07 16:36:49 +00:00
|
|
|
|
2023-11-10 00:20:59 +00:00
|
|
|
pub(crate) fn tmp_file(&self, ext: Option<&str>) -> TmpFile {
|
2023-12-23 17:58:20 +00:00
|
|
|
TmpFile(Some(self.build_tmp_file(ext)))
|
2023-11-10 00:20:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) async fn tmp_folder(&self) -> std::io::Result<TmpFolder> {
|
|
|
|
let path = self.build_tmp_file(None);
|
|
|
|
tokio::fs::create_dir(&path).await?;
|
2023-12-23 17:58:20 +00:00
|
|
|
Ok(TmpFolder(Some(path)))
|
2023-11-10 00:20:59 +00:00
|
|
|
}
|
|
|
|
|
2023-10-07 16:36:49 +00:00
|
|
|
pub(crate) async fn cleanup(self: Arc<Self>) -> std::io::Result<()> {
|
|
|
|
if let Some(path) = Arc::into_inner(self).and_then(|mut this| this.path.take()) {
|
|
|
|
tokio::fs::remove_dir_all(path).await?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2023-10-07 00:42:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for TmpDir {
|
|
|
|
fn drop(&mut self) {
|
2023-12-23 18:10:25 +00:00
|
|
|
if let Some(path) = self.path.take() {
|
|
|
|
tracing::warn!("TmpDir - Blocking remove of {path:?}");
|
2023-10-07 16:36:49 +00:00
|
|
|
std::fs::remove_dir_all(path).expect("Removed directory");
|
|
|
|
}
|
2023-10-07 00:42:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-10 00:20:59 +00:00
|
|
|
#[must_use]
|
2023-12-23 17:58:20 +00:00
|
|
|
pub(crate) struct TmpFolder(Option<PathBuf>);
|
|
|
|
|
|
|
|
impl TmpFolder {
|
|
|
|
pub(crate) async fn cleanup(mut self) -> std::io::Result<()> {
|
|
|
|
self.consume().await
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl Extras for TmpFolder {
|
|
|
|
async fn consume(&mut self) -> std::io::Result<()> {
|
|
|
|
tokio::fs::remove_dir_all(&self).await?;
|
|
|
|
self.0.take();
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
2023-11-10 00:20:59 +00:00
|
|
|
|
|
|
|
impl AsRef<Path> for TmpFolder {
|
|
|
|
fn as_ref(&self) -> &Path {
|
2023-12-23 17:58:20 +00:00
|
|
|
self.0.as_deref().unwrap()
|
2023-11-10 00:20:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Deref for TmpFolder {
|
|
|
|
type Target = Path;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
2023-12-23 17:58:20 +00:00
|
|
|
self.0.as_deref().unwrap()
|
2023-11-10 00:20:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for TmpFolder {
|
|
|
|
fn drop(&mut self) {
|
2023-12-23 17:58:20 +00:00
|
|
|
if let Some(path) = self.0.take() {
|
2023-12-23 18:10:25 +00:00
|
|
|
tracing::warn!("TmpFolder - Blocking remove of directory {path:?}");
|
|
|
|
if let Err(e) = std::fs::remove_dir_all(path) {
|
|
|
|
tracing::error!("Failed removing directory {e}");
|
|
|
|
}
|
2023-12-23 17:58:20 +00:00
|
|
|
}
|
2023-11-10 00:20:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[must_use]
|
2023-12-23 17:58:20 +00:00
|
|
|
pub(crate) struct TmpFile(Option<PathBuf>);
|
|
|
|
|
|
|
|
impl TmpFile {
|
|
|
|
pub(crate) async fn cleanup(mut self) -> std::io::Result<()> {
|
|
|
|
self.consume().await
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl Extras for TmpFile {
|
|
|
|
async fn consume(&mut self) -> std::io::Result<()> {
|
|
|
|
tokio::fs::remove_file(&self).await?;
|
|
|
|
self.0.take();
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
2023-11-10 00:20:59 +00:00
|
|
|
|
|
|
|
impl AsRef<Path> for TmpFile {
|
|
|
|
fn as_ref(&self) -> &Path {
|
2023-12-23 17:58:20 +00:00
|
|
|
self.0.as_deref().unwrap()
|
2023-11-10 00:20:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Deref for TmpFile {
|
|
|
|
type Target = Path;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
2023-12-23 17:58:20 +00:00
|
|
|
self.0.as_deref().unwrap()
|
2023-11-10 00:20:59 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-23 19:14:12 +00:00
|
|
|
|
|
|
|
impl Drop for TmpFile {
|
|
|
|
fn drop(&mut self) {
|
2023-12-23 17:58:20 +00:00
|
|
|
if let Some(path) = self.0.take() {
|
2023-12-23 18:10:25 +00:00
|
|
|
tracing::warn!("TmpFile - Blocking remove of file {path:?}");
|
|
|
|
if let Err(e) = std::fs::remove_file(path) {
|
|
|
|
tracing::error!("Failed removing file {e}");
|
|
|
|
}
|
2023-12-23 17:58:20 +00:00
|
|
|
}
|
2021-10-23 19:14:12 +00:00
|
|
|
}
|
|
|
|
}
|