use std::ffi;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use std::result;
use anyhow::Result;
pub struct TempPath {
path: Option<PathBuf>,
}
impl TempPath {
pub fn new(original_path: &Path) -> result::Result<Self, PathBuf> {
let mut path = original_path.parent().unwrap().to_path_buf();
let mut file_name = ffi::OsString::from("~");
file_name.push(original_path.file_name().unwrap());
path.push(file_name);
if path.exists() {
Err(path)
} else {
Ok(Self::new_unchecked(path))
}
}
pub fn new_force(original_path: &Path) -> Result<Self> {
match Self::new(original_path) {
Ok(temp) => Ok(temp),
Err(path) => {
nuke_path(&path)?;
Ok(Self::new_unchecked(path))
}
}
}
pub fn new_unchecked(path: PathBuf) -> Self {
Self { path: Some(path) }
}
pub fn path(&self) -> &Path {
self.path.as_ref().unwrap()
}
pub fn rename(mut self, new_path: &Path) -> io::Result<()> {
if let Err(err) = nuke_path(new_path) {
if err.kind() != io::ErrorKind::NotFound {
return Err(err);
}
};
if let Some(path) = &self.path {
fs::rename(path, new_path)?;
self.path = None;
}
Ok(())
}
}
impl Drop for TempPath {
fn drop(&mut self) {
if let Some(path) = &self.path {
nuke_path(path).ok();
}
}
}
fn nuke_path(path: &Path) -> io::Result<()> {
if path.is_dir() {
fs::remove_dir_all(path)
} else {
fs::remove_file(path)
}
}