1#[cfg(test)]
7#[path = "types_test.rs"]
8mod types_test;
9
10use crate::legacy;
11use crate::plugin::types::Plugins;
12use ci_info::types::CiInfo;
13use git_info::types::GitInfo;
14use indexmap::{IndexMap, IndexSet};
15use regex::Regex;
16use rust_info::types::RustInfo;
17use std::collections::HashMap;
18
19pub fn get_platform_name() -> String {
21 if cfg!(windows) {
22 "windows".to_string()
23 } else if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
24 "mac".to_string()
25 } else {
26 "linux".to_string()
27 }
28}
29
30fn get_namespaced_task_name(namespace: &str, task: &str) -> String {
31 let mut namespaced_task = String::new();
32
33 if namespace.len() > 0 {
34 namespaced_task.push_str(namespace);
35 namespaced_task.push_str("::");
36 }
37 namespaced_task.push_str(task);
38
39 namespaced_task
40}
41
42fn extend_script_value(
43 current_script_value: Option<ScriptValue>,
44 new_script_value: Option<ScriptValue>,
45) -> Option<ScriptValue> {
46 match current_script_value {
47 Some(ref current_value) => match new_script_value {
48 Some(ref new_value) => match current_value {
49 ScriptValue::Sections(current_sections) => match new_value {
50 ScriptValue::Sections(new_sections) => {
51 let pre = if new_sections.pre.is_some() {
52 new_sections.pre.clone()
53 } else {
54 current_sections.pre.clone()
55 };
56 let main = if new_sections.main.is_some() {
57 new_sections.main.clone()
58 } else {
59 current_sections.main.clone()
60 };
61 let post = if new_sections.post.is_some() {
62 new_sections.post.clone()
63 } else {
64 current_sections.post.clone()
65 };
66
67 Some(ScriptValue::Sections(ScriptSections { pre, main, post }))
68 }
69 _ => current_script_value,
70 },
71 _ => new_script_value,
72 },
73 None => current_script_value,
74 },
75 None => new_script_value,
76 }
77}
78
79#[derive(Debug, Clone)]
80pub struct CliArgs {
82 pub command: String,
84 pub build_file: Option<String>,
86 pub task: String,
88 pub profile: Option<String>,
90 pub log_level: String,
92 pub disable_color: bool,
94 pub completion: Option<String>,
96 pub cwd: Option<String>,
98 pub env: Option<Vec<String>>,
100 pub env_file: Option<String>,
102 pub disable_workspace: bool,
104 pub disable_on_error: bool,
106 pub allow_private: bool,
108 pub skip_init_end_tasks: bool,
110 pub skip_tasks_pattern: Option<String>,
112 pub print_only: bool,
114 pub list_all_steps: bool,
116 pub list_category_steps: Option<String>,
118 pub diff_execution_plan: bool,
120 pub disable_check_for_updates: bool,
122 pub experimental: bool,
124 pub arguments: Option<Vec<String>>,
126 pub output_format: String,
128 pub output_file: Option<String>,
130 pub print_time_summary: bool,
132 pub hide_uninteresting: bool,
134}
135
136impl CliArgs {
137 pub fn new() -> CliArgs {
139 CliArgs {
140 command: "".to_string(),
141 build_file: None,
142 task: "default".to_string(),
143 profile: None,
144 log_level: "info".to_string(),
145 disable_color: false,
146 completion: None,
147 cwd: None,
148 env: None,
149 env_file: None,
150 disable_workspace: false,
151 disable_on_error: false,
152 allow_private: false,
153 skip_init_end_tasks: false,
154 skip_tasks_pattern: None,
155 print_only: false,
156 list_all_steps: false,
157 list_category_steps: None,
158 diff_execution_plan: false,
159 disable_check_for_updates: false,
160 experimental: false,
161 arguments: None,
162 output_format: "default".to_string(),
163 output_file: None,
164 print_time_summary: false,
165 hide_uninteresting: false,
166 }
167 }
168}
169
170#[derive(Debug)]
171pub(crate) struct RunTaskOptions {
172 pub(crate) plugins_enabled: bool,
173}
174
175#[derive(Serialize, Deserialize, Debug, Clone, Default)]
176pub struct Cache {
178 #[serde(skip)]
180 pub file_name: Option<String>,
181 pub last_update_check: Option<u64>,
183}
184
185impl Cache {
186 pub fn new() -> Cache {
188 Default::default()
189 }
190}
191
192#[derive(Serialize, Deserialize, Debug, Clone, Default)]
193pub struct GlobalConfig {
195 #[serde(skip)]
197 pub file_name: Option<String>,
198 pub log_level: Option<String>,
200 pub disable_color: Option<bool>,
202 pub default_task_name: Option<String>,
204 pub update_check_minimum_interval: Option<String>,
206 pub search_project_root: Option<bool>,
208}
209
210impl GlobalConfig {
211 pub fn new() -> GlobalConfig {
213 GlobalConfig {
214 search_project_root: Some(false),
215 ..Default::default()
216 }
217 }
218}
219
220#[derive(Serialize, Deserialize, Debug, Clone, Default)]
221pub struct Workspace {
223 pub members: Option<Vec<String>>,
225 pub exclude: Option<Vec<String>>,
227 pub dependencies: Option<IndexMap<String, CrateDependency>>,
229 pub package: Option<PackageInfo>,
231}
232
233impl Workspace {
234 pub fn new() -> Workspace {
236 Default::default()
237 }
238}
239
240#[derive(Serialize, Deserialize, Debug, Clone, Default)]
241pub struct PackageInfo {
243 pub name: Option<String>,
245 pub version: Option<String>,
247 pub description: Option<String>,
249 pub license: Option<String>,
251 pub documentation: Option<String>,
253 pub homepage: Option<String>,
255 pub repository: Option<String>,
257}
258
259impl PackageInfo {
260 pub fn new() -> PackageInfo {
262 Default::default()
263 }
264}
265
266#[derive(Serialize, Deserialize, Debug, Clone)]
267pub struct CrateDependencyInfo {
269 pub path: Option<String>,
271}
272
273#[derive(Serialize, Deserialize, Debug, Clone)]
274#[serde(untagged)]
275pub enum CrateDependency {
277 Version(String),
279 Info(CrateDependencyInfo),
281}
282
283#[derive(Deserialize, Debug, Clone, Default)]
284pub struct CrateInfo {
286 pub package: Option<PackageInfo>,
288 pub workspace: Option<Workspace>,
290 pub dependencies: Option<IndexMap<String, CrateDependency>>,
292}
293
294impl CrateInfo {
295 pub fn new() -> CrateInfo {
297 Default::default()
298 }
299}
300
301#[derive(Debug, Clone)]
302pub struct EnvInfo {
304 pub rust_info: RustInfo,
306 pub crate_info: CrateInfo,
308 pub git_info: GitInfo,
310 pub ci_info: CiInfo,
312}
313
314#[derive(Debug, Clone)]
315pub struct FlowInfo {
317 pub config: Config,
319 pub task: String,
321 pub env_info: EnvInfo,
323 pub disable_workspace: bool,
325 pub disable_on_error: bool,
327 pub allow_private: bool,
329 pub skip_init_end_tasks: bool,
331 pub skip_tasks_pattern: Option<Regex>,
333 pub cli_arguments: Option<Vec<String>>,
335}
336
337#[derive(Debug, Clone, Default)]
338pub struct FlowState {
340 pub time_summary: Vec<(String, u128)>,
342 pub forced_plugin: Option<String>,
344}
345
346impl FlowState {
347 pub fn new() -> FlowState {
349 Default::default()
350 }
351}
352
353#[derive(Serialize, Deserialize, Debug, Clone)]
354pub struct RustVersionCondition {
356 pub min: Option<String>,
358 pub max: Option<String>,
360 pub equal: Option<String>,
362}
363
364#[derive(Serialize, Deserialize, Debug, Clone)]
365pub struct FilesFilesModifiedCondition {
367 pub input: Vec<String>,
369 pub output: Vec<String>,
371}
372
373#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
374pub enum ConditionType {
376 And,
378 Or,
380 GroupOr,
382}
383
384#[derive(Serialize, Deserialize, Debug, Clone, Default)]
385pub struct TaskCondition {
387 pub condition_type: Option<ConditionType>,
389 pub fail_message: Option<String>,
391 pub profiles: Option<Vec<String>>,
393 pub os: Option<Vec<String>>,
395 pub platforms: Option<Vec<String>>,
397 pub channels: Option<Vec<String>>,
399 pub env_set: Option<Vec<String>>,
401 pub env_not_set: Option<Vec<String>>,
403 pub env: Option<IndexMap<String, String>>,
405 pub env_not: Option<IndexMap<String, String>>,
407 pub env_true: Option<Vec<String>>,
409 pub env_false: Option<Vec<String>>,
411 pub env_contains: Option<IndexMap<String, String>>,
413 pub rust_version: Option<RustVersionCondition>,
415 pub files_exist: Option<Vec<String>>,
417 pub files_not_exist: Option<Vec<String>>,
419 pub files_modified: Option<FilesFilesModifiedCondition>,
421}
422
423impl TaskCondition {
424 pub fn get_condition_type(&self) -> ConditionType {
425 match self.condition_type {
426 Some(ref value) => value.clone(),
427 None => ConditionType::And,
428 }
429 }
430}
431
432#[derive(Serialize, Deserialize, Debug, Clone)]
433pub struct EnvFileInfo {
435 pub path: String,
437 pub base_path: Option<String>,
439 pub profile: Option<String>,
441 pub defaults_only: Option<bool>,
443}
444
445impl EnvFileInfo {
446 pub fn new(path: String) -> EnvFileInfo {
448 EnvFileInfo {
449 path,
450 base_path: None,
451 profile: None,
452 defaults_only: None,
453 }
454 }
455}
456
457#[derive(Serialize, Deserialize, Debug, Clone)]
458#[serde(untagged)]
459pub enum EnvFile {
461 Path(String),
463 Info(EnvFileInfo),
465}
466
467#[derive(Serialize, Deserialize, Debug, Clone)]
468pub struct EnvValueScript {
470 pub script: Vec<String>,
472 pub multi_line: Option<bool>,
474 pub condition: Option<TaskCondition>,
476 pub depends_on: Option<Vec<String>>,
478}
479
480#[derive(Serialize, Deserialize, Debug, Clone)]
481pub struct EnvValueDecode {
483 pub source: String,
485 pub default_value: Option<String>,
487 pub mapping: HashMap<String, String>,
489 pub condition: Option<TaskCondition>,
491}
492
493#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
494pub struct EnvValueUnset {
496 pub unset: bool,
498}
499
500#[derive(Serialize, Deserialize, Debug, Clone)]
501pub struct EnvValueConditioned {
503 pub value: String,
505 pub condition: Option<TaskCondition>,
507}
508
509#[derive(Serialize, Deserialize, Debug, Clone)]
510pub struct EnvValuePathGlob {
512 pub glob: String,
514 pub include_files: Option<bool>,
516 pub include_dirs: Option<bool>,
518 pub ignore_type: Option<String>,
520}
521
522#[derive(Serialize, Deserialize, Debug, Clone)]
523#[serde(untagged)]
524pub enum EnvValue {
526 Value(String),
528 Boolean(bool),
530 Number(isize),
532 List(Vec<String>),
534 Unset(EnvValueUnset),
536 Script(EnvValueScript),
538 Decode(EnvValueDecode),
540 Conditional(EnvValueConditioned),
542 PathGlob(EnvValuePathGlob),
544 Profile(IndexMap<String, EnvValue>),
546}
547
548#[derive(Debug, Serialize, Clone, PartialEq, Eq)]
553#[serde(transparent)]
554pub struct TestArg {
555 pub inner: Vec<String>,
557}
558
559impl std::ops::Deref for TestArg {
560 type Target = Vec<String>;
561 fn deref(&self) -> &Self::Target {
562 &self.inner
563 }
564}
565
566impl std::ops::DerefMut for TestArg {
567 fn deref_mut(&mut self) -> &mut Self::Target {
568 &mut self.inner
569 }
570}
571
572impl<'de> serde::de::Deserialize<'de> for TestArg {
573 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
574 where
575 D: serde::de::Deserializer<'de>,
576 {
577 struct StringVecVisitor;
578 impl<'de> serde::de::Visitor<'de> for StringVecVisitor {
579 type Value = TestArg;
580
581 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
582 formatter.write_str("A string or an array of strings")
583 }
584
585 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
586 where
587 E: serde::de::Error,
588 {
589 Ok(TestArg {
590 inner: vec![s.to_string()],
591 })
592 }
593
594 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
595 where
596 A: serde::de::SeqAccess<'de>,
597 {
598 let mut v = Vec::with_capacity(seq.size_hint().unwrap_or(0));
599 while let Some(s) = seq.next_element()? {
600 v.push(s);
601 }
602
603 Ok(TestArg { inner: v })
604 }
605 }
606 deserializer.deserialize_any(StringVecVisitor)
607 }
608}
609
610#[derive(Serialize, Deserialize, Debug, Clone)]
611pub struct InstallCargoPluginInfo {
613 pub crate_name: Option<String>,
615 pub min_version: Option<String>,
617 pub install_command: Option<String>,
619 pub force: Option<bool>,
621}
622
623impl PartialEq for InstallCargoPluginInfo {
624 fn eq(&self, other: &InstallCargoPluginInfo) -> bool {
625 let mut same = match self.crate_name {
626 Some(ref crate_name) => match other.crate_name {
627 Some(ref other_crate_name) => crate_name == other_crate_name,
628 None => false,
629 },
630 None => match other.crate_name {
631 None => true,
632 _ => false,
633 },
634 };
635 if !same {
636 return false;
637 }
638
639 same = match self.min_version {
640 Some(ref min_version) => match other.min_version {
641 Some(ref other_min_version) => min_version == other_min_version,
642 None => false,
643 },
644 None => match other.min_version {
645 None => true,
646 _ => false,
647 },
648 };
649 if !same {
650 return false;
651 }
652
653 same = match self.install_command {
654 Some(ref install_command) => match other.install_command {
655 Some(ref other_install_command) => install_command == other_install_command,
656 None => false,
657 },
658 None => match other.install_command {
659 None => true,
660 _ => false,
661 },
662 };
663 if !same {
664 return false;
665 }
666
667 match self.force {
668 Some(ref force) => match other.force {
669 Some(ref other_force) => force == other_force,
670 None => false,
671 },
672 None => match other.force {
673 None => true,
674 _ => false,
675 },
676 }
677 }
678}
679
680#[derive(Serialize, Deserialize, Debug, Clone)]
681pub struct InstallCrateInfo {
683 pub crate_name: String,
685 pub rustup_component_name: Option<String>,
687 pub binary: String,
689 pub test_arg: TestArg,
691 pub min_version: Option<String>,
693 pub version: Option<String>,
695 pub install_command: Option<String>,
697 pub force: Option<bool>,
699}
700
701impl PartialEq for InstallCrateInfo {
702 fn eq(&self, other: &InstallCrateInfo) -> bool {
703 if self.crate_name != other.crate_name
704 || self.binary != other.binary
705 || self.test_arg != other.test_arg
706 {
707 return false;
708 }
709
710 let mut same = match self.rustup_component_name {
711 Some(ref rustup_component_name) => match other.rustup_component_name {
712 Some(ref other_rustup_component_name) => {
713 if rustup_component_name == other_rustup_component_name {
714 true
715 } else {
716 false
717 }
718 }
719 None => false,
720 },
721 None => match other.rustup_component_name {
722 None => true,
723 _ => false,
724 },
725 };
726 if !same {
727 return false;
728 }
729
730 same = match self.min_version {
731 Some(ref min_version) => match other.min_version {
732 Some(ref other_min_version) => min_version == other_min_version,
733 None => false,
734 },
735 None => match other.min_version {
736 None => true,
737 _ => false,
738 },
739 };
740 if !same {
741 return false;
742 }
743
744 same = match self.version {
745 Some(ref version) => match other.version {
746 Some(ref other_version) => version == other_version,
747 None => false,
748 },
749 None => match other.version {
750 None => true,
751 _ => false,
752 },
753 };
754 if !same {
755 return false;
756 }
757
758 same = match self.install_command {
759 Some(ref install_command) => match other.install_command {
760 Some(ref other_install_command) => install_command == other_install_command,
761 None => false,
762 },
763 None => match other.install_command {
764 None => true,
765 _ => false,
766 },
767 };
768 if !same {
769 return false;
770 }
771
772 match self.force {
773 Some(ref force) => match other.force {
774 Some(ref other_force) => force == other_force,
775 None => false,
776 },
777 None => match other.force {
778 None => true,
779 _ => false,
780 },
781 }
782 }
783}
784
785#[derive(Serialize, Deserialize, Debug, Clone)]
786pub struct InstallRustupComponentInfo {
788 pub rustup_component_name: String,
790 pub binary: Option<String>,
792 pub test_arg: Option<TestArg>,
794}
795
796impl PartialEq for InstallRustupComponentInfo {
797 fn eq(&self, other: &InstallRustupComponentInfo) -> bool {
798 if self.rustup_component_name != other.rustup_component_name {
799 false
800 } else {
801 let same = match self.binary {
802 Some(ref value) => match other.binary {
803 Some(ref other_value) => value == other_value,
804 None => false,
805 },
806 None => match other.binary {
807 None => true,
808 _ => false,
809 },
810 };
811
812 if same {
813 self.test_arg == other.test_arg
814 } else {
815 false
816 }
817 }
818 }
819}
820
821#[derive(Serialize, Deserialize, Debug, Clone)]
822#[serde(untagged)]
823pub enum InstallCrate {
825 Enabled(bool),
827 Value(String),
829 CrateInfo(InstallCrateInfo),
831 RustupComponentInfo(InstallRustupComponentInfo),
833 CargoPluginInfo(InstallCargoPluginInfo),
835}
836
837impl PartialEq for InstallCrate {
838 fn eq(&self, other: &InstallCrate) -> bool {
839 match self {
840 InstallCrate::Enabled(value) => match other {
841 InstallCrate::Enabled(other_value) => value == other_value,
842 _ => false,
843 },
844 InstallCrate::Value(value) => match other {
845 InstallCrate::Value(other_value) => value == other_value,
846 _ => false,
847 },
848 InstallCrate::CargoPluginInfo(info) => match other {
849 InstallCrate::CargoPluginInfo(other_info) => info == other_info,
850 _ => false,
851 },
852 InstallCrate::CrateInfo(info) => match other {
853 InstallCrate::CrateInfo(other_info) => info == other_info,
854 _ => false,
855 },
856 InstallCrate::RustupComponentInfo(info) => match other {
857 InstallCrate::RustupComponentInfo(other_info) => info == other_info,
858 _ => false,
859 },
860 }
861 }
862}
863
864#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
865#[serde(untagged)]
866pub enum RunTaskName {
868 Single(String),
870 Multiple(Vec<String>),
872}
873
874#[derive(Serialize, Deserialize, Debug, Clone)]
875pub struct RunTaskDetails {
877 pub name: RunTaskName,
879 pub fork: Option<bool>,
881 pub parallel: Option<bool>,
883 pub cleanup_task: Option<String>,
885}
886
887#[derive(Serialize, Deserialize, Debug, Clone)]
888pub struct RunTaskRoutingInfo {
890 pub name: RunTaskName,
892 pub fork: Option<bool>,
894 pub parallel: Option<bool>,
896 pub cleanup_task: Option<String>,
898 pub condition: Option<TaskCondition>,
900 pub condition_script: Option<ConditionScriptValue>,
902 pub condition_script_runner_args: Option<Vec<String>>,
904}
905
906#[derive(Serialize, Deserialize, Debug, Clone)]
907#[serde(untagged)]
908pub enum RunTaskInfo {
910 Name(String),
912 Details(RunTaskDetails),
914 Routing(Vec<RunTaskRoutingInfo>),
916}
917
918#[derive(Serialize, Deserialize, Debug, Clone)]
919pub struct WatchOptions {
921 pub version: Option<String>,
923 pub postpone: Option<bool>,
925 pub ignore_pattern: Option<MaybeArray<String>>,
927 pub no_git_ignore: Option<bool>,
929 pub why: Option<bool>,
931 pub watch: Option<Vec<String>>,
933}
934
935#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
936#[serde(untagged)]
937pub enum MaybeArray<T> {
939 Single(T),
941 Multiple(Vec<T>),
943}
944
945impl PartialEq for WatchOptions {
946 fn eq(&self, other: &WatchOptions) -> bool {
947 let mut same = match self.version {
948 Some(ref value) => match other.version {
949 Some(ref other_value) => value == other_value,
950 None => false,
951 },
952 None => match other.version {
953 None => true,
954 _ => false,
955 },
956 };
957
958 same = if same {
959 match self.postpone {
960 Some(ref value) => match other.postpone {
961 Some(ref other_value) => value == other_value,
962 None => false,
963 },
964 None => match other.postpone {
965 None => true,
966 _ => false,
967 },
968 }
969 } else {
970 false
971 };
972
973 same = if same {
974 match self.ignore_pattern {
975 Some(ref value) => match other.ignore_pattern {
976 Some(ref other_value) => value == other_value,
977 None => false,
978 },
979 None => match other.ignore_pattern {
980 None => true,
981 _ => false,
982 },
983 }
984 } else {
985 false
986 };
987
988 same = if same {
989 match self.no_git_ignore {
990 Some(ref value) => match other.no_git_ignore {
991 Some(ref other_value) => value == other_value,
992 None => false,
993 },
994 None => match other.no_git_ignore {
995 None => true,
996 _ => false,
997 },
998 }
999 } else {
1000 false
1001 };
1002
1003 if same {
1004 match self.watch {
1005 Some(ref value) => match other.watch {
1006 Some(ref other_value) => value == other_value,
1007 None => false,
1008 },
1009 None => match other.watch {
1010 None => true,
1011 _ => false,
1012 },
1013 }
1014 } else {
1015 false
1016 }
1017 }
1018}
1019
1020#[derive(Serialize, Deserialize, Debug, Clone)]
1021#[serde(untagged)]
1022pub enum TaskWatchOptions {
1024 Boolean(bool),
1026 Options(WatchOptions),
1028}
1029
1030impl PartialEq for TaskWatchOptions {
1031 fn eq(&self, other: &TaskWatchOptions) -> bool {
1032 match self {
1033 TaskWatchOptions::Boolean(value) => match other {
1034 TaskWatchOptions::Boolean(other_value) => value == other_value,
1035 _ => false,
1036 },
1037 TaskWatchOptions::Options(info) => match other {
1038 TaskWatchOptions::Options(other_info) => info == other_info,
1039 _ => false,
1040 },
1041 }
1042 }
1043}
1044
1045#[derive(Serialize, Deserialize, Debug, Clone)]
1046#[serde(untagged)]
1047pub enum DeprecationInfo {
1049 Boolean(bool),
1051 Message(String),
1053}
1054
1055impl PartialEq for DeprecationInfo {
1056 fn eq(&self, other: &DeprecationInfo) -> bool {
1057 match self {
1058 DeprecationInfo::Boolean(value) => match other {
1059 DeprecationInfo::Boolean(other_value) => value == other_value,
1060 _ => false,
1061 },
1062 DeprecationInfo::Message(message) => match other {
1063 DeprecationInfo::Message(other_message) => message == other_message,
1064 _ => false,
1065 },
1066 }
1067 }
1068}
1069
1070#[derive(Serialize, Deserialize, Debug, Clone)]
1071pub struct FileScriptValue {
1073 pub file: String,
1075 pub absolute_path: Option<bool>,
1077}
1078
1079#[derive(Serialize, Deserialize, Debug, Clone)]
1080pub struct ScriptSections {
1082 pub pre: Option<String>,
1084 pub main: Option<String>,
1086 pub post: Option<String>,
1088}
1089
1090#[derive(Serialize, Deserialize, Debug, Clone)]
1091#[serde(untagged)]
1092pub enum ScriptValue {
1094 SingleLine(String),
1096 Text(Vec<String>),
1098 File(FileScriptValue),
1100 Sections(ScriptSections),
1102}
1103
1104#[derive(Serialize, Deserialize, Debug, Clone)]
1105#[serde(untagged)]
1106pub enum ConditionScriptValue {
1108 SingleLine(String),
1110 Text(Vec<String>),
1112}
1113
1114#[derive(Serialize, Deserialize, Debug, Clone, Default)]
1115pub struct Task {
1117 pub clear: Option<bool>,
1119 pub description: Option<String>,
1121 pub category: Option<String>,
1123 pub disabled: Option<bool>,
1125 pub private: Option<bool>,
1127 pub deprecated: Option<DeprecationInfo>,
1129 pub extend: Option<String>,
1131 pub workspace: Option<bool>,
1133 pub plugin: Option<String>,
1135 pub watch: Option<TaskWatchOptions>,
1137 pub condition: Option<TaskCondition>,
1139 pub condition_script: Option<ConditionScriptValue>,
1141 pub condition_script_runner_args: Option<Vec<String>>,
1143 pub ignore_errors: Option<bool>,
1145 pub force: Option<bool>,
1147 pub env_files: Option<Vec<EnvFile>>,
1149 pub env: Option<IndexMap<String, EnvValue>>,
1151 pub cwd: Option<String>,
1153 pub alias: Option<String>,
1155 pub linux_alias: Option<String>,
1157 pub windows_alias: Option<String>,
1159 pub mac_alias: Option<String>,
1161 pub install_crate: Option<InstallCrate>,
1163 pub install_crate_args: Option<Vec<String>>,
1165 pub install_script: Option<ScriptValue>,
1167 pub command: Option<String>,
1169 pub args: Option<Vec<String>>,
1171 pub script: Option<ScriptValue>,
1173 pub script_runner: Option<String>,
1175 pub script_runner_args: Option<Vec<String>>,
1177 pub script_extension: Option<String>,
1179 pub run_task: Option<RunTaskInfo>,
1181 pub dependencies: Option<Vec<DependencyIdentifier>>,
1183 pub toolchain: Option<ToolchainSpecifier>,
1185 pub linux: Option<PlatformOverrideTask>,
1187 pub windows: Option<PlatformOverrideTask>,
1189 pub mac: Option<PlatformOverrideTask>,
1191}
1192
1193#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
1196#[serde(untagged)]
1197pub enum ToolchainSpecifier {
1198 Simple(String),
1200 Bounded(ToolchainBoundedSpecifier),
1202}
1203
1204impl From<String> for ToolchainSpecifier {
1205 fn from(channel: String) -> Self {
1206 Self::Simple(channel)
1207 }
1208}
1209
1210impl From<&str> for ToolchainSpecifier {
1211 fn from(channel: &str) -> Self {
1212 channel.to_string().into()
1213 }
1214}
1215
1216impl std::fmt::Display for ToolchainSpecifier {
1217 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1218 match self {
1219 Self::Simple(ref channel) => write!(formatter, "{}", channel),
1220 Self::Bounded(ref spec) => write!(formatter, "{}", spec),
1221 }
1222 }
1223}
1224
1225impl ToolchainSpecifier {
1226 pub fn channel(&self) -> &str {
1228 match self {
1229 Self::Simple(ref channel) => &channel,
1230 Self::Bounded(ToolchainBoundedSpecifier { ref channel, .. }) => channel,
1231 }
1232 }
1233
1234 pub fn min_version(&self) -> Option<&str> {
1236 match self {
1237 Self::Simple(_) => None,
1238 Self::Bounded(ToolchainBoundedSpecifier {
1239 ref min_version, ..
1240 }) => Some(min_version),
1241 }
1242 }
1243}
1244
1245#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
1247pub struct ToolchainBoundedSpecifier {
1248 pub channel: String,
1250 pub min_version: String,
1252}
1253
1254impl std::fmt::Display for ToolchainBoundedSpecifier {
1255 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1256 write!(formatter, "{} >= {}", self.channel, self.min_version)
1257 }
1258}
1259
1260#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
1262#[serde(untagged)]
1263pub enum DependencyIdentifier {
1264 Definition(TaskIdentifier),
1266 Name(String),
1268}
1269
1270impl From<&str> for DependencyIdentifier {
1271 fn from(name: &str) -> Self {
1272 DependencyIdentifier::Name(name.to_string())
1273 }
1274}
1275
1276impl DependencyIdentifier {
1277 pub fn name(&self) -> &str {
1279 match self {
1280 DependencyIdentifier::Definition(identifier) => &identifier.name,
1281 DependencyIdentifier::Name(name) => name,
1282 }
1283 }
1284
1285 pub fn with_namespace(self, namespace: &str) -> Self {
1287 match self {
1288 DependencyIdentifier::Definition(mut identifier) => {
1289 identifier.name = get_namespaced_task_name(namespace, &identifier.name);
1290 DependencyIdentifier::Definition(identifier)
1291 }
1292 DependencyIdentifier::Name(name) => {
1293 DependencyIdentifier::Name(get_namespaced_task_name(namespace, &name))
1294 }
1295 }
1296 }
1297}
1298
1299#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
1301pub struct TaskIdentifier {
1302 pub name: String,
1304 pub path: Option<String>,
1306}
1307
1308impl std::fmt::Display for TaskIdentifier {
1309 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1310 match &self.path {
1311 Some(path) => write!(formatter, "{}:{}", path, self.name),
1312 None => write!(formatter, "{}", self.name),
1313 }
1314 }
1315}
1316
1317impl TaskIdentifier {
1318 pub fn from_name(name: &str) -> Self {
1320 Self {
1321 name: name.to_string(),
1322 path: None,
1323 }
1324 }
1325}
1326
1327impl Into<TaskIdentifier> for DependencyIdentifier {
1328 fn into(self) -> TaskIdentifier {
1329 match self {
1330 DependencyIdentifier::Definition(identifier) => identifier,
1331 DependencyIdentifier::Name(name) => TaskIdentifier { name, path: None },
1332 }
1333 }
1334}
1335
1336impl Task {
1337 pub fn new() -> Task {
1339 Default::default()
1340 }
1341
1342 pub fn apply(self: &mut Task, modify_config: &ModifyConfig) {
1344 match modify_config.private {
1345 Some(value) => {
1346 if value {
1347 self.private = Some(true);
1348 }
1349 }
1350 None => (),
1351 };
1352
1353 match modify_config.namespace {
1354 Some(ref namespace) => {
1355 if namespace.len() > 0 {
1356 if self.extend.is_some() {
1357 self.extend = Some(get_namespaced_task_name(
1358 namespace,
1359 &self.extend.clone().unwrap(),
1360 ));
1361 }
1362
1363 if self.alias.is_some() {
1364 self.alias = Some(get_namespaced_task_name(
1365 namespace,
1366 &self.alias.clone().unwrap(),
1367 ));
1368 }
1369
1370 if self.linux_alias.is_some() {
1371 self.linux_alias = Some(get_namespaced_task_name(
1372 namespace,
1373 &self.linux_alias.clone().unwrap(),
1374 ));
1375 }
1376
1377 if self.windows_alias.is_some() {
1378 self.windows_alias = Some(get_namespaced_task_name(
1379 namespace,
1380 &self.windows_alias.clone().unwrap(),
1381 ));
1382 }
1383
1384 if self.mac_alias.is_some() {
1385 self.mac_alias = Some(get_namespaced_task_name(
1386 namespace,
1387 &self.mac_alias.clone().unwrap(),
1388 ));
1389 }
1390
1391 if self.run_task.is_some() {
1392 let mut run_task = self.run_task.clone().unwrap();
1393
1394 run_task = match run_task {
1395 RunTaskInfo::Name(value) => {
1396 RunTaskInfo::Name(get_namespaced_task_name(namespace, &value))
1397 }
1398 RunTaskInfo::Details(mut run_task_details) => {
1399 match run_task_details.name {
1400 RunTaskName::Single(ref name) => {
1401 run_task_details.name = RunTaskName::Single(
1402 get_namespaced_task_name(namespace, name),
1403 )
1404 }
1405 RunTaskName::Multiple(ref names) => {
1406 let mut updated_names = vec![];
1407 for name in names {
1408 updated_names
1409 .push(get_namespaced_task_name(namespace, name));
1410 }
1411
1412 run_task_details.name =
1413 RunTaskName::Multiple(updated_names);
1414 }
1415 };
1416
1417 RunTaskInfo::Details(run_task_details)
1418 }
1419 RunTaskInfo::Routing(mut routing_info_vector) => {
1420 for routing_info in &mut routing_info_vector {
1421 match routing_info.name {
1422 RunTaskName::Single(ref name) => {
1423 routing_info.name = RunTaskName::Single(
1424 get_namespaced_task_name(namespace, name),
1425 )
1426 }
1427 RunTaskName::Multiple(ref names) => {
1428 let mut updated_names = vec![];
1429 for name in names {
1430 updated_names.push(get_namespaced_task_name(
1431 namespace, name,
1432 ));
1433 }
1434
1435 routing_info.name =
1436 RunTaskName::Multiple(updated_names);
1437 }
1438 };
1439 }
1440
1441 RunTaskInfo::Routing(routing_info_vector)
1442 }
1443 };
1444
1445 self.run_task = Some(run_task);
1446 }
1447
1448 if let Some(dependencies) = &self.dependencies {
1449 self.dependencies = Some(
1450 dependencies
1451 .iter()
1452 .map(|identifier| identifier.to_owned().with_namespace(namespace))
1453 .collect(),
1454 );
1455 }
1456 }
1457 }
1458 None => (),
1459 };
1460 }
1461
1462 pub fn extend(self: &mut Task, task: &Task) {
1468 let override_values = match task.clear {
1469 Some(value) => value,
1470 None => false,
1471 };
1472
1473 if task.clear.is_some() {
1474 self.clear = task.clear.clone();
1475 }
1476
1477 if task.description.is_some() {
1478 self.description = task.description.clone();
1479 } else if override_values {
1480 self.description = None;
1481 }
1482
1483 if task.category.is_some() {
1484 self.category = task.category.clone();
1485 } else if override_values {
1486 self.category = None;
1487 }
1488
1489 if task.disabled.is_some() {
1490 self.disabled = task.disabled.clone();
1491 } else if override_values {
1492 self.disabled = None;
1493 }
1494
1495 if task.private.is_some() {
1496 self.private = task.private.clone();
1497 } else if override_values {
1498 self.private = None;
1499 }
1500
1501 if task.deprecated.is_some() {
1502 self.deprecated = task.deprecated.clone();
1503 } else if override_values {
1504 self.deprecated = None;
1505 }
1506
1507 if task.extend.is_some() {
1508 self.extend = task.extend.clone();
1509 } else if override_values {
1510 self.extend = None;
1511 }
1512
1513 if task.workspace.is_some() {
1514 self.workspace = task.workspace.clone();
1515 } else if override_values {
1516 self.workspace = None;
1517 }
1518
1519 if task.plugin.is_some() {
1520 self.plugin = task.plugin.clone();
1521 } else if override_values {
1522 self.plugin = None;
1523 }
1524
1525 if task.watch.is_some() {
1526 self.watch = task.watch.clone();
1527 } else if override_values {
1528 self.watch = None;
1529 }
1530
1531 if task.condition.is_some() {
1532 self.condition = task.condition.clone();
1533 } else if override_values {
1534 self.condition = None;
1535 }
1536
1537 if task.condition_script.is_some() {
1538 self.condition_script = task.condition_script.clone();
1539 } else if override_values {
1540 self.condition_script = None;
1541 }
1542
1543 if task.condition_script_runner_args.is_some() {
1544 self.condition_script_runner_args = task.condition_script_runner_args.clone();
1545 } else if override_values {
1546 self.condition_script_runner_args = None;
1547 }
1548
1549 if task.ignore_errors.is_some() {
1550 self.ignore_errors = task.ignore_errors.clone();
1551 } else if override_values {
1552 self.ignore_errors = None;
1553 }
1554
1555 if task.force.is_some() {
1556 self.force = task.force.clone();
1557 } else if override_values {
1558 self.force = None;
1559 }
1560
1561 if task.env_files.is_some() {
1562 self.env_files = task.env_files.clone();
1563 } else if override_values {
1564 self.env_files = None;
1565 }
1566
1567 if task.env.is_some() {
1568 self.env = task.env.clone();
1569 } else if override_values {
1570 self.env = None;
1571 }
1572
1573 if task.cwd.is_some() {
1574 self.cwd = task.cwd.clone();
1575 } else if override_values {
1576 self.cwd = None;
1577 }
1578
1579 if task.alias.is_some() {
1580 self.alias = task.alias.clone();
1581 } else if override_values {
1582 self.alias = None;
1583 }
1584
1585 if task.linux_alias.is_some() {
1586 self.linux_alias = task.linux_alias.clone();
1587 } else if override_values {
1588 self.linux_alias = None;
1589 }
1590
1591 if task.windows_alias.is_some() {
1592 self.windows_alias = task.windows_alias.clone();
1593 } else if override_values {
1594 self.windows_alias = None;
1595 }
1596
1597 if task.mac_alias.is_some() {
1598 self.mac_alias = task.mac_alias.clone();
1599 } else if override_values {
1600 self.mac_alias = None;
1601 }
1602
1603 if task.install_crate.is_some() {
1604 self.install_crate = task.install_crate.clone();
1605 } else if override_values {
1606 self.install_crate = None;
1607 }
1608
1609 if task.install_crate_args.is_some() {
1610 self.install_crate_args = task.install_crate_args.clone();
1611 } else if override_values {
1612 self.install_crate_args = None;
1613 }
1614
1615 if task.install_script.is_some() {
1616 self.install_script =
1617 extend_script_value(self.install_script.clone(), task.install_script.clone());
1618 } else if override_values {
1619 self.install_script = None;
1620 }
1621
1622 if task.command.is_some() {
1623 self.command = task.command.clone();
1624 } else if override_values {
1625 self.command = None;
1626 }
1627
1628 if task.args.is_some() {
1629 self.args = task.args.clone();
1630 } else if override_values {
1631 self.args = None;
1632 }
1633
1634 if task.script.is_some() {
1635 self.script = extend_script_value(self.script.clone(), task.script.clone());
1636 } else if override_values {
1637 self.script = None;
1638 }
1639
1640 if task.script_runner.is_some() {
1641 self.script_runner = task.script_runner.clone();
1642 } else if override_values {
1643 self.script_runner = None;
1644 }
1645
1646 if task.script_runner_args.is_some() {
1647 self.script_runner_args = task.script_runner_args.clone();
1648 } else if override_values {
1649 self.script_runner_args = None;
1650 }
1651
1652 if task.script_extension.is_some() {
1653 self.script_extension = task.script_extension.clone();
1654 } else if override_values {
1655 self.script_extension = None;
1656 }
1657
1658 if task.run_task.is_some() {
1659 self.run_task = task.run_task.clone();
1660 } else if override_values {
1661 self.run_task = None;
1662 }
1663
1664 if task.dependencies.is_some() {
1665 self.dependencies = task.dependencies.clone();
1666 } else if override_values {
1667 self.dependencies = None;
1668 }
1669
1670 if task.toolchain.is_some() {
1671 self.toolchain = task.toolchain.clone();
1672 } else if override_values {
1673 self.toolchain = None;
1674 }
1675
1676 if task.linux.is_some() {
1677 self.linux = task.linux.clone();
1678 } else if override_values {
1679 self.linux = None;
1680 }
1681
1682 if task.windows.is_some() {
1683 self.windows = task.windows.clone();
1684 } else if override_values {
1685 self.windows = None;
1686 }
1687
1688 if task.mac.is_some() {
1689 self.mac = task.mac.clone();
1690 } else if override_values {
1691 self.mac = None;
1692 }
1693 }
1694
1695 pub fn should_ignore_errors(self: &Task) -> bool {
1697 match self.ignore_errors {
1698 Some(value) => value,
1699 None => match self.force {
1700 Some(value) => {
1701 legacy::show_deprecated_attriute_warning("force", "ignore_errors");
1702
1703 value
1704 }
1705 None => false,
1706 },
1707 }
1708 }
1709
1710 fn get_override(self: &Task) -> Option<PlatformOverrideTask> {
1712 let platform_name = get_platform_name();
1713 if platform_name == "windows" {
1714 match self.windows {
1715 Some(ref value) => Some(value.clone()),
1716 _ => None,
1717 }
1718 } else if platform_name == "mac" {
1719 match self.mac {
1720 Some(ref value) => Some(value.clone()),
1721 _ => None,
1722 }
1723 } else {
1724 match self.linux {
1725 Some(ref value) => Some(value.clone()),
1726 _ => None,
1727 }
1728 }
1729 }
1730
1731 pub fn get_normalized_task(self: &mut Task) -> Task {
1733 match self.get_override() {
1734 Some(ref mut override_task) => {
1735 override_task.extend(self);
1736
1737 Task {
1738 clear: self.clear.clone(),
1739 description: self.description.clone(),
1740 category: self.category.clone(),
1741 disabled: override_task.disabled.clone(),
1742 private: override_task.private.clone(),
1743 deprecated: override_task.deprecated.clone(),
1744 extend: override_task.extend.clone(),
1745 workspace: self.workspace.clone(),
1746 plugin: override_task.plugin.clone(),
1747 watch: override_task.watch.clone(),
1748 condition: override_task.condition.clone(),
1749 condition_script: override_task.condition_script.clone(),
1750 condition_script_runner_args: override_task
1751 .condition_script_runner_args
1752 .clone(),
1753 ignore_errors: override_task.ignore_errors.clone(),
1754 force: override_task.force.clone(),
1755 env_files: override_task.env_files.clone(),
1756 env: override_task.env.clone(),
1757 cwd: override_task.cwd.clone(),
1758 alias: None,
1759 linux_alias: None,
1760 windows_alias: None,
1761 mac_alias: None,
1762 install_crate: override_task.install_crate.clone(),
1763 install_crate_args: override_task.install_crate_args.clone(),
1764 install_script: override_task.install_script.clone(),
1765 command: override_task.command.clone(),
1766 args: override_task.args.clone(),
1767 script: override_task.script.clone(),
1768 script_runner: override_task.script_runner.clone(),
1769 script_runner_args: override_task.script_runner_args.clone(),
1770 script_extension: override_task.script_extension.clone(),
1771 run_task: override_task.run_task.clone(),
1772 dependencies: override_task.dependencies.clone(),
1773 toolchain: override_task.toolchain.clone(),
1774 linux: None,
1775 windows: None,
1776 mac: None,
1777 }
1778 }
1779 None => self.clone(),
1780 }
1781 }
1782
1783 pub fn get_alias(self: &Task) -> Option<String> {
1785 let alias = if cfg!(windows) {
1786 match self.windows_alias {
1787 Some(ref value) => Some(value),
1788 _ => None,
1789 }
1790 } else if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
1791 match self.mac_alias {
1792 Some(ref value) => Some(value),
1793 _ => None,
1794 }
1795 } else {
1796 match self.linux_alias {
1797 Some(ref value) => Some(value),
1798 _ => None,
1799 }
1800 };
1801
1802 match alias {
1803 Some(os_alias) => Some(os_alias.clone()),
1804 _ => match self.alias {
1805 Some(ref alias) => Some(alias.clone()),
1806 _ => None,
1807 },
1808 }
1809 }
1810
1811 pub fn get_actions_count(self: &Task) -> u8 {
1813 let mut actions_count = 0;
1814
1815 if self.run_task.is_some() {
1816 actions_count = actions_count + 1;
1817 }
1818 if self.command.is_some() {
1819 actions_count = actions_count + 1;
1820 }
1821 if self.script.is_some() {
1822 actions_count = actions_count + 1;
1823 }
1824
1825 actions_count
1826 }
1827
1828 pub fn is_actionable(self: &Task) -> bool {
1831 if self.disabled.unwrap_or(false) {
1832 return false;
1833 }
1834
1835 let actions_count = self.get_actions_count();
1836 if actions_count > 0 {
1837 return true;
1838 }
1839
1840 if self.install_crate.is_some() || self.install_script.is_some() {
1841 return true;
1842 }
1843
1844 let mut actionable = match self.env {
1845 Some(ref value) => value.len() > 0,
1846 None => false,
1847 };
1848 if actionable {
1849 return true;
1850 }
1851
1852 actionable = match self.env_files {
1853 Some(ref value) => value.len() > 0,
1854 None => false,
1855 };
1856 if actionable {
1857 return true;
1858 }
1859
1860 actionable = match self.dependencies {
1861 Some(ref value) => value.len() > 0,
1862 None => false,
1863 };
1864 if actionable {
1865 return true;
1866 }
1867
1868 actionable = match self.watch {
1869 Some(ref options) => match options {
1870 TaskWatchOptions::Boolean(value) => *value,
1871 _ => true,
1872 },
1873 None => false,
1874 };
1875
1876 actionable
1877 }
1878
1879 pub fn is_valid(self: &Task) -> bool {
1881 let actions_count = self.get_actions_count();
1882
1883 if actions_count <= 1 {
1884 true
1885 } else {
1886 false
1887 }
1888 }
1889}
1890
1891#[derive(Serialize, Deserialize, Debug, Clone)]
1892pub struct PlatformOverrideTask {
1894 pub clear: Option<bool>,
1896 pub disabled: Option<bool>,
1898 pub private: Option<bool>,
1900 pub deprecated: Option<DeprecationInfo>,
1902 pub extend: Option<String>,
1904 pub plugin: Option<String>,
1906 pub watch: Option<TaskWatchOptions>,
1908 pub condition: Option<TaskCondition>,
1910 pub condition_script: Option<ConditionScriptValue>,
1912 pub condition_script_runner_args: Option<Vec<String>>,
1914 pub ignore_errors: Option<bool>,
1916 pub force: Option<bool>,
1918 pub env_files: Option<Vec<EnvFile>>,
1920 pub env: Option<IndexMap<String, EnvValue>>,
1922 pub cwd: Option<String>,
1924 pub install_crate: Option<InstallCrate>,
1926 pub install_crate_args: Option<Vec<String>>,
1928 pub install_script: Option<ScriptValue>,
1930 pub command: Option<String>,
1932 pub args: Option<Vec<String>>,
1934 pub script: Option<ScriptValue>,
1936 pub script_runner: Option<String>,
1938 pub script_runner_args: Option<Vec<String>>,
1940 pub script_extension: Option<String>,
1942 pub run_task: Option<RunTaskInfo>,
1944 pub dependencies: Option<Vec<DependencyIdentifier>>,
1946 pub toolchain: Option<ToolchainSpecifier>,
1948}
1949
1950impl PlatformOverrideTask {
1951 pub fn extend(self: &mut PlatformOverrideTask, task: &mut Task) {
1957 let copy_values = match self.clear {
1958 Some(value) => !value,
1959 None => true,
1960 };
1961
1962 if copy_values {
1963 if self.disabled.is_none() && task.disabled.is_some() {
1964 self.disabled = task.disabled.clone();
1965 }
1966
1967 if self.private.is_none() && task.private.is_some() {
1968 self.private = task.private.clone();
1969 }
1970
1971 if self.deprecated.is_none() && task.deprecated.is_some() {
1972 self.deprecated = task.deprecated.clone();
1973 }
1974
1975 if self.extend.is_none() && task.extend.is_some() {
1976 self.extend = task.extend.clone();
1977 }
1978
1979 if self.plugin.is_none() && task.plugin.is_some() {
1980 self.plugin = task.plugin.clone();
1981 }
1982
1983 if self.watch.is_none() && task.watch.is_some() {
1984 self.watch = task.watch.clone();
1985 }
1986
1987 if self.condition.is_none() && task.condition.is_some() {
1988 self.condition = task.condition.clone();
1989 }
1990
1991 if self.condition_script.is_none() && task.condition_script.is_some() {
1992 self.condition_script = task.condition_script.clone();
1993 }
1994
1995 if self.condition_script_runner_args.is_none()
1996 && task.condition_script_runner_args.is_some()
1997 {
1998 self.condition_script_runner_args = task.condition_script_runner_args.clone();
1999 }
2000
2001 if self.ignore_errors.is_none() && task.ignore_errors.is_some() {
2002 self.ignore_errors = task.ignore_errors.clone();
2003 }
2004
2005 if self.force.is_none() && task.force.is_some() {
2006 self.force = task.force.clone();
2007 }
2008
2009 if self.env_files.is_none() && task.env_files.is_some() {
2010 self.env_files = task.env_files.clone();
2011 }
2012
2013 if self.env.is_none() && task.env.is_some() {
2014 self.env = task.env.clone();
2015 }
2016
2017 if self.cwd.is_none() && task.cwd.is_some() {
2018 self.cwd = task.cwd.clone();
2019 }
2020
2021 if self.install_crate.is_none() && task.install_crate.is_some() {
2022 self.install_crate = task.install_crate.clone();
2023 }
2024
2025 if self.install_crate_args.is_none() && task.install_crate_args.is_some() {
2026 self.install_crate_args = task.install_crate_args.clone();
2027 }
2028
2029 if self.install_script.is_none() && task.install_script.is_some() {
2030 self.install_script =
2031 extend_script_value(self.install_script.clone(), task.install_script.clone());
2032 }
2033
2034 if self.command.is_none() && task.command.is_some() {
2035 self.command = task.command.clone();
2036 }
2037
2038 if self.args.is_none() && task.args.is_some() {
2039 self.args = task.args.clone();
2040 }
2041
2042 if self.script.is_none() && task.script.is_some() {
2043 self.script = extend_script_value(None, task.script.clone());
2044 }
2045
2046 if self.script_runner.is_none() && task.script_runner.is_some() {
2047 self.script_runner = task.script_runner.clone();
2048 }
2049
2050 if self.script_runner_args.is_none() && task.script_runner_args.is_some() {
2051 self.script_runner_args = task.script_runner_args.clone();
2052 }
2053
2054 if self.script_extension.is_none() && task.script_extension.is_some() {
2055 self.script_extension = task.script_extension.clone();
2056 }
2057
2058 if self.run_task.is_none() && task.run_task.is_some() {
2059 self.run_task = task.run_task.clone();
2060 }
2061
2062 if self.dependencies.is_none() && task.dependencies.is_some() {
2063 self.dependencies = task.dependencies.clone();
2064 }
2065
2066 if self.toolchain.is_none() && task.toolchain.is_some() {
2067 self.toolchain = task.toolchain.clone();
2068 }
2069 }
2070 }
2071}
2072
2073#[derive(Serialize, Deserialize, Debug, Clone)]
2074pub struct ExtendOptions {
2076 pub path: String,
2078 pub optional: Option<bool>,
2080 pub relative: Option<String>,
2083}
2084
2085#[derive(Serialize, Deserialize, Debug, Clone)]
2086#[serde(untagged)]
2087pub enum Extend {
2089 Path(String),
2091 Options(ExtendOptions),
2093 List(Vec<ExtendOptions>),
2095}
2096
2097#[derive(Serialize, Deserialize, Debug, Clone)]
2098pub struct ModifyConfig {
2100 pub private: Option<bool>,
2102 pub namespace: Option<String>,
2104}
2105
2106impl ModifyConfig {
2107 pub fn is_modifications_defined(self: &ModifyConfig) -> bool {
2109 if self.private.unwrap_or(false) {
2110 true
2111 } else {
2112 match self.namespace {
2113 Some(ref value) => value.len() > 0,
2114 None => false,
2115 }
2116 }
2117 }
2118
2119 pub fn get_namespace_prefix(self: &ModifyConfig) -> String {
2121 match self.namespace {
2122 Some(ref value) => get_namespaced_task_name(value, ""),
2123 None => "".to_string(),
2124 }
2125 }
2126}
2127
2128#[derive(Serialize, Deserialize, Debug, Clone, Copy, Hash, PartialEq, Eq)]
2129#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
2130pub enum UnstableFeature {
2132 CtrlCHandling,
2134}
2135
2136impl UnstableFeature {
2137 pub fn to_env_name(&self) -> String {
2139 let mut feature = serde_json::to_string(&self).unwrap();
2140 feature = feature.replace("\"", "");
2141 format!("CARGO_MAKE_UNSTABLE_FEATURE_{feature}", feature = feature)
2142 }
2143
2144 pub fn is_env_set(&self) -> bool {
2146 envmnt::is(self.to_env_name())
2147 }
2148}
2149
2150#[derive(Serialize, Deserialize, Debug, Clone, Default)]
2151pub struct ConfigSection {
2153 pub skip_core_tasks: Option<bool>,
2155 pub modify_core_tasks: Option<ModifyConfig>,
2157 pub init_task: Option<String>,
2159 pub end_task: Option<String>,
2161 pub on_error_task: Option<String>,
2163 pub legacy_migration_task: Option<String>,
2165 pub additional_profiles: Option<Vec<String>>,
2167 pub min_version: Option<String>,
2169 pub default_to_workspace: Option<bool>,
2171 pub skip_git_env_info: Option<bool>,
2173 pub skip_rust_env_info: Option<bool>,
2175 pub skip_crate_env_info: Option<bool>,
2177 pub reduce_output: Option<bool>,
2179 pub time_summary: Option<bool>,
2181 pub load_cargo_aliases: Option<bool>,
2183 pub disable_install: Option<bool>,
2185 pub main_project_member: Option<String>,
2187 pub load_script: Option<ScriptValue>,
2189 pub linux_load_script: Option<ScriptValue>,
2191 pub windows_load_script: Option<ScriptValue>,
2193 pub mac_load_script: Option<ScriptValue>,
2195 pub unstable_features: Option<IndexSet<UnstableFeature>>,
2197}
2198
2199impl ConfigSection {
2200 pub fn new() -> ConfigSection {
2202 Default::default()
2203 }
2204
2205 pub fn apply(self: &mut ConfigSection, modify_config: &ModifyConfig) {
2207 match modify_config.namespace {
2208 Some(ref namespace) => {
2209 if self.init_task.is_some() {
2210 self.init_task = Some(get_namespaced_task_name(
2211 namespace,
2212 &self.init_task.clone().unwrap(),
2213 ));
2214 }
2215
2216 if self.end_task.is_some() {
2217 self.end_task = Some(get_namespaced_task_name(
2218 namespace,
2219 &self.end_task.clone().unwrap(),
2220 ));
2221 }
2222
2223 if self.on_error_task.is_some() {
2224 self.on_error_task = Some(get_namespaced_task_name(
2225 namespace,
2226 &self.on_error_task.clone().unwrap(),
2227 ));
2228 }
2229
2230 if self.legacy_migration_task.is_some() {
2231 self.legacy_migration_task = Some(get_namespaced_task_name(
2232 namespace,
2233 &self.legacy_migration_task.clone().unwrap(),
2234 ));
2235 }
2236 }
2237 None => (),
2238 }
2239 }
2240
2241 pub fn extend(self: &mut ConfigSection, extended: &mut ConfigSection) {
2247 if extended.skip_core_tasks.is_some() {
2248 self.skip_core_tasks = extended.skip_core_tasks.clone();
2249 }
2250
2251 if extended.modify_core_tasks.is_some() {
2252 self.modify_core_tasks = extended.modify_core_tasks.clone();
2253 }
2254
2255 if extended.init_task.is_some() {
2256 self.init_task = extended.init_task.clone();
2257 }
2258
2259 if extended.end_task.is_some() {
2260 self.end_task = extended.end_task.clone();
2261 }
2262
2263 if extended.on_error_task.is_some() {
2264 self.on_error_task = extended.on_error_task.clone();
2265 }
2266
2267 if extended.legacy_migration_task.is_some() {
2268 self.legacy_migration_task = extended.legacy_migration_task.clone();
2269 }
2270
2271 if extended.additional_profiles.is_some() {
2272 self.additional_profiles = extended.additional_profiles.clone();
2273 }
2274
2275 if extended.min_version.is_some() {
2276 self.min_version = extended.min_version.clone();
2277 }
2278
2279 if extended.default_to_workspace.is_some() {
2280 self.default_to_workspace = extended.default_to_workspace.clone();
2281 }
2282
2283 if extended.skip_git_env_info.is_some() {
2284 self.skip_git_env_info = extended.skip_git_env_info.clone();
2285 }
2286
2287 if extended.skip_rust_env_info.is_some() {
2288 self.skip_rust_env_info = extended.skip_rust_env_info.clone();
2289 }
2290
2291 if extended.skip_crate_env_info.is_some() {
2292 self.skip_crate_env_info = extended.skip_crate_env_info.clone();
2293 }
2294
2295 if extended.reduce_output.is_some() {
2296 self.reduce_output = extended.reduce_output.clone();
2297 }
2298
2299 if extended.time_summary.is_some() {
2300 self.time_summary = extended.time_summary.clone();
2301 }
2302
2303 if extended.load_cargo_aliases.is_some() {
2304 self.load_cargo_aliases = extended.load_cargo_aliases.clone();
2305 }
2306
2307 if extended.disable_install.is_some() {
2308 self.disable_install = extended.disable_install.clone();
2309 }
2310
2311 if extended.main_project_member.is_some() {
2312 self.main_project_member = extended.main_project_member.clone();
2313 }
2314
2315 if extended.load_script.is_some() {
2316 self.load_script =
2317 extend_script_value(self.load_script.clone(), extended.load_script.clone());
2318 }
2319
2320 if extended.linux_load_script.is_some() {
2321 self.linux_load_script = extend_script_value(
2322 self.linux_load_script.clone(),
2323 extended.linux_load_script.clone(),
2324 );
2325 }
2326
2327 if extended.windows_load_script.is_some() {
2328 self.windows_load_script = extend_script_value(
2329 self.windows_load_script.clone(),
2330 extended.windows_load_script.clone(),
2331 );
2332 }
2333
2334 if extended.mac_load_script.is_some() {
2335 self.mac_load_script = extend_script_value(
2336 self.mac_load_script.clone(),
2337 extended.mac_load_script.clone(),
2338 );
2339 }
2340
2341 if let Some(extended_unstable_features) = extended.unstable_features.clone() {
2342 if let Some(unstable_features) = &mut self.unstable_features {
2343 unstable_features.extend(extended_unstable_features);
2344 } else {
2345 self.unstable_features = Some(extended_unstable_features);
2346 }
2347 }
2348 }
2349
2350 pub fn get_load_script(self: &ConfigSection) -> Option<ScriptValue> {
2352 let platform_name = get_platform_name();
2353
2354 if platform_name == "windows" {
2355 if self.windows_load_script.is_some() {
2356 self.windows_load_script.clone()
2357 } else {
2358 self.load_script.clone()
2359 }
2360 } else if platform_name == "mac" {
2361 if self.mac_load_script.is_some() {
2362 self.mac_load_script.clone()
2363 } else {
2364 self.load_script.clone()
2365 }
2366 } else {
2367 if self.linux_load_script.is_some() {
2368 self.linux_load_script.clone()
2369 } else {
2370 self.load_script.clone()
2371 }
2372 }
2373 }
2374}
2375
2376#[derive(Serialize, Deserialize, Debug, Clone, Default)]
2377pub struct Config {
2379 pub config: ConfigSection,
2381 pub env_files: Vec<EnvFile>,
2383 pub env: IndexMap<String, EnvValue>,
2385 pub env_scripts: Vec<String>,
2387 pub tasks: IndexMap<String, Task>,
2389 pub plugins: Option<Plugins>,
2391}
2392
2393impl Config {
2394 pub fn apply(self: &mut Config, modify_config: &ModifyConfig) {
2396 self.config.apply(&modify_config);
2397
2398 let namespace = match modify_config.namespace {
2399 Some(ref namespace) => namespace,
2400 None => "",
2401 };
2402
2403 let mut modified_tasks = IndexMap::<String, Task>::new();
2404
2405 for (key, value) in self.tasks.iter() {
2406 let namespaced_task = get_namespaced_task_name(namespace, &key);
2407 let mut task = value.clone();
2408
2409 task.apply(&modify_config);
2410
2411 modified_tasks.insert(namespaced_task, task);
2412 }
2413
2414 self.tasks = modified_tasks;
2415 }
2416}
2417
2418#[derive(Serialize, Deserialize, Debug, Clone, Default)]
2419pub struct ExternalConfig {
2421 pub extend: Option<Extend>,
2423 pub config: Option<ConfigSection>,
2425 pub env_files: Option<Vec<EnvFile>>,
2427 pub env: Option<IndexMap<String, EnvValue>>,
2429 pub env_scripts: Option<Vec<String>>,
2431 pub tasks: Option<IndexMap<String, Task>>,
2433 pub plugins: Option<Plugins>,
2435}
2436
2437impl ExternalConfig {
2438 pub fn new() -> ExternalConfig {
2440 Default::default()
2441 }
2442}
2443
2444#[derive(Serialize, Clone, Debug)]
2445pub struct Step {
2447 pub name: String,
2449 pub config: Task,
2451}
2452
2453#[derive(Debug)]
2454pub struct ExecutionPlan {
2456 pub steps: Vec<Step>,
2458}
2459
2460#[derive(Debug)]
2461pub struct CommandSpec {
2463 pub command: String,
2465 pub args: Option<Vec<String>>,
2467}