xref: /DADK/dadk-user/src/parser/task.rs (revision d2ade6ef037f43d0342021730a0d8b3af7bc36c1)
173779f3dSLoGin use std::path::PathBuf;
273779f3dSLoGin 
373779f3dSLoGin use crate::executor::source::{ArchiveSource, GitSource, LocalSource};
4*d2ade6efSJomo use dadk_config::{
5*d2ade6efSJomo     common::{
6*d2ade6efSJomo         target_arch::TargetArch,
7*d2ade6efSJomo         task::{
8*d2ade6efSJomo             BuildConfig, CleanConfig, Dependency, InstallConfig, Source, TaskEnv, TaskSource,
9*d2ade6efSJomo             TaskSourceType,
105129c63bSJomo         },
11*d2ade6efSJomo     },
12*d2ade6efSJomo     user::UserConfigFile,
135129c63bSJomo };
14*d2ade6efSJomo use serde::{Deserialize, Serialize};
15*d2ade6efSJomo 
16*d2ade6efSJomo use anyhow::{Ok, Result};
175129c63bSJomo 
1873779f3dSLoGin // 对于生成的包名和版本号,需要进行替换的字符。
1973779f3dSLoGin pub static NAME_VERSION_REPLACE_TABLE: [(&str, &str); 6] = [
2073779f3dSLoGin     (" ", "_"),
2173779f3dSLoGin     ("\t", "_"),
2273779f3dSLoGin     ("-", "_"),
2373779f3dSLoGin     (".", "_"),
2473779f3dSLoGin     ("+", "_"),
2573779f3dSLoGin     ("*", "_"),
2673779f3dSLoGin ];
2773779f3dSLoGin 
2873779f3dSLoGin #[derive(Debug, Clone, Serialize, Deserialize)]
2973779f3dSLoGin pub struct DADKTask {
3073779f3dSLoGin     /// 包名
3173779f3dSLoGin     pub name: String,
3273779f3dSLoGin     /// 版本
3373779f3dSLoGin     pub version: String,
3473779f3dSLoGin     /// 包的描述
3573779f3dSLoGin     pub description: String,
3673779f3dSLoGin     /// 任务类型
3773779f3dSLoGin     pub task_type: TaskType,
3873779f3dSLoGin     /// 依赖的包
3973779f3dSLoGin     pub depends: Vec<Dependency>,
4073779f3dSLoGin     /// 构建配置
4173779f3dSLoGin     pub build: BuildConfig,
4273779f3dSLoGin     /// 安装配置
4373779f3dSLoGin     pub install: InstallConfig,
4473779f3dSLoGin     /// 清理配置
4573779f3dSLoGin     pub clean: CleanConfig,
4673779f3dSLoGin     /// 环境变量
4773779f3dSLoGin     pub envs: Option<Vec<TaskEnv>>,
4873779f3dSLoGin 
4973779f3dSLoGin     /// (可选) 是否只构建一次,如果为true,DADK会在构建成功后,将构建结果缓存起来,下次构建时,直接使用缓存的构建结果。
5073779f3dSLoGin     #[serde(default)]
5173779f3dSLoGin     pub build_once: bool,
5273779f3dSLoGin 
5373779f3dSLoGin     /// (可选) 是否只安装一次,如果为true,DADK会在安装成功后,不再重复安装。
new( name: String, version: String, description: String, rust_target: Option<String>, task_type: TaskType, depends: Vec<Dependency>, build: BuildConfig, install: InstallConfig, clean: CleanConfig, envs: Option<Vec<TaskEnv>>, build_once: bool, install_once: bool, target_arch: Option<Vec<TargetArch>>, ) -> Self5473779f3dSLoGin     #[serde(default)]
5573779f3dSLoGin     pub install_once: bool,
5673779f3dSLoGin 
5773779f3dSLoGin     #[serde(default = "DADKTask::default_target_arch_vec")]
5873779f3dSLoGin     pub target_arch: Vec<TargetArch>,
5973779f3dSLoGin }
6073779f3dSLoGin 
6173779f3dSLoGin impl DADKTask {
6273779f3dSLoGin     #[allow(dead_code)]
6373779f3dSLoGin     pub fn new(
6473779f3dSLoGin         name: String,
6573779f3dSLoGin         version: String,
6673779f3dSLoGin         description: String,
6773779f3dSLoGin         task_type: TaskType,
6873779f3dSLoGin         depends: Vec<Dependency>,
6973779f3dSLoGin         build: BuildConfig,
7073779f3dSLoGin         install: InstallConfig,
7173779f3dSLoGin         clean: CleanConfig,
7273779f3dSLoGin         envs: Option<Vec<TaskEnv>>,
7373779f3dSLoGin         build_once: bool,
7473779f3dSLoGin         install_once: bool,
7573779f3dSLoGin         target_arch: Option<Vec<TargetArch>>,
7673779f3dSLoGin     ) -> Self {
7773779f3dSLoGin         Self {
7873779f3dSLoGin             name,
7973779f3dSLoGin             version,
8073779f3dSLoGin             description,
8173779f3dSLoGin             task_type,
8273779f3dSLoGin             depends,
8373779f3dSLoGin             build,
8473779f3dSLoGin             install,
8573779f3dSLoGin             clean,
8673779f3dSLoGin             envs,
8773779f3dSLoGin             build_once,
8873779f3dSLoGin             install_once,
8973779f3dSLoGin             target_arch: target_arch.unwrap_or_else(Self::default_target_arch_vec),
9073779f3dSLoGin         }
9173779f3dSLoGin     }
9273779f3dSLoGin 
9373779f3dSLoGin     /// 默认的目标处理器架构
9473779f3dSLoGin     ///
9573779f3dSLoGin     /// 从环境变量`ARCH`中获取,如果没有设置,则默认为`x86_64`
9673779f3dSLoGin     pub fn default_target_arch() -> TargetArch {
9773779f3dSLoGin         let s = std::env::var("ARCH").unwrap_or("x86_64".to_string());
9873779f3dSLoGin         return TargetArch::try_from(s.as_str()).unwrap();
9973779f3dSLoGin     }
10073779f3dSLoGin 
10173779f3dSLoGin     fn default_target_arch_vec() -> Vec<TargetArch> {
10273779f3dSLoGin         vec![Self::default_target_arch()]
10373779f3dSLoGin     }
10473779f3dSLoGin 
105*d2ade6efSJomo     pub fn validate(&mut self) -> Result<()> {
10673779f3dSLoGin         if self.name.is_empty() {
107*d2ade6efSJomo             return Err(anyhow::Error::msg("name is empty"));
10873779f3dSLoGin         }
10973779f3dSLoGin         if self.version.is_empty() {
110*d2ade6efSJomo             return Err(anyhow::Error::msg("version is empty"));
11173779f3dSLoGin         }
11273779f3dSLoGin         self.task_type.validate()?;
11373779f3dSLoGin         self.build.validate()?;
11473779f3dSLoGin         self.validate_build_type()?;
11573779f3dSLoGin         self.install.validate()?;
11673779f3dSLoGin         self.clean.validate()?;
11773779f3dSLoGin         self.validate_depends()?;
11873779f3dSLoGin         self.validate_envs()?;
11973779f3dSLoGin         self.validate_target_arch()?;
12073779f3dSLoGin 
12173779f3dSLoGin         return Ok(());
12273779f3dSLoGin     }
12373779f3dSLoGin 
12473779f3dSLoGin     pub fn trim(&mut self) {
12573779f3dSLoGin         self.name = self.name.trim().to_string();
12673779f3dSLoGin         self.version = self.version.trim().to_string();
12773779f3dSLoGin         self.description = self.description.trim().to_string();
12873779f3dSLoGin         self.task_type.trim();
12973779f3dSLoGin         self.build.trim();
13073779f3dSLoGin         self.install.trim();
13173779f3dSLoGin         self.clean.trim();
13273779f3dSLoGin         self.trim_depends();
13373779f3dSLoGin         self.trim_envs();
13473779f3dSLoGin     }
13573779f3dSLoGin 
136*d2ade6efSJomo     fn validate_depends(&self) -> Result<()> {
13773779f3dSLoGin         for depend in &self.depends {
13873779f3dSLoGin             depend.validate()?;
13973779f3dSLoGin         }
14073779f3dSLoGin         return Ok(());
14173779f3dSLoGin     }
14273779f3dSLoGin 
14373779f3dSLoGin     fn trim_depends(&mut self) {
14473779f3dSLoGin         for depend in &mut self.depends {
14573779f3dSLoGin             depend.trim();
14673779f3dSLoGin         }
14773779f3dSLoGin     }
14873779f3dSLoGin 
149*d2ade6efSJomo     fn validate_envs(&self) -> Result<()> {
15073779f3dSLoGin         if let Some(envs) = &self.envs {
15173779f3dSLoGin             for env in envs {
15273779f3dSLoGin                 env.validate()?;
15373779f3dSLoGin             }
15473779f3dSLoGin         }
15573779f3dSLoGin         return Ok(());
15673779f3dSLoGin     }
15773779f3dSLoGin 
158*d2ade6efSJomo     fn validate_target_arch(&self) -> Result<()> {
15973779f3dSLoGin         if self.target_arch.is_empty() {
160*d2ade6efSJomo             return Err(anyhow::Error::msg("target_arch is empty"));
16173779f3dSLoGin         }
16273779f3dSLoGin         return Ok(());
16373779f3dSLoGin     }
16473779f3dSLoGin 
16573779f3dSLoGin     fn trim_envs(&mut self) {
16673779f3dSLoGin         if let Some(envs) = &mut self.envs {
16773779f3dSLoGin             for env in envs {
16873779f3dSLoGin                 env.trim();
16973779f3dSLoGin             }
17073779f3dSLoGin         }
17173779f3dSLoGin     }
17273779f3dSLoGin 
17373779f3dSLoGin     /// 验证任务类型与构建配置是否匹配
174*d2ade6efSJomo     fn validate_build_type(&self) -> Result<()> {
17573779f3dSLoGin         match &self.task_type {
17673779f3dSLoGin             TaskType::BuildFromSource(_) => {
17773779f3dSLoGin                 if self.build.build_command.is_none() {
178*d2ade6efSJomo                     return Err(anyhow::Error::msg("build command is empty"));
17973779f3dSLoGin                 }
18073779f3dSLoGin             }
18173779f3dSLoGin             TaskType::InstallFromPrebuilt(_) => {
18273779f3dSLoGin                 if self.build.build_command.is_some() {
183*d2ade6efSJomo                     return Err(anyhow::Error::msg(
184*d2ade6efSJomo                         "build command should be empty when install from prebuilt",
185*d2ade6efSJomo                     ));
18673779f3dSLoGin                 }
18773779f3dSLoGin             }
18873779f3dSLoGin         }
18973779f3dSLoGin         return Ok(());
19073779f3dSLoGin     }
19173779f3dSLoGin 
19273779f3dSLoGin     pub fn name_version(&self) -> String {
19373779f3dSLoGin         let mut name_version = format!("{}-{}", self.name, self.version);
19473779f3dSLoGin         for (src, dst) in &NAME_VERSION_REPLACE_TABLE {
19573779f3dSLoGin             name_version = name_version.replace(src, dst);
19673779f3dSLoGin         }
19773779f3dSLoGin         return name_version;
19873779f3dSLoGin     }
19973779f3dSLoGin 
20073779f3dSLoGin     pub fn name_version_env(&self) -> String {
20173779f3dSLoGin         return Self::name_version_uppercase(&self.name, &self.version);
20273779f3dSLoGin     }
20373779f3dSLoGin 
20473779f3dSLoGin     pub fn name_version_uppercase(name: &str, version: &str) -> String {
20573779f3dSLoGin         let mut name_version = format!("{}-{}", name, version).to_ascii_uppercase();
20673779f3dSLoGin         for (src, dst) in &NAME_VERSION_REPLACE_TABLE {
20773779f3dSLoGin             name_version = name_version.replace(src, dst);
20873779f3dSLoGin         }
20973779f3dSLoGin         return name_version;
21073779f3dSLoGin     }
21173779f3dSLoGin 
21273779f3dSLoGin     /// # 获取源码目录
21373779f3dSLoGin     ///
21473779f3dSLoGin     /// 如果从本地路径构建,则返回本地路径。否则返回None。
21573779f3dSLoGin     pub fn source_path(&self) -> Option<PathBuf> {
21673779f3dSLoGin         match &self.task_type {
21773779f3dSLoGin             TaskType::BuildFromSource(cs) => match cs {
21873779f3dSLoGin                 CodeSource::Local(lc) => {
21973779f3dSLoGin                     return Some(lc.path().clone());
22073779f3dSLoGin                 }
22173779f3dSLoGin                 _ => {
22273779f3dSLoGin                     return None;
22373779f3dSLoGin                 }
22473779f3dSLoGin             },
22573779f3dSLoGin             TaskType::InstallFromPrebuilt(ps) => match ps {
22673779f3dSLoGin                 PrebuiltSource::Local(lc) => {
22773779f3dSLoGin                     return Some(lc.path().clone());
22873779f3dSLoGin                 }
22973779f3dSLoGin                 _ => {
23073779f3dSLoGin                     return None;
23173779f3dSLoGin                 }
23273779f3dSLoGin             },
23373779f3dSLoGin         }
23473779f3dSLoGin     }
23573779f3dSLoGin }
23673779f3dSLoGin 
237*d2ade6efSJomo impl TryFrom<UserConfigFile> for DADKTask {
238*d2ade6efSJomo     type Error = anyhow::Error;
2395129c63bSJomo 
240*d2ade6efSJomo     fn try_from(user_config: UserConfigFile) -> Result<Self> {
241*d2ade6efSJomo         Ok(DADKTask {
new(build_command: Option<String>) -> Self242*d2ade6efSJomo             name: user_config.name,
243*d2ade6efSJomo             version: user_config.version,
244*d2ade6efSJomo             description: user_config.description,
245*d2ade6efSJomo             task_type: TaskType::try_from(user_config.task_source)?,
246*d2ade6efSJomo             depends: user_config.depends,
247*d2ade6efSJomo             build: user_config.build,
248*d2ade6efSJomo             install: user_config.install,
249*d2ade6efSJomo             clean: user_config.clean,
250*d2ade6efSJomo             envs: Some(user_config.envs),
251*d2ade6efSJomo             build_once: user_config.build_once,
252*d2ade6efSJomo             install_once: user_config.install_once,
253*d2ade6efSJomo             target_arch: user_config.target_arch,
254*d2ade6efSJomo         })
25573779f3dSLoGin     }
25673779f3dSLoGin }
25773779f3dSLoGin 
25873779f3dSLoGin /// # 任务类型
25973779f3dSLoGin #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
26073779f3dSLoGin pub enum TaskType {
26173779f3dSLoGin     /// 从源码构建
26273779f3dSLoGin     BuildFromSource(CodeSource),
26373779f3dSLoGin     /// 从预编译包安装
26473779f3dSLoGin     InstallFromPrebuilt(PrebuiltSource),
26573779f3dSLoGin }
26673779f3dSLoGin 
26773779f3dSLoGin impl TaskType {
268*d2ade6efSJomo     pub fn validate(&mut self) -> Result<()> {
validate(&self) -> Result<(), String>26973779f3dSLoGin         match self {
27073779f3dSLoGin             TaskType::BuildFromSource(source) => source.validate(),
27173779f3dSLoGin             TaskType::InstallFromPrebuilt(source) => source.validate(),
27273779f3dSLoGin         }
27373779f3dSLoGin     }
27473779f3dSLoGin 
27573779f3dSLoGin     pub fn trim(&mut self) {
27673779f3dSLoGin         match self {
27773779f3dSLoGin             TaskType::BuildFromSource(source) => source.trim(),
27873779f3dSLoGin             TaskType::InstallFromPrebuilt(source) => source.trim(),
trim(&mut self)27973779f3dSLoGin         }
28073779f3dSLoGin     }
28173779f3dSLoGin }
28273779f3dSLoGin 
283*d2ade6efSJomo impl TryFrom<TaskSource> for TaskType {
284*d2ade6efSJomo     type Error = anyhow::Error;
285*d2ade6efSJomo     fn try_from(task_source: TaskSource) -> Result<Self> {
286*d2ade6efSJomo         match task_source.source_type {
287*d2ade6efSJomo             TaskSourceType::BuildFromSource => match task_source.source {
288*d2ade6efSJomo                 Source::Git => Ok(TaskType::BuildFromSource(CodeSource::Git(GitSource::new(
289*d2ade6efSJomo                     task_source.source_path,
290*d2ade6efSJomo                     task_source.branch,
291*d2ade6efSJomo                     task_source.revision,
292*d2ade6efSJomo                 )))),
293*d2ade6efSJomo                 Source::Local => Ok(TaskType::BuildFromSource(CodeSource::Local(
294*d2ade6efSJomo                     LocalSource::new(PathBuf::from(task_source.source_path)),
2955129c63bSJomo                 ))),
296*d2ade6efSJomo                 Source::Archive => Ok(TaskType::BuildFromSource(CodeSource::Archive(
297*d2ade6efSJomo                     ArchiveSource::new(task_source.source_path),
2985129c63bSJomo                 ))),
2995129c63bSJomo             },
300*d2ade6efSJomo             TaskSourceType::InstallFromPrebuilt => match task_source.source {
301*d2ade6efSJomo                 Source::Git => Err(anyhow::Error::msg(
302*d2ade6efSJomo                     "InstallFromPrebuild doesn't support Git",
3035129c63bSJomo                 )),
304*d2ade6efSJomo                 Source::Local => Ok(TaskType::InstallFromPrebuilt(PrebuiltSource::Local(
305*d2ade6efSJomo                     LocalSource::new(PathBuf::from(task_source.source_path)),
3065129c63bSJomo                 ))),
307*d2ade6efSJomo                 Source::Archive => Ok(TaskType::InstallFromPrebuilt(PrebuiltSource::Archive(
308*d2ade6efSJomo                     ArchiveSource::new(task_source.source_path),
309*d2ade6efSJomo                 ))),
3105129c63bSJomo             },
3115129c63bSJomo         }
3125129c63bSJomo     }
3135129c63bSJomo }
3145129c63bSJomo 
new(name: String, version: String) -> Self31573779f3dSLoGin /// # 代码源
31673779f3dSLoGin #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
31773779f3dSLoGin pub enum CodeSource {
31873779f3dSLoGin     /// 从Git仓库获取
31973779f3dSLoGin     Git(GitSource),
32073779f3dSLoGin     /// 从本地目录获取
32173779f3dSLoGin     Local(LocalSource),
32273779f3dSLoGin     /// 从在线压缩包获取
32373779f3dSLoGin     Archive(ArchiveSource),
32473779f3dSLoGin }
32573779f3dSLoGin 
32673779f3dSLoGin impl CodeSource {
327*d2ade6efSJomo     pub fn validate(&mut self) -> Result<()> {
32873779f3dSLoGin         match self {
trim(&mut self)32973779f3dSLoGin             CodeSource::Git(source) => source.validate(),
33073779f3dSLoGin             CodeSource::Local(source) => source.validate(Some(false)),
33173779f3dSLoGin             CodeSource::Archive(source) => source.validate(),
33273779f3dSLoGin         }
33373779f3dSLoGin     }
33473779f3dSLoGin     pub fn trim(&mut self) {
33573779f3dSLoGin         match self {
33673779f3dSLoGin             CodeSource::Git(source) => source.trim(),
33773779f3dSLoGin             CodeSource::Local(source) => source.trim(),
33873779f3dSLoGin             CodeSource::Archive(source) => source.trim(),
33973779f3dSLoGin         }
34073779f3dSLoGin     }
34173779f3dSLoGin }
34273779f3dSLoGin 
34373779f3dSLoGin /// # 预编译包源
34473779f3dSLoGin #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
34573779f3dSLoGin pub enum PrebuiltSource {
34673779f3dSLoGin     /// 从在线压缩包获取
34773779f3dSLoGin     Archive(ArchiveSource),
34873779f3dSLoGin     /// 从本地目录/文件获取
validate(&mut self) -> Result<(), String>34973779f3dSLoGin     Local(LocalSource),
35073779f3dSLoGin }
35173779f3dSLoGin 
35273779f3dSLoGin impl PrebuiltSource {
353*d2ade6efSJomo     pub fn validate(&self) -> Result<()> {
35473779f3dSLoGin         match self {
35573779f3dSLoGin             PrebuiltSource::Archive(source) => source.validate(),
35673779f3dSLoGin             PrebuiltSource::Local(source) => source.validate(None),
35773779f3dSLoGin         }
35873779f3dSLoGin     }
35973779f3dSLoGin 
36073779f3dSLoGin     pub fn trim(&mut self) {
36173779f3dSLoGin         match self {
36273779f3dSLoGin             PrebuiltSource::Archive(source) => source.trim(),
36373779f3dSLoGin             PrebuiltSource::Local(source) => source.trim(),
36473779f3dSLoGin         }
36573779f3dSLoGin     }
36673779f3dSLoGin }
367