xref: /DADK/src/executor/cache.rs (revision 8f388bf05339108880442da40968e6669c65ea6f)
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)]
79 pub struct CacheDir {
80     entity: Rc<SchedEntity>,
81     pub path: PathBuf,
82     pub cache_type: CacheDirType,
83 }
84 
85 #[derive(Debug, Clone, Copy)]
86 pub enum CacheDirType {
87     Build,
88     Source,
89 }
90 
91 impl CacheDir {
92     pub fn new(entity: Rc<SchedEntity>, cache_type: CacheDirType) -> Result<Self, ExecutorError> {
93         let task = entity.task();
94         let path = Self::get_path(task, cache_type);
95 
96         let result = Self {
97             entity,
98             path,
99             cache_type,
100         };
101 
102         result.create()?;
103 
104         return Ok(result);
105     }
106 
107     fn get_path(task: &DADKTask, cache_type: CacheDirType) -> PathBuf {
108         let cache_root = CACHE_ROOT.get();
109         let name_version = task.name_version();
110         let cache_dir = match cache_type {
111             CacheDirType::Build => {
112                 format!("{}/build/{}", cache_root.to_str().unwrap(), name_version)
113             }
114             CacheDirType::Source => {
115                 format!("{}/source/{}", cache_root.to_str().unwrap(), name_version)
116             }
117         };
118 
119         return PathBuf::from(cache_dir);
120     }
121 
122     pub fn build_dir(entity: Rc<SchedEntity>) -> Result<PathBuf, ExecutorError> {
123         return Ok(Self::new(entity, CacheDirType::Build)?.path);
124     }
125 
126     pub fn source_dir(entity: Rc<SchedEntity>) -> Result<PathBuf, ExecutorError> {
127         return Ok(Self::new(entity, CacheDirType::Source)?.path);
128     }
129 
130     pub fn build_dir_env_key(entity: Rc<SchedEntity>) -> Result<String, ExecutorError> {
131         let name_version_env = entity.task().name_version_env();
132         return Ok(format!("DADK_BUILD_CACHE_DIR_{}", name_version_env));
133     }
134 
135     pub fn source_dir_env_key(entity: Rc<SchedEntity>) -> Result<String, ExecutorError> {
136         let name_version_env = entity.task().name_version_env();
137         return Ok(format!("DADK_SOURCE_CACHE_DIR_{}", name_version_env));
138     }
139 
140     pub fn need_source_cache(entity: &Rc<SchedEntity>) -> bool {
141         let task_type = &entity.task().task_type;
142 
143         if let TaskType::BuildFromSource(cs) = task_type {
144             match cs {
145                 CodeSource::Git(_) | CodeSource::Archive(_) => {
146                     return true;
147                 }
148                 CodeSource::Local(_) => {
149                     return false;
150                 }
151             }
152         } else if let TaskType::InstallFromPrebuilt(ps) = task_type {
153             match ps {
154                 crate::parser::task::PrebuiltSource::Archive(_) => return true,
155                 crate::parser::task::PrebuiltSource::Local(_) => return false,
156             }
157         }
158 
159         unimplemented!("Not fully implemented task type: {:?}", task_type);
160     }
161 
162     fn create(&self) -> Result<(), ExecutorError> {
163         if !self.path.exists() {
164             info!("Cache dir not exists, create it: {:?}", self.path);
165             std::fs::create_dir_all(&self.path).map_err(|e| ExecutorError::IoError(e))?;
166             debug!("Cache dir: [{:?}] created.", self.path);
167         } else if !self.path.is_dir() {
168             // 如果路径类别不是目录,则报错
169             return Err(ExecutorError::IoError(std::io::Error::new(
170                 std::io::ErrorKind::NotADirectory,
171                 format!("Cache dir is not a directory: {:?}", self.path),
172             )));
173         }
174 
175         return Ok(());
176     }
177 }
178