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