mod.rs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. //! # 配置解析器
  2. //!
  3. //! 用于解析配置文件,生成任务列表
  4. //!
  5. //! 您需要指定一个配置文件目录,解析器会自动解析该目录下的所有配置文件。
  6. //! 软件包的配置文件格式为toml
  7. //!
  8. //! ## 简介
  9. //!
  10. //! 在每个配置文件中,您需要指定软件包的名称、版本、描述、任务类型、依赖、构建配置和安装配置。DADK会根据这些信息生成任务列表。
  11. //!
  12. //! ## 配置文件格式
  13. //!
  14. //! ```toml
  15. //! name = "test_git"
  16. //! version = "0.1.0"
  17. //! description = ""
  18. //! build_once = true
  19. //! install_once = true
  20. //! target_arch = ["x86_64"]
  21. //!
  22. //! [task_type]
  23. //! type = "build_from_source"
  24. //! source = "git"
  25. //! source_path = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/test_git.git"
  26. //! revison = "01cdc56863"
  27. //! branch = "test"
  28. //!
  29. //! [build]
  30. //! build-command = "make instal"
  31. //!
  32. //! [install]
  33. //! in_dragonos_path = "/bin"
  34. //!
  35. //! [clean]
  36. //! clean-command = "make clean"
  37. //!
  38. //! [depends]
  39. //! depend1 = "0.1.1"
  40. //! depend2 = "0.1.2"
  41. //!
  42. //! [envs]
  43. //! PATH = "/usr/bin"
  44. //! LD_LIBRARY_PATH = "/usr/lib"
  45. use std::{
  46. fmt::Debug,
  47. fs::{DirEntry, ReadDir},
  48. path::PathBuf,
  49. };
  50. use self::task::DADKTask;
  51. use anyhow::Result;
  52. use dadk_config::user::UserConfigFile;
  53. use log::{debug, error, info};
  54. pub mod task;
  55. pub mod task_log;
  56. /// # 配置解析器
  57. ///
  58. /// 用于解析配置文件,生成任务列表
  59. #[derive(Debug)]
  60. pub struct Parser {
  61. /// 配置文件目录
  62. config_dir: PathBuf,
  63. /// 扫描到的配置文件列表
  64. config_files: Vec<PathBuf>,
  65. }
  66. pub struct ParserError {
  67. pub config_file: Option<PathBuf>,
  68. pub error: InnerParserError,
  69. }
  70. impl Debug for ParserError {
  71. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  72. match &self.error {
  73. InnerParserError::IoError(e) => {
  74. if let Some(config_file) = &self.config_file {
  75. write!(
  76. f,
  77. "IO Error while parsing config file {}: {}",
  78. config_file.display(),
  79. e
  80. )
  81. } else {
  82. write!(f, "IO Error while parsing config files: {}", e)
  83. }
  84. }
  85. InnerParserError::TomlError(e) => {
  86. if let Some(config_file) = &self.config_file {
  87. write!(
  88. f,
  89. "Toml Error while parsing config file {}: {}",
  90. config_file.display(),
  91. e
  92. )
  93. } else {
  94. write!(f, "Toml Error while parsing config file: {}", e)
  95. }
  96. }
  97. InnerParserError::TaskError(e) => {
  98. if let Some(config_file) = &self.config_file {
  99. write!(
  100. f,
  101. "Error while parsing config file {}: {}",
  102. config_file.display(),
  103. e
  104. )
  105. } else {
  106. write!(f, "Error while parsing config file: {}", e)
  107. }
  108. }
  109. }
  110. }
  111. }
  112. #[derive(Debug)]
  113. pub enum InnerParserError {
  114. IoError(std::io::Error),
  115. TomlError(toml::de::Error),
  116. TaskError(String),
  117. }
  118. impl Parser {
  119. pub fn new(config_dir: PathBuf) -> Self {
  120. Self {
  121. config_dir,
  122. config_files: Vec::new(),
  123. }
  124. }
  125. /// # 解析所有配置文件,生成任务列表
  126. ///
  127. /// ## 参数
  128. ///
  129. /// * `config_dir` - 配置文件所在目录
  130. ///
  131. /// ## 返回值
  132. ///
  133. /// * `Ok(Vec<(PathBuf, DADKTask)>)` - 任务列表(配置文件路径, 任务)
  134. /// * `Err(ParserError)` - 解析错误
  135. pub fn parse(&mut self) -> Result<Vec<(PathBuf, DADKTask)>> {
  136. self.scan_config_files()?;
  137. info!("Found {} config files", self.config_files.len());
  138. let r: Result<Vec<(PathBuf, DADKTask)>> = self.gen_tasks();
  139. if r.is_err() {
  140. error!("Error while parsing config files: {:?}", r);
  141. }
  142. return r;
  143. }
  144. /// # 扫描配置文件目录,找到所有配置文件
  145. fn scan_config_files(&mut self) -> Result<()> {
  146. info!("Scanning config files in {}", self.config_dir.display());
  147. let mut dir_queue: Vec<PathBuf> = Vec::new();
  148. // 将config目录加入队列
  149. dir_queue.push(self.config_dir.clone());
  150. while !dir_queue.is_empty() {
  151. // 扫描目录,找到所有*.dadk文件
  152. let dir = dir_queue.pop().unwrap();
  153. let entries: ReadDir = std::fs::read_dir(&dir)?;
  154. for entry in entries {
  155. let entry: DirEntry = entry?;
  156. let path: PathBuf = entry.path();
  157. if path.is_dir() {
  158. dir_queue.push(path);
  159. } else if path.is_file() {
  160. let extension: Option<&std::ffi::OsStr> = path.extension();
  161. if extension.is_none() {
  162. continue;
  163. }
  164. let extension: &std::ffi::OsStr = extension.unwrap();
  165. if extension.to_ascii_lowercase() != "toml" {
  166. continue;
  167. }
  168. // 找到一个配置文件, 加入列表
  169. self.config_files.push(path);
  170. }
  171. }
  172. }
  173. return Ok(());
  174. }
  175. /// # 解析所有配置文件,生成任务列表
  176. ///
  177. /// 一旦发生错误,立即返回
  178. ///
  179. /// ## 返回值
  180. ///
  181. /// * `Ok(Vec<DADKTask>)` - 任务列表
  182. /// * `Err(ParserError)` - 解析错误
  183. fn gen_tasks(&self) -> Result<Vec<(PathBuf, DADKTask)>> {
  184. let mut result_vec = Vec::new();
  185. for config_file in &self.config_files {
  186. let task: DADKTask = self.parse_config_file(config_file)?;
  187. debug!("Parsed config file {}: {:?}", config_file.display(), task);
  188. result_vec.push((config_file.clone(), task));
  189. }
  190. return Ok(result_vec);
  191. }
  192. /// # 解析单个配置文件,生成任务
  193. ///
  194. /// ## 参数
  195. ///
  196. /// * `config_file` - 配置文件路径
  197. ///
  198. /// ## 返回值
  199. ///
  200. /// * `Ok(DADKTask)` - 生成好的任务
  201. /// * `Err(ParserError)` - 解析错误
  202. pub(super) fn parse_config_file(&self, config_file: &PathBuf) -> Result<DADKTask> {
  203. log::trace!("Parsing config file {}", config_file.display());
  204. // 从toml文件中解析出DADKTask
  205. let mut task: DADKTask = Self::parse_toml_file(config_file)?;
  206. // 去除字符串中的空白字符
  207. task.trim();
  208. // 校验DADKTask的参数是否合法
  209. task.validate()?;
  210. return Ok(task);
  211. }
  212. /// 解析toml文件,生成DADKTask
  213. pub fn parse_toml_file(config_file: &PathBuf) -> Result<DADKTask> {
  214. let dadk_user_config = UserConfigFile::load(config_file)?;
  215. DADKTask::try_from(dadk_user_config)
  216. }
  217. }