use crate::errors::Error;
use anyhow::Context;
use std::path::{Path, PathBuf};
pub(crate) trait ResolvePath {
fn resolve_path(&self) -> anyhow::Result<PathBuf>;
}
impl ResolvePath for Path {
fn resolve_path(&self) -> anyhow::Result<PathBuf> {
self.to_path_buf().resolve_path()
}
}
impl ResolvePath for PathBuf {
fn resolve_path(&self) -> anyhow::Result<PathBuf> {
if !&self.exists() {
let path = Path::new(env!("HOME")).join(self);
return path
.canonicalize()
.with_context(|| format!("Failed to canonicalize {}", path.display()));
}
Ok(self.to_path_buf())
}
}
pub(crate) trait StripPrefix {
fn strip_prefix(&self, prefix: &str) -> anyhow::Result<PathBuf>;
}
impl StripPrefix for PathBuf {
fn strip_prefix(&self, prefix: &str) -> anyhow::Result<PathBuf> {
match Path::strip_prefix(self, prefix) {
Ok(path) => Ok(path.to_path_buf()),
Err(err) => {
let err = Error::StripPrefix {
prefix: String::from("/"),
path: self.display().to_string(),
err,
};
Err(err.into())
}
}
}
}
impl StripPrefix for Path {
fn strip_prefix(&self, prefix: &str) -> anyhow::Result<PathBuf> {
self.to_path_buf().strip_prefix(prefix)
}
}
pub(crate) trait MakeDirs {
fn make_all_dirs(&self) -> anyhow::Result<()>;
}
impl MakeDirs for Path {
fn make_all_dirs(&self) -> anyhow::Result<()> {
match std::fs::create_dir_all(self) {
Ok(_) => Ok(()),
Err(err) => {
let err = Error::MakeDir {
path: self.display().to_string(),
err,
};
Err(err.into())
}
}
}
}
impl MakeDirs for PathBuf {
fn make_all_dirs(&self) -> anyhow::Result<()> {
self.as_path().make_all_dirs()
}
}
pub(crate) trait RemoveDirs {
fn remove_all_dirs(&self) -> anyhow::Result<()>;
}
impl RemoveDirs for Path {
fn remove_all_dirs(&self) -> anyhow::Result<()> {
match std::fs::remove_dir_all(self) {
Ok(_) => Ok(()),
Err(err) => {
let err = Error::RemoveDir {
path: self.display().to_string(),
err,
};
Err(err.into())
}
}
}
}
impl RemoveDirs for PathBuf {
fn remove_all_dirs(&self) -> anyhow::Result<()> {
self.as_path().remove_all_dirs()
}
}
pub(crate) trait Metadata {
fn get_metadata(&self) -> anyhow::Result<std::fs::Metadata>;
fn get_modified(&self) -> anyhow::Result<std::time::SystemTime>;
}
impl Metadata for Path {
fn get_metadata(&self) -> anyhow::Result<std::fs::Metadata> {
match self.metadata() {
Ok(metadata) => Ok(metadata),
Err(_) => {
let err = Error::Metadata(self.display().to_string());
Err(err.into())
}
}
}
fn get_modified(&self) -> anyhow::Result<std::time::SystemTime> {
match self.get_metadata()?.modified() {
Ok(modified) => Ok(modified),
Err(_) => {
let err = Error::ModifiedTime(self.display().to_string());
Err(err.into())
}
}
}
}
impl Metadata for PathBuf {
fn get_metadata(&self) -> anyhow::Result<std::fs::Metadata> {
self.as_path().get_metadata()
}
fn get_modified(&self) -> anyhow::Result<std::time::SystemTime> {
self.as_path().get_modified()
}
}
#[cfg(test)]
mod tests {}