use std::{
env,
fs::{self, File},
ops::{Deref, DerefMut},
path::{Path, PathBuf},
};
use anyhow::anyhow;
use super::consts::GOUP_HOME;
#[derive(Debug, Clone, PartialEq)]
pub struct Dir {
path: PathBuf,
}
impl Dir {
pub fn home_dir() -> Result<PathBuf, anyhow::Error> {
dirs::home_dir().ok_or_else(|| anyhow!("home dir get failed"))
}
pub fn new<P: AsRef<Path>>(p: P) -> Self {
let mut path: PathBuf = p.as_ref().into();
path.push(".goup");
Self { path }
}
pub fn goup_home() -> Result<Self, anyhow::Error> {
env::var(GOUP_HOME)
.ok()
.filter(|s| !s.is_empty())
.map(|s| {
Ok(Self {
path: PathBuf::from(s),
})
})
.unwrap_or_else(|| Self::home_dir().map(Self::new))
}
pub fn join_path<P: AsRef<Path>>(&self, path: P) -> Self {
Self {
path: self.path.join(path),
}
}
pub fn env(&self) -> Self {
self.join_path("env")
}
pub fn current(&self) -> Self {
self.join_path("current")
}
pub fn current_bin(&self) -> Self {
let mut d = self.join_path("current");
d.push("bin");
d
}
pub fn bin(&self) -> Self {
self.join_path("bin")
}
pub fn version<P: AsRef<Path>>(&self, ver: P) -> Self {
self.join_path(ver)
}
pub fn cache(&self) -> Self {
self.join_path("cache")
}
pub fn cache_file<P: AsRef<Path>>(&self, p: P) -> Self {
let mut d = self.join_path("cache");
d.push(p);
d
}
pub fn version_go<P: AsRef<Path>>(&self, ver: P) -> Self {
let mut d = self.join_path(ver);
d.push("go");
d
}
fn version_dot_unpacked_success<P: AsRef<Path>>(&self, ver: P) -> Self {
let mut d = self.join_path(ver);
d.push(".unpacked-success");
d
}
pub fn is_dot_unpacked_success_file_exists<P>(&self, ver: P) -> bool
where
P: AsRef<Path>,
{
self.version_dot_unpacked_success(&ver).exists()
}
pub fn create_dot_unpacked_success_file<P>(&self, ver: P) -> Result<(), anyhow::Error>
where
P: AsRef<Path>,
{
let dot_unpacked_success_file = self.version_dot_unpacked_success(&ver);
let parent = dot_unpacked_success_file.parent();
if let Some(parent) = parent {
fs::create_dir_all(parent)?;
}
File::create(&dot_unpacked_success_file)?;
Ok(())
}
}
impl AsRef<Path> for Dir {
fn as_ref(&self) -> &Path {
&self.path
}
}
impl Deref for Dir {
type Target = PathBuf;
fn deref(&self) -> &Self::Target {
&self.path
}
}
impl DerefMut for Dir {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.path
}
}
impl Default for Dir {
fn default() -> Self {
Self {
path: PathBuf::new(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::ffi::OsStr;
#[test]
fn test_home_dir() {
println!("Dir - home_dir: {:?}", Dir::home_dir());
println!("Dir - from_home_dir: {:?}", Dir::goup_home());
}
#[test]
fn test_dir() {
let home_dir = Path::new("/home/dev");
assert_eq!(Dir::new(home_dir).as_ref(), Path::new("/home/dev/.goup"));
assert_eq!(Dir::new(home_dir).file_name(), Some(OsStr::new(".goup")));
assert_eq!(
Dir::new(home_dir).env().as_ref(),
Path::new("/home/dev/.goup/env")
);
assert_eq!(
Dir::new(home_dir).current().as_ref(),
Path::new("/home/dev/.goup/current")
);
assert_eq!(
Dir::new(home_dir).current_bin().as_ref(),
Path::new("/home/dev/.goup/current/bin")
);
assert_eq!(
Dir::new(home_dir).bin().as_ref(),
Path::new("/home/dev/.goup/bin")
);
assert_eq!(
Dir::new(home_dir).cache().as_ref(),
Path::new("/home/dev/.goup/cache")
);
assert_eq!(
Dir::new(home_dir).cache_file("file").as_ref(),
Path::new("/home/dev/.goup/cache/file")
);
assert_eq!(
Dir::new(home_dir).version("go1.21.2").as_ref(),
Path::new("/home/dev/.goup/go1.21.2")
);
assert_eq!(
Dir::new(home_dir).version_go("go1.21.2").as_ref(),
Path::new("/home/dev/.goup/go1.21.2/go")
);
assert_eq!(
Dir::new(home_dir).version_go("go1.21.2").as_ref(),
Path::new("/home/dev/.goup/go1.21.2/go")
);
assert_eq!(
Dir::new(home_dir).version_go("go1.21.2").as_ref(),
Path::new("/home/dev/.goup/go1.21.2/go")
);
}
#[test]
fn test_dot_unpacked_success_file() -> Result<(), anyhow::Error> {
let tmp_home_dir = tempfile::tempdir()?;
let tmp_goup_home = Dir::new(tmp_home_dir);
println!("{}", tmp_goup_home.display());
assert!(!tmp_goup_home.is_dot_unpacked_success_file_exists("go1.21.2"));
tmp_goup_home.create_dot_unpacked_success_file("go1.21.2")?;
assert!(tmp_goup_home.is_dot_unpacked_success_file_exists("go1.21.2"));
Ok(())
}
}