1use std::{
2 env,
3 fs::{self, File},
4 ops::{Deref, DerefMut},
5 path::{Path, PathBuf},
6};
7
8use anyhow::anyhow;
9
10use super::consts::GOUP_HOME;
11
12#[derive(Debug, Clone, PartialEq)]
14pub struct Dir {
15 path: PathBuf,
16}
17
18impl Dir {
19 pub fn home_dir() -> Result<PathBuf, anyhow::Error> {
21 dirs::home_dir().ok_or_else(|| anyhow!("home dir get failed"))
22 }
23 pub fn new<P: AsRef<Path>>(p: P) -> Self {
25 let mut path: PathBuf = p.as_ref().into();
26 path.push(".goup");
27 Self { path }
28 }
29 pub fn goup_home() -> Result<Self, anyhow::Error> {
31 env::var(GOUP_HOME)
32 .ok()
33 .filter(|s| !s.is_empty())
34 .map(|s| {
35 Ok(Self {
36 path: PathBuf::from(s),
37 })
38 })
39 .unwrap_or_else(|| Self::home_dir().map(Self::new))
40 }
41 pub fn join_path<P: AsRef<Path>>(&self, path: P) -> Self {
43 Self {
44 path: self.path.join(path),
45 }
46 }
47 pub fn env(&self) -> Self {
49 self.join_path("env")
50 }
51 pub fn current(&self) -> Self {
53 self.join_path("current")
54 }
55 pub fn current_bin(&self) -> Self {
57 let mut d = self.join_path("current");
58 d.push("bin");
59 d
60 }
61 pub fn bin(&self) -> Self {
63 self.join_path("bin")
64 }
65 pub fn version<P: AsRef<Path>>(&self, ver: P) -> Self {
67 self.join_path(ver)
68 }
69 pub fn cache(&self) -> Self {
71 self.join_path("cache")
72 }
73 pub fn cache_file<P: AsRef<Path>>(&self, p: P) -> Self {
75 let mut d = self.join_path("cache");
76 d.push(p);
77 d
78 }
79 pub fn version_go<P: AsRef<Path>>(&self, ver: P) -> Self {
81 let mut d = self.join_path(ver);
82 d.push("go");
83 d
84 }
85 fn version_dot_unpacked_success<P: AsRef<Path>>(&self, ver: P) -> Self {
87 let mut d = self.join_path(ver);
88 d.push(".unpacked-success");
89 d
90 }
91 pub fn is_dot_unpacked_success_file_exists<P>(&self, ver: P) -> bool
93 where
94 P: AsRef<Path>,
95 {
96 self.version_dot_unpacked_success(&ver).exists()
97 }
98 pub fn create_dot_unpacked_success_file<P>(&self, ver: P) -> Result<(), anyhow::Error>
100 where
101 P: AsRef<Path>,
102 {
103 let dot_unpacked_success_file = self.version_dot_unpacked_success(&ver);
104 let parent = dot_unpacked_success_file.parent();
105 if let Some(parent) = parent {
106 fs::create_dir_all(parent)?;
107 }
108 File::create(&dot_unpacked_success_file)?;
109 Ok(())
110 }
111}
112
113impl AsRef<Path> for Dir {
114 fn as_ref(&self) -> &Path {
115 &self.path
116 }
117}
118
119impl Deref for Dir {
120 type Target = PathBuf;
121
122 fn deref(&self) -> &Self::Target {
123 &self.path
124 }
125}
126
127impl DerefMut for Dir {
128 fn deref_mut(&mut self) -> &mut Self::Target {
129 &mut self.path
130 }
131}
132
133impl Default for Dir {
134 fn default() -> Self {
135 Self {
136 path: PathBuf::new(),
137 }
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144 use std::ffi::OsStr;
145
146 #[test]
147 fn test_home_dir() {
148 println!("Dir - home_dir: {:?}", Dir::home_dir());
149 println!("Dir - from_home_dir: {:?}", Dir::goup_home());
150 }
151 #[test]
152 fn test_dir() {
153 let home_dir = Path::new("/home/dev");
154
155 assert_eq!(Dir::new(home_dir).as_ref(), Path::new("/home/dev/.goup"));
156 assert_eq!(Dir::new(home_dir).file_name(), Some(OsStr::new(".goup")));
157
158 assert_eq!(
159 Dir::new(home_dir).env().as_ref(),
160 Path::new("/home/dev/.goup/env")
161 );
162 assert_eq!(
163 Dir::new(home_dir).current().as_ref(),
164 Path::new("/home/dev/.goup/current")
165 );
166 assert_eq!(
167 Dir::new(home_dir).current_bin().as_ref(),
168 Path::new("/home/dev/.goup/current/bin")
169 );
170 assert_eq!(
171 Dir::new(home_dir).bin().as_ref(),
172 Path::new("/home/dev/.goup/bin")
173 );
174 assert_eq!(
175 Dir::new(home_dir).cache().as_ref(),
176 Path::new("/home/dev/.goup/cache")
177 );
178 assert_eq!(
179 Dir::new(home_dir).cache_file("file").as_ref(),
180 Path::new("/home/dev/.goup/cache/file")
181 );
182 assert_eq!(
183 Dir::new(home_dir).version("go1.21.2").as_ref(),
184 Path::new("/home/dev/.goup/go1.21.2")
185 );
186 assert_eq!(
187 Dir::new(home_dir).version_go("go1.21.2").as_ref(),
188 Path::new("/home/dev/.goup/go1.21.2/go")
189 );
190 assert_eq!(
191 Dir::new(home_dir).version_go("go1.21.2").as_ref(),
192 Path::new("/home/dev/.goup/go1.21.2/go")
193 );
194 assert_eq!(
195 Dir::new(home_dir).version_go("go1.21.2").as_ref(),
196 Path::new("/home/dev/.goup/go1.21.2/go")
197 );
198 }
199
200 #[test]
201 fn test_dot_unpacked_success_file() -> Result<(), anyhow::Error> {
202 let tmp_home_dir = tempfile::tempdir()?;
203 let tmp_goup_home = Dir::new(tmp_home_dir);
204 println!("{}", tmp_goup_home.display());
205 assert!(!tmp_goup_home.is_dot_unpacked_success_file_exists("go1.21.2"));
206 tmp_goup_home.create_dot_unpacked_success_file("go1.21.2")?;
207 assert!(tmp_goup_home.is_dot_unpacked_success_file_exists("go1.21.2"));
208 Ok(())
209 }
210}