cache.rs 6.5 KB

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