#![allow(dead_code)]
#![allow(clippy::disallowed_methods)]
#![allow(clippy::disallowed_types)]
use std::{
fs::{self, File, Permissions},
io::{self, Write},
path::{Path, PathBuf},
};
use nix::unistd::{mkdtemp, mkstemp};
fn template(dir: &Path, prefix: &str) -> PathBuf {
dir.join(format!("{prefix}XXXXXX"))
}
pub fn tempfile() -> io::Result<File> {
let (fd, path) = mkstemp(&template(&std::env::temp_dir(), ".tmp"))?;
let _ = fs::remove_file(&path);
Ok(File::from(fd))
}
pub fn tempdir() -> io::Result<TempDir> {
Builder::new().tempdir()
}
pub struct NamedTempFile {
file: File,
path: PathBuf,
}
impl NamedTempFile {
pub fn new() -> io::Result<NamedTempFile> {
let (fd, path) = mkstemp(&template(&std::env::temp_dir(), ".tmp"))?;
Ok(NamedTempFile {
file: File::from(fd),
path,
})
}
pub fn path(&self) -> &Path {
&self.path
}
pub fn as_file(&self) -> &File {
&self.file
}
}
impl Write for NamedTempFile {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.file.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.file.flush()
}
}
impl Drop for NamedTempFile {
fn drop(&mut self) {
let _ = fs::remove_file(&self.path);
}
}
pub struct TempDir {
path: PathBuf,
keep: bool,
}
impl TempDir {
pub fn path(&self) -> &Path {
&self.path
}
pub fn keep(mut self) -> PathBuf {
self.keep = true;
self.path.clone()
}
}
impl Drop for TempDir {
fn drop(&mut self) {
if !self.keep {
let _ = fs::remove_dir_all(&self.path);
}
}
}
#[derive(Default)]
pub struct Builder {
prefix: Option<String>,
permissions: Option<Permissions>,
keep: bool,
}
impl Builder {
pub fn new() -> Builder {
Builder::default()
}
pub fn prefix(mut self, prefix: &str) -> Builder {
self.prefix = Some(prefix.to_owned());
self
}
pub fn permissions(mut self, permissions: Permissions) -> Builder {
self.permissions = Some(permissions);
self
}
pub fn disable_cleanup(mut self, disable: bool) -> Builder {
self.keep = disable;
self
}
pub fn tempdir(self) -> io::Result<TempDir> {
let dir = std::env::temp_dir();
self.make(&dir)
}
pub fn tempdir_in<P: AsRef<Path>>(self, dir: P) -> io::Result<TempDir> {
self.make(dir.as_ref())
}
fn make(self, dir: &Path) -> io::Result<TempDir> {
let prefix = self.prefix.as_deref().unwrap_or(".tmp");
let path = mkdtemp(&template(dir, prefix))?;
if let Some(permissions) = self.permissions {
fs::set_permissions(&path, permissions)?;
}
Ok(TempDir {
path,
keep: self.keep,
})
}
}