xref: /DADK/src/executor/cache.rs (revision 5eecb314569f6288fb23abaac59f55a942a096ec)
1 use std::{path::PathBuf, rc::Rc};
2 
3 use log::{debug, info};
4 
5 use crate::{
6     parser::task::{CodeSource, DADKTask, TaskType},
7     scheduler::SchedEntity,
8     utils::lazy_init::Lazy,
9 };
10 
11 use super::ExecutorError;
12 
13 pub static CACHE_ROOT: Lazy<PathBuf> = Lazy::new();
14 
15 /// # 初始化缓存根目录
16 ///
17 /// ## 参数
18 ///
19 /// - `path` 缓存根目录的路径
20 pub fn cache_root_init(path: Option<PathBuf>) -> Result<(), ExecutorError> {
21     let cache_root: String;
22     if path.is_none() {
23         // 查询环境变量,是否有设置缓存根目录
24         let env = std::env::var("DADK_CACHE_ROOT");
25         if env.is_ok() {
26             cache_root = env.unwrap();
27         } else {
28             // 如果没有设置环境变量,则使用默认值
29             // 默认值为当前目录下的.cache目录
30             let cwd = std::env::current_dir().map_err(|e| ExecutorError::IoError(e))?;
31             let cwd = cwd.to_str();
32 
33             if cwd.is_none() {
34                 return Err(ExecutorError::IoError(std::io::Error::new(
35                     std::io::ErrorKind::Other,
36                     "Current dir is not a valid unicode string",
37                 )));
38             }
39             let cwd = cwd.unwrap();
40 
41             cache_root = format!("{}/.cache", cwd);
42         }
43     } else {
44         // 如果有设置缓存根目录,则使用设置的值
45         let path = path.unwrap();
46         let x = path
47             .to_str()
48             .ok_or(ExecutorError::IoError(std::io::Error::new(
49                 std::io::ErrorKind::Other,
50                 "Cache root dir is not a valid unicode string",
51             )))?;
52         cache_root = x.to_string();
53     }
54 
55     let cache_root = PathBuf::from(cache_root);
56 
57     // 如果缓存根目录不存在,则创建
58     if !cache_root.exists() {
59         info!("Cache root dir not exists, create it: {:?}", cache_root);
60         std::fs::create_dir_all(&cache_root).map_err(|e| ExecutorError::IoError(e))?;
61     } else if !cache_root.is_dir() {
62         // 如果缓存根目录不是目录,则报错
63         return Err(ExecutorError::IoError(std::io::Error::new(
64             std::io::ErrorKind::NotADirectory,
65             format!("Cache root dir is not a directory: {:?}", cache_root),
66         )));
67     }
68 
69     // 初始化缓存根目录
70     CACHE_ROOT.init(cache_root);
71 
72     // 设置环境变量
73     std::env::set_var("DADK_CACHE_ROOT", CACHE_ROOT.get().to_str().unwrap());
74     info!("Cache root dir: {:?}", CACHE_ROOT.get());
75     return Ok(());
76 }
77 
78 #[derive(Debug, Clone)]
79 pub struct CacheDir {
80     #[allow(dead_code)]
81     entity: Rc<SchedEntity>,
82     pub path: PathBuf,
83     pub cache_type: CacheDirType,
84 }
85 
86 #[derive(Debug, Clone, Copy)]
87 pub enum CacheDirType {
88     Build,
89     Source,
90 }
91 
92 impl CacheDir {
93     pub fn new(entity: Rc<SchedEntity>, cache_type: CacheDirType) -> Result<Self, ExecutorError> {
94         let task = entity.task();
95         let path = Self::get_path(task, cache_type);
96 
97         let result = Self {
98             entity,
99             path,
100             cache_type,
101         };
102 
103         result.create()?;
104 
105         return Ok(result);
106     }
107 
108     fn get_path(task: &DADKTask, cache_type: CacheDirType) -> PathBuf {
109         let cache_root = CACHE_ROOT.get();
110         let name_version = task.name_version();
111         let cache_dir = match cache_type {
112             CacheDirType::Build => {
113                 format!("{}/build/{}", cache_root.to_str().unwrap(), name_version)
114             }
115             CacheDirType::Source => {
116                 format!("{}/source/{}", cache_root.to_str().unwrap(), name_version)
117             }
118         };
119 
120         return PathBuf::from(cache_dir);
121     }
122 
123     pub fn build_dir(entity: Rc<SchedEntity>) -> Result<PathBuf, ExecutorError> {
124         return Ok(Self::new(entity, CacheDirType::Build)?.path);
125     }
126 
127     pub fn source_dir(entity: Rc<SchedEntity>) -> Result<PathBuf, ExecutorError> {
128         return Ok(Self::new(entity, CacheDirType::Source)?.path);
129     }
130 
131     pub fn build_dir_env_key(entity: &Rc<SchedEntity>) -> Result<String, ExecutorError> {
132         let name_version_env = entity.task().name_version_env();
133         return Ok(format!("DADK_BUILD_CACHE_DIR_{}", name_version_env));
134     }
135 
136     pub fn source_dir_env_key(entity: &Rc<SchedEntity>) -> Result<String, ExecutorError> {
137         let name_version_env = entity.task().name_version_env();
138         return Ok(format!("DADK_SOURCE_CACHE_DIR_{}", name_version_env));
139     }
140 
141     pub fn need_source_cache(entity: &Rc<SchedEntity>) -> bool {
142         let task_type = &entity.task().task_type;
143 
144         if let TaskType::BuildFromSource(cs) = task_type {
145             match cs {
146                 CodeSource::Git(_) | CodeSource::Archive(_) => {
147                     return true;
148                 }
149                 CodeSource::Local(_) => {
150                     return false;
151                 }
152             }
153         } else if let TaskType::InstallFromPrebuilt(ps) = task_type {
154             match ps {
155                 crate::parser::task::PrebuiltSource::Archive(_) => return true,
156                 crate::parser::task::PrebuiltSource::Local(_) => return false,
157             }
158         }
159 
160         unimplemented!("Not fully implemented task type: {:?}", task_type);
161     }
162 
163     pub fn create(&self) -> Result<(), ExecutorError> {
164         if !self.path.exists() {
165             info!("Cache dir not exists, create it: {:?}", self.path);
166             std::fs::create_dir_all(&self.path).map_err(|e| ExecutorError::IoError(e))?;
167             debug!("Cache dir: [{:?}] created.", self.path);
168         } else if !self.path.is_dir() {
169             // 如果路径类别不是目录,则报错
170             return Err(ExecutorError::IoError(std::io::Error::new(
171                 std::io::ErrorKind::NotADirectory,
172                 format!("Cache dir is not a directory: {:?}", self.path),
173             )));
174         }
175 
176         return Ok(());
177     }
178 
179     /// 判断缓存目录是否为空
180     pub fn is_empty(&self) -> Result<bool, ExecutorError> {
181         let x = self
182             .path
183             .read_dir()
184             .map_err(|e| ExecutorError::IoError(e))?;
185         for _ in x {
186             return Ok(false);
187         }
188 
189         return Ok(true);
190     }
191 }
192