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