sagiegurari / cargo-make
1
//! # types
2
//!
3
//! Defines the various types and aliases used by cargo-make.
4
//!
5

6
#[cfg(test)]
7
#[path = "./types_test.rs"]
8
mod types_test;
9

10
use crate::legacy;
11
use ci_info::types::CiInfo;
12
use git_info::types::GitInfo;
13
use indexmap::IndexMap;
14
use rust_info::types::RustInfo;
15
use std::collections::HashMap;
16

17
/// Returns the platform name
18 8
pub fn get_platform_name() -> String {
19 2
    if cfg!(windows) {
20 0
        "windows".to_string()
21 2
    } else if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
22 0
        "mac".to_string()
23
    } else {
24 8
        "linux".to_string()
25
    }
26 8
}
27

28 8
fn get_namespaced_task_name(namespace: &str, task: &str) -> String {
29 8
    let mut namespaced_task = String::new();
30

31 8
    if namespace.len() > 0 {
32 8
        namespaced_task.push_str(namespace);
33 8
        namespaced_task.push_str("::");
34
    }
35 8
    namespaced_task.push_str(task);
36

37 2
    namespaced_task
38 8
}
39

40 0
#[derive(Debug, Clone)]
41
/// Holds CLI args
42
pub struct CliArgs {
43
    /// The command name
44 0
    pub command: String,
45
    /// The external Makefile.toml path
46 0
    pub build_file: Option<String>,
47
    /// The task to invoke
48 0
    pub task: String,
49
    /// The profile name
50 0
    pub profile: Option<String>,
51
    /// Log level name
52 0
    pub log_level: String,
53
    /// Disables colorful output
54 0
    pub disable_color: bool,
55
    /// Current working directory
56 0
    pub cwd: Option<String>,
57
    /// Environment variables
58 0
    pub env: Option<Vec<String>>,
59
    /// Environment variables file
60 0
    pub env_file: Option<String>,
61
    /// Prevent workspace support
62 0
    pub disable_workspace: bool,
63
    /// Prevent on error flow even if defined in config section
64 0
    pub disable_on_error: bool,
65
    /// Allow invocation of private tasks
66 0
    pub allow_private: bool,
67
    /// If true, the init and end tasks are skipped
68 0
    pub skip_init_end_tasks: bool,
69
    /// Only print the execution plan
70 0
    pub print_only: bool,
71
    /// List all known steps
72 0
    pub list_all_steps: bool,
73
    /// Diff flows
74 0
    pub diff_execution_plan: bool,
75
    /// Disables the update check during startup
76 0
    pub disable_check_for_updates: bool,
77
    /// Allows access unsupported experimental predefined tasks
78 0
    pub experimental: bool,
79
    /// additional command line arguments
80 0
    pub arguments: Option<Vec<String>>,
81
    /// Output format
82 0
    pub output_format: String,
83
    /// Output file name
84 0
    pub output_file: Option<String>,
85
    /// Print time summary at end of the flow
86 0
    pub print_time_summary: bool,
87
}
88

89
impl CliArgs {
90
    /// Creates and returns a new instance.
91 8
    pub fn new() -> CliArgs {
92 8
        CliArgs {
93 8
            command: "".to_string(),
94 8
            build_file: None,
95 8
            task: "default".to_string(),
96 8
            profile: None,
97 8
            log_level: "info".to_string(),
98
            disable_color: false,
99 8
            cwd: None,
100 8
            env: None,
101 8
            env_file: None,
102
            disable_workspace: false,
103
            disable_on_error: false,
104
            allow_private: false,
105
            skip_init_end_tasks: false,
106
            print_only: false,
107
            list_all_steps: false,
108
            diff_execution_plan: false,
109
            disable_check_for_updates: false,
110
            experimental: false,
111 8
            arguments: None,
112 8
            output_format: "default".to_string(),
113 8
            output_file: None,
114
            print_time_summary: false,
115 0
        }
116 8
    }
117
}
118

119 8
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
120
/// Holds persisted data used by cargo-make
121
pub struct Cache {
122
    /// File from which the cache file was loaded from
123
    #[serde(skip)]
124 8
    pub file_name: Option<String>,
125
    /// Holds last update check with returned no updates result
126 8
    pub last_update_check: Option<u64>,
127
}
128

129
impl Cache {
130
    /// Returns new instance
131 8
    pub fn new() -> Cache {
132 8
        Default::default()
133 8
    }
134
}
135

136 8
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
137
/// Holds configuration info for cargo-make
138
pub struct GlobalConfig {
139
    /// File from which the global config was loaded from
140
    #[serde(skip)]
141 8
    pub file_name: Option<String>,
142
    /// Default log level
143 8
    pub log_level: Option<String>,
144
    /// Default output coloring
145 8
    pub disable_color: Option<bool>,
146
    /// Default task name
147 8
    pub default_task_name: Option<String>,
148
    /// Update check minimum time from the previous check (always, daily, weekly, monthly)
149 8
    pub update_check_minimum_interval: Option<String>,
150
    /// True to search for project root in parent directories if current cwd is not a project root
151 8
    pub search_project_root: Option<bool>,
152
}
153

154
impl GlobalConfig {
155
    /// Returns new instance
156 8
    pub fn new() -> GlobalConfig {
157 8
        GlobalConfig {
158 8
            search_project_root: Some(false),
159 8
            ..Default::default()
160
        }
161 8
    }
162
}
163

164 8
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
165
/// Holds crate workspace info, see http://doc.crates.io/manifest.html#the-workspace-section
166
pub struct Workspace {
167
    /// members paths
168 8
    pub members: Option<Vec<String>>,
169
    /// exclude paths
170 8
    pub exclude: Option<Vec<String>>,
171
}
172

173
impl Workspace {
174
    /// Creates and returns a new instance.
175 8
    pub fn new() -> Workspace {
176 8
        Default::default()
177 8
    }
178
}
179

180 8
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
181
/// Holds crate package information loaded from the Cargo.toml file package section.
182
pub struct PackageInfo {
183
    /// name
184 2
    pub name: Option<String>,
185
    /// version
186 2
    pub version: Option<String>,
187
    /// description
188 2
    pub description: Option<String>,
189
    /// license
190 2
    pub license: Option<String>,
191
    /// documentation link
192 2
    pub documentation: Option<String>,
193
    /// homepage link
194 2
    pub homepage: Option<String>,
195
    /// repository link
196 2
    pub repository: Option<String>,
197
}
198

199
impl PackageInfo {
200
    /// Creates and returns a new instance.
201 2
    pub fn new() -> PackageInfo {
202 2
        Default::default()
203 2
    }
204
}
205

206 8
#[derive(Serialize, Deserialize, Debug, Clone)]
207
/// Holds crate dependency info.
208
pub struct CrateDependencyInfo {
209
    /// Holds the dependency path
210 2
    pub path: Option<String>,
211
}
212

213 8
#[derive(Serialize, Deserialize, Debug, Clone)]
214
#[serde(untagged)]
215
/// Holds crate dependency info.
216
pub enum CrateDependency {
217
    /// Holds the dependency version
218 8
    Version(String),
219
    /// Hold dependency info
220 8
    Info(CrateDependencyInfo),
221
}
222

223 8
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
224
/// Holds crate information loaded from the Cargo.toml file.
225
pub struct CrateInfo {
226
    /// package info
227 8
    pub package: Option<PackageInfo>,
228
    /// workspace info
229 8
    pub workspace: Option<Workspace>,
230
    /// crate dependencies
231 8
    pub dependencies: Option<IndexMap<String, CrateDependency>>,
232
}
233

234
impl CrateInfo {
235
    /// Creates and returns a new instance.
236 8
    pub fn new() -> CrateInfo {
237 8
        Default::default()
238 8
    }
239
}
240

241 8
#[derive(Debug, Clone)]
242
/// Holds env information
243
pub struct EnvInfo {
244
    /// Rust info
245 8
    pub rust_info: RustInfo,
246
    /// Crate info
247 8
    pub crate_info: CrateInfo,
248
    /// Git info
249 8
    pub git_info: GitInfo,
250
    /// CI info
251 8
    pub ci_info: CiInfo,
252
}
253

254 8
#[derive(Debug, Clone)]
255
/// Holds flow information
256
pub struct FlowInfo {
257
    /// The flow config object
258 8
    pub config: Config,
259
    /// The main task of the flow
260 8
    pub task: String,
261
    /// The env info
262 8
    pub env_info: EnvInfo,
263
    /// Prevent workspace support
264 8
    pub disable_workspace: bool,
265
    /// Prevent on error flow even if defined in config section
266 8
    pub disable_on_error: bool,
267
    /// Allow invocation of private tasks
268 8
    pub allow_private: bool,
269
    /// If true, the init and end tasks are skipped
270 8
    pub skip_init_end_tasks: bool,
271
    /// additional command line arguments
272 8
    pub cli_arguments: Option<Vec<String>>,
273
}
274

275 8
#[derive(Debug, Clone, Default)]
276
/// Holds mutable flow state
277
pub struct FlowState {
278
    /// timing info for summary
279 8
    pub time_summary: Vec<(String, u128)>,
280
}
281

282
impl FlowState {
283
    /// Creates and returns a new instance.
284 8
    pub fn new() -> FlowState {
285 8
        Default::default()
286 8
    }
287
}
288

289 8
#[derive(Serialize, Deserialize, Debug, Clone)]
290
/// Rust version condition structure
291
pub struct RustVersionCondition {
292
    /// min version number
293 8
    pub min: Option<String>,
294
    /// max version number
295 8
    pub max: Option<String>,
296
    /// specific version number
297 8
    pub equal: Option<String>,
298
}
299

300 8
#[derive(Serialize, Deserialize, Debug, Clone)]
301
/// Holds condition attributes
302
pub struct TaskCondition {
303
    /// Failure message
304 8
    pub fail_message: Option<String>,
305
    /// Profile names (development, ...)
306 8
    pub profiles: Option<Vec<String>>,
307
    /// Platform names (linux, windows, mac)
308 8
    pub platforms: Option<Vec<String>>,
309
    /// Channel names (stable, beta, nightly)
310 8
    pub channels: Option<Vec<String>>,
311
    /// Environment variables which must be defined
312 8
    pub env_set: Option<Vec<String>>,
313
    /// Environment variables which must not be defined
314 8
    pub env_not_set: Option<Vec<String>>,
315
    /// Environment variables and their values
316 8
    pub env: Option<IndexMap<String, String>>,
317
    /// Environment variables which are defined as true
318 8
    pub env_true: Option<Vec<String>>,
319
    /// Environment variables which are defined as false
320 8
    pub env_false: Option<Vec<String>>,
321
    /// Environment variables and the values which they are required to contain
322 8
    pub env_contains: Option<IndexMap<String, String>>,
323
    /// Rust version condition
324 8
    pub rust_version: Option<RustVersionCondition>,
325
    /// Files exist
326 8
    pub files_exist: Option<Vec<String>>,
327
    /// Files which do not exist
328 8
    pub files_not_exist: Option<Vec<String>>,
329
}
330

331 2
#[derive(Serialize, Deserialize, Debug, Clone)]
332
/// Env file path and attributes
333
pub struct EnvFileInfo {
334
    /// The file path as string
335 2
    pub path: String,
336
    /// The path base directory (relative paths are from this base path)
337 2
    pub base_path: Option<String>,
338
    /// The profile name this file is relevant to
339 2
    pub profile: Option<String>,
340
}
341

342
impl EnvFileInfo {
343
    /// Creates and returns a new instance.
344 0
    pub fn new(path: String) -> EnvFileInfo {
345 0
        EnvFileInfo {
346 0
            path,
347 0
            base_path: None,
348 0
            profile: None,
349
        }
350 0
    }
351
}
352

353 8
#[derive(Serialize, Deserialize, Debug, Clone)]
354
#[serde(untagged)]
355
/// Holds the env file path and attributes
356
pub enum EnvFile {
357
    /// The file path as string
358 8
    Path(String),
359
    /// Extended info object for env file
360 2
    Info(EnvFileInfo),
361
}
362

363 8
#[derive(Serialize, Deserialize, Debug, Clone)]
364
/// Env value provided by a script
365
pub struct EnvValueScript {
366
    /// The script to execute to get the env value
367 2
    pub script: Vec<String>,
368
    /// True/False to enable multi line env values
369 2
    pub multi_line: Option<bool>,
370
}
371

372 8
#[derive(Serialize, Deserialize, Debug, Clone)]
373
/// Env value provided by decoding other values
374
pub struct EnvValueDecode {
375
    /// The source value (can be an env expression)
376 8
    pub source: String,
377
    /// The default value in case no decode mapping was found, if not provided it will default to the source value
378 8
    pub default_value: Option<String>,
379
    /// The decoding mapping
380 8
    pub mapping: HashMap<String, String>,
381
}
382

383 8
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
384
/// Enables to unset env variables
385
pub struct EnvValueUnset {
386
    /// If true, the env variable will be unset, else ignored
387 0
    pub unset: bool,
388
}
389

390 8
#[derive(Serialize, Deserialize, Debug, Clone)]
391
/// Env value provided by decoding other values
392
pub struct EnvValueConditioned {
393
    /// The value to set (can be an env expression)
394 8
    pub value: String,
395
    /// The condition to validate
396 8
    pub condition: Option<TaskCondition>,
397
}
398

399 8
#[derive(Serialize, Deserialize, Debug, Clone)]
400
#[serde(untagged)]
401
/// Holds the env value or script
402
pub enum EnvValue {
403
    /// The value as string
404 8
    Value(String),
405
    /// The value as boolean
406 8
    Boolean(bool),
407
    /// The value as number
408 8
    Number(isize),
409
    /// The value as a list of strings
410 8
    List(Vec<String>),
411
    /// Unset env
412 8
    Unset(EnvValueUnset),
413
    /// Script which will return the value
414 8
    Script(EnvValueScript),
415
    /// Env decoding info
416 8
    Decode(EnvValueDecode),
417
    /// Conditional env value
418 8
    Conditional(EnvValueConditioned),
419
    /// Profile env
420 8
    Profile(IndexMap<String, EnvValue>),
421
}
422

423
/// Arguments used to check whether a crate or rustup component is installed.
424
///
425
/// Deserialize into an array of strings. Allows both a single string (which will
426
/// become a single-element array) or a sequence of strings.
427 8
#[derive(Debug, Serialize, Clone, PartialEq, Eq)]
428
#[serde(transparent)]
429
pub struct TestArg {
430
    /// Content of the arguments
431 8
    pub inner: Vec<String>,
432
}
433

434
impl std::ops::Deref for TestArg {
435
    type Target = Vec<String>;
436 8
    fn deref(&self) -> &Self::Target {
437 2
        &self.inner
438 8
    }
439
}
440

441
impl std::ops::DerefMut for TestArg {
442
    fn deref_mut(&mut self) -> &mut Self::Target {
443
        &mut self.inner
444
    }
445
}
446

447
impl<'de> serde::de::Deserialize<'de> for TestArg {
448 8
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
449
    where
450
        D: serde::de::Deserializer<'de>,
451
    {
452
        struct StringVecVisitor;
453
        impl<'de> serde::de::Visitor<'de> for StringVecVisitor {
454
            type Value = TestArg;
455

456 0
            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
457 0
                formatter.write_str("A string or an array of strings")
458 0
            }
459

460 8
            fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
461
            where
462
                E: serde::de::Error,
463
            {
464 8
                Ok(TestArg {
465 8
                    inner: vec![s.to_string()],
466
                })
467 8
            }
468

469 8
            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
470
            where
471
                A: serde::de::SeqAccess<'de>,
472
            {
473 8
                let mut v = Vec::with_capacity(seq.size_hint().unwrap_or(0));
474 8
                while let Some(s) = seq.next_element()? {
475 8
                    v.push(s);
476 6
                }
477

478 8
                Ok(TestArg { inner: v })
479 8
            }
480
        }
481 8
        deserializer.deserialize_any(StringVecVisitor)
482 8
    }
483
}
484

485 8
#[derive(Serialize, Deserialize, Debug, Clone)]
486
/// Holds instructions how to install the cargo plugin
487
pub struct InstallCargoPluginInfo {
488
    /// The provided crate to install
489 8
    pub crate_name: Option<String>,
490
    /// Minimial version
491 8
    pub min_version: String,
492
}
493

494
impl PartialEq for InstallCargoPluginInfo {
495 8
    fn eq(&self, other: &InstallCargoPluginInfo) -> bool {
496 8
        if self.min_version != other.min_version {
497 8
            false
498
        } else {
499 8
            match self.crate_name {
500 8
                Some(ref crate_name) => match other.crate_name {
501 8
                    Some(ref other_crate_name) => crate_name == other_crate_name,
502 8
                    None => false,
503
                },
504 0
                None => match other.crate_name {
505 8
                    None => true,
506 0
                    _ => false,
507
                },
508
            }
509
        }
510 8
    }
511
}
512

513 8
#[derive(Serialize, Deserialize, Debug, Clone)]
514
/// Holds instructions how to install the crate
515
pub struct InstallCrateInfo {
516
    /// The provided crate to install
517 8
    pub crate_name: String,
518
    /// If defined, the component to install via rustup
519 8
    pub rustup_component_name: Option<String>,
520
    /// The binary file name to be used to test if the crate is already installed
521 8
    pub binary: String,
522
    /// Test arguments that will be used to check that the crate is installed.
523 8
    pub test_arg: TestArg,
524
    /// Minimial version
525 8
    pub min_version: Option<String>,
526
}
527

528
impl PartialEq for InstallCrateInfo {
529 8
    fn eq(&self, other: &InstallCrateInfo) -> bool {
530 8
        if self.crate_name != other.crate_name
531 8
            || self.binary != other.binary
532 8
            || self.test_arg != other.test_arg
533
        {
534 8
            false
535
        } else {
536 8
            match self.rustup_component_name {
537 8
                Some(ref rustup_component_name) => match other.rustup_component_name {
538 8
                    Some(ref other_rustup_component_name) => {
539 8
                        if rustup_component_name == other_rustup_component_name {
540 8
                            match self.min_version {
541 8
                                Some(ref min_version) => match other.min_version {
542 8
                                    Some(ref other_min_version) => min_version == other_min_version,
543 8
                                    None => false,
544
                                },
545 0
                                None => match other.min_version {
546 8
                                    None => true,
547 0
                                    _ => false,
548
                                },
549
                            }
550
                        } else {
551 8
                            false
552
                        }
553
                    }
554 8
                    None => false,
555
                },
556 0
                None => match other.rustup_component_name {
557 8
                    None => true,
558 0
                    _ => false,
559
                },
560
            }
561
        }
562 8
    }
563
}
564

565 8
#[derive(Serialize, Deserialize, Debug, Clone)]
566
/// Holds instructions how to install a rustup component
567
pub struct InstallRustupComponentInfo {
568
    /// The component to install via rustup
569 8
    pub rustup_component_name: String,
570
    /// The binary file name to be used to test if the crate is already installed
571 8
    pub binary: Option<String>,
572
    /// Test argument that will be used to check that the crate is installed
573 8
    pub test_arg: Option<TestArg>,
574
}
575

576
impl PartialEq for InstallRustupComponentInfo {
577 8
    fn eq(&self, other: &InstallRustupComponentInfo) -> bool {
578 8
        if self.rustup_component_name != other.rustup_component_name {
579 8
            false
580
        } else {
581 8
            let same = match self.binary {
582 8
                Some(ref value) => match other.binary {
583 8
                    Some(ref other_value) => value == other_value,
584 8
                    None => false,
585
                },
586 0
                None => match other.binary {
587 8
                    None => true,
588 0
                    _ => false,
589
                },
590
            };
591

592 8
            if same {
593 8
                self.test_arg == other.test_arg
594
            } else {
595 8
                false
596
            }
597
        }
598 8
    }
599
}
600

601 8
#[derive(Serialize, Deserialize, Debug, Clone)]
602
#[serde(untagged)]
603
/// Install crate name or params
604
pub enum InstallCrate {
605
    /// The value as string
606 8
    Value(String),
607
    /// Install crate params
608 8
    CrateInfo(InstallCrateInfo),
609
    /// Install rustup component params
610 8
    RustupComponentInfo(InstallRustupComponentInfo),
611
    /// Install cargo plugin info
612 0
    CargoPluginInfo(InstallCargoPluginInfo),
613
}
614

615
impl PartialEq for InstallCrate {
616 8
    fn eq(&self, other: &InstallCrate) -> bool {
617 8
        match self {
618 8
            InstallCrate::Value(value) => match other {
619 8
                InstallCrate::Value(other_value) => value == other_value,
620 0
                _ => false,
621
            },
622 8
            InstallCrate::CargoPluginInfo(info) => match other {
623 8
                InstallCrate::CargoPluginInfo(other_info) => info == other_info,
624 0
                _ => false,
625
            },
626 8
            InstallCrate::CrateInfo(info) => match other {
627 8
                InstallCrate::CrateInfo(other_info) => info == other_info,
628 0
                _ => false,
629
            },
630 8
            InstallCrate::RustupComponentInfo(info) => match other {
631 8
                InstallCrate::RustupComponentInfo(other_info) => info == other_info,
632 0
                _ => false,
633
            },
634
        }
635 8
    }
636
}
637

638 8
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
639
#[serde(untagged)]
640
/// Holds the run task name/s
641
pub enum RunTaskName {
642
    /// Single task name
643 8
    Single(String),
644
    /// Multiple task names
645 8
    Multiple(Vec<String>),
646
}
647

648 8
#[derive(Serialize, Deserialize, Debug, Clone)]
649
/// Holds the run task information
650
pub struct RunTaskDetails {
651
    /// The task name
652 8
    pub name: RunTaskName,
653
    /// True to fork the task to a new sub process
654 8
    pub fork: Option<bool>,
655
    /// True to run all tasks in parallel (default false)
656 8
    pub parallel: Option<bool>,
657
    /// Cleanup task name
658 8
    pub cleanup_task: Option<String>,
659
}
660

661 8
#[derive(Serialize, Deserialize, Debug, Clone)]
662
/// Holds the run task routing information
663
pub struct RunTaskRoutingInfo {
664
    /// The task name
665 8
    pub name: RunTaskName,
666
    /// True to fork the task to a new sub process
667 8
    pub fork: Option<bool>,
668
    /// True to run all tasks in parallel (default false)
669 8
    pub parallel: Option<bool>,
670
    /// Cleanup task name
671 8
    pub cleanup_task: Option<String>,
672
    /// if provided all condition values must be met in order for the task to be invoked
673 8
    pub condition: Option<TaskCondition>,
674
    /// if script exit code is not 0, the task will not be invoked
675 8
    pub condition_script: Option<Vec<String>>,
676
}
677

678 8
#[derive(Serialize, Deserialize, Debug, Clone)]
679
#[serde(untagged)]
680
/// Run task info
681
pub enum RunTaskInfo {
682
    /// Task name
683 8
    Name(String),
684
    /// Run Task Info
685 8
    Details(RunTaskDetails),
686
    /// Task conditional selector
687 8
    Routing(Vec<RunTaskRoutingInfo>),
688
}
689

690 0
#[derive(Serialize, Deserialize, Debug, Clone)]
691
/// Holds watch options
692
pub struct WatchOptions {
693
    /// Watch version to install if not already installed
694 0
    pub version: Option<String>,
695
    /// Postpone first run until a file changes
696 0
    pub postpone: Option<bool>,
697
    /// Ignore a glob/gitignore-style pattern
698 0
    pub ignore_pattern: Option<String>,
699
    /// Do not use .gitignore files
700 0
    pub no_git_ignore: Option<bool>,
701
    /// Select which files/folders to watch
702 0
    pub watch: Option<Vec<String>>,
703
}
704

705
impl PartialEq for WatchOptions {
706 0
    fn eq(&self, other: &WatchOptions) -> bool {
707 0
        let mut same = match self.version {
708 0
            Some(ref value) => match other.version {
709 0
                Some(ref other_value) => value == other_value,
710 0
                None => false,
711
            },
712 0
            None => match other.version {
713 0
                None => true,
714 0
                _ => false,
715
            },
716
        };
717

718 0
        same = if same {
719 0
            match self.postpone {
720 0
                Some(ref value) => match other.postpone {
721 0
                    Some(ref other_value) => value == other_value,
722 0
                    None => false,
723
                },
724 0
                None => match other.postpone {
725 0
                    None => true,
726 0
                    _ => false,
727
                },
728
            }
729
        } else {
730 0
            false
731
        };
732

733 0
        same = if same {
734 0
            match self.ignore_pattern {
735 0
                Some(ref value) => match other.ignore_pattern {
736 0
                    Some(ref other_value) => value == other_value,
737 0
                    None => false,
738
                },
739 0
                None => match other.ignore_pattern {
740 0
                    None => true,
741 0
                    _ => false,
742
                },
743
            }
744
        } else {
745 0
            false
746
        };
747

748 0
        same = if same {
749 0
            match self.no_git_ignore {
750 0
                Some(ref value) => match other.no_git_ignore {
751 0
                    Some(ref other_value) => value == other_value,
752 0
                    None => false,
753
                },
754 0
                None => match other.no_git_ignore {
755 0
                    None => true,
756 0
                    _ => false,
757
                },
758
            }
759
        } else {
760 0
            false
761
        };
762

763 0
        if same {
764 0
            match self.watch {
765 0
                Some(ref value) => match other.watch {
766 0
                    Some(ref other_value) => value == other_value,
767 0
                    None => false,
768
                },
769 0
                None => match other.watch {
770 0
                    None => true,
771 0
                    _ => false,
772
                },
773
            }
774
        } else {
775 0
            false
776
        }
777 0
    }
778
}
779

780 8
#[derive(Serialize, Deserialize, Debug, Clone)]
781
#[serde(untagged)]
782
/// Holds watch options or simple true/false value
783
pub enum TaskWatchOptions {
784
    /// True/False to enable/disable watch
785 8
    Boolean(bool),
786
    /// Extended configuration for watch
787 0
    Options(WatchOptions),
788
}
789

790
impl PartialEq for TaskWatchOptions {
791 8
    fn eq(&self, other: &TaskWatchOptions) -> bool {
792 8
        match self {
793 8
            TaskWatchOptions::Boolean(value) => match other {
794 8
                TaskWatchOptions::Boolean(other_value) => value == other_value,
795 0
                _ => false,
796
            },
797 0
            TaskWatchOptions::Options(info) => match other {
798 0
                TaskWatchOptions::Options(other_info) => info == other_info,
799 0
                _ => false,
800
            },
801
        }
802 8
    }
803
}
804

805 8
#[derive(Serialize, Deserialize, Debug, Clone)]
806
#[serde(untagged)]
807
/// Holds deprecation info such as true/false/message
808
pub enum DeprecationInfo {
809
    /// True/False flag (true is deprecated)
810 8
    Boolean(bool),
811
    /// Deprecation message
812 8
    Message(String),
813
}
814

815
impl PartialEq for DeprecationInfo {
816 8
    fn eq(&self, other: &DeprecationInfo) -> bool {
817 8
        match self {
818 8
            DeprecationInfo::Boolean(value) => match other {
819 8
                DeprecationInfo::Boolean(other_value) => value == other_value,
820 8
                _ => false,
821
            },
822 8
            DeprecationInfo::Message(message) => match other {
823 8
                DeprecationInfo::Message(other_message) => message == other_message,
824 0
                _ => false,
825
            },
826
        }
827 8
    }
828
}
829

830 0
#[derive(Serialize, Deserialize, Debug, Clone)]
831
/// Script file name
832
pub struct FileScriptValue {
833
    /// Script file name
834 0
    pub file: String,
835
    /// True for absolute path (default false)
836 0
    pub absolute_path: Option<bool>,
837
}
838

839 8
#[derive(Serialize, Deserialize, Debug, Clone)]
840
#[serde(untagged)]
841
/// Script value (text, file name, ...)
842
pub enum ScriptValue {
843
    /// The script text lines
844 8
    Text(Vec<String>),
845
    /// Script file name
846 0
    File(FileScriptValue),
847
}
848

849 8
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
850
/// Holds a single task configuration such as command and dependencies list
851
pub struct Task {
852
    /// if true, it should ignore all data in base task
853 8
    pub clear: Option<bool>,
854
    /// Task description
855 8
    pub description: Option<String>,
856
    /// Category name used to document the task
857 8
    pub category: Option<String>,
858
    /// if true, the command/script of this task will not be invoked, dependencies however will be
859 8
    pub disabled: Option<bool>,
860
    /// if true, the task is hidden from the list of available tasks and also cannot be invoked directly from cli
861 8
    pub private: Option<bool>,
862
    /// if not false, this task is defined as deprecated
863 8
    pub deprecated: Option<DeprecationInfo>,
864
    /// Extend any task based on the defined name
865 8
    pub extend: Option<String>,
866
    /// set to false to notify cargo-make that this is not a workspace and should not call task for every member (same as --no-workspace CLI flag)
867 8
    pub workspace: Option<bool>,
868
    /// set to true to watch for file changes and invoke the task operation
869 8
    pub watch: Option<TaskWatchOptions>,
870
    /// if provided all condition values must be met in order for the task to be invoked (will not stop dependencies)
871 8
    pub condition: Option<TaskCondition>,
872
    /// if script exit code is not 0, the command/script of this task will not be invoked, dependencies however will be
873 8
    pub condition_script: Option<Vec<String>>,
874
    /// if true, any error while executing the task will be printed but will not break the build
875 8
    pub ignore_errors: Option<bool>,
876
    /// DEPRECATED, replaced with ignore_errors
877 8
    pub force: Option<bool>,
878
    /// The env files to setup before running the task commands
879 8
    pub env_files: Option<Vec<EnvFile>>,
880
    /// The env vars to setup before running the task commands
881 8
    pub env: Option<IndexMap<String, EnvValue>>,
882
    /// The working directory for the task to execute its command/script
883 8
    pub cwd: Option<String>,
884
    /// if defined, task points to another task and all other properties are ignored
885 8
    pub alias: Option<String>,
886
    /// acts like alias if runtime OS is Linux (takes precedence over alias)
887 8
    pub linux_alias: Option<String>,
888
    /// acts like alias if runtime OS is Windows (takes precedence over alias)
889 8
    pub windows_alias: Option<String>,
890
    /// acts like alias if runtime OS is Mac (takes precedence over alias)
891 8
    pub mac_alias: Option<String>,
892
    /// if defined, the provided crate will be installed (if needed) before running the task
893 8
    pub install_crate: Option<InstallCrate>,
894
    /// additional cargo install arguments
895 8
    pub install_crate_args: Option<Vec<String>>,
896
    /// if defined, the provided script will be executed before running the task
897 8
    pub install_script: Option<Vec<String>>,
898
    /// The command to execute
899 8
    pub command: Option<String>,
900
    /// The command args
901 8
    pub args: Option<Vec<String>>,
902
    /// If command is not defined, and script is defined, the provided script will be executed
903 8
    pub script: Option<ScriptValue>,
904
    /// The script runner (defaults to cmd in windows and sh for other platforms)
905 8
    pub script_runner: Option<String>,
906
    /// The script runner arguments before the script file path
907 8
    pub script_runner_args: Option<Vec<String>>,
908
    /// The script file extension
909 8
    pub script_extension: Option<String>,
910
    /// The task name to execute
911 8
    pub run_task: Option<RunTaskInfo>,
912
    /// A list of tasks to execute before this task
913 8
    pub dependencies: Option<Vec<String>>,
914
    /// The rust toolchain used to invoke the command or install the needed crates/components
915 8
    pub toolchain: Option<String>,
916
    /// override task if runtime OS is Linux (takes precedence over alias)
917 8
    pub linux: Option<PlatformOverrideTask>,
918
    /// override task if runtime OS is Windows (takes precedence over alias)
919 8
    pub windows: Option<PlatformOverrideTask>,
920
    /// override task if runtime OS is Mac (takes precedence over alias)
921 8
    pub mac: Option<PlatformOverrideTask>,
922
}
923

924
impl Task {
925
    /// Creates and returns a new instance.
926 8
    pub fn new() -> Task {
927 8
        Default::default()
928 8
    }
929

930
    /// Apply modifications
931 8
    pub fn apply(self: &mut Task, modify_config: &ModifyConfig) {
932 8
        match modify_config.private {
933 8
            Some(value) => {
934 8
                if value {
935 8
                    self.private = Some(true);
936
                }
937
            }
938
            None => (),
939
        };
940

941 8
        match modify_config.namespace {
942 8
            Some(ref namespace) => {
943 8
                if namespace.len() > 0 {
944 8
                    if self.extend.is_some() {
945 8
                        self.extend = Some(get_namespaced_task_name(
946 8
                            namespace,
947 8
                            &self.extend.clone().unwrap(),
948 8
                        ));
949
                    }
950

951 8
                    if self.alias.is_some() {
952 8
                        self.alias = Some(get_namespaced_task_name(
953 8
                            namespace,
954 8
                            &self.alias.clone().unwrap(),
955 8
                        ));
956
                    }
957

958 8
                    if self.linux_alias.is_some() {
959 8
                        self.linux_alias = Some(get_namespaced_task_name(
960 8
                            namespace,
961 8
                            &self.linux_alias.clone().unwrap(),
962 8
                        ));
963
                    }
964

965 8
                    if self.windows_alias.is_some() {
966 8
                        self.windows_alias = Some(get_namespaced_task_name(
967 8
                            namespace,
968 8
                            &self.windows_alias.clone().unwrap(),
969 8
                        ));
970
                    }
971

972 8
                    if self.mac_alias.is_some() {
973 8
                        self.mac_alias = Some(get_namespaced_task_name(
974 8
                            namespace,
975 8
                            &self.mac_alias.clone().unwrap(),
976 8
                        ));
977
                    }
978

979 8
                    if self.run_task.is_some() {
980 8
                        let mut run_task = self.run_task.clone().unwrap();
981

982 8
                        run_task = match run_task {
983 8
                            RunTaskInfo::Name(value) => {
984 8
                                RunTaskInfo::Name(get_namespaced_task_name(namespace, &value))
985 6
                            }
986 8
                            RunTaskInfo::Details(mut run_task_details) => {
987 8
                                match run_task_details.name {
988 8
                                    RunTaskName::Single(ref name) => {
989 8
                                        run_task_details.name = RunTaskName::Single(
990 8
                                            get_namespaced_task_name(namespace, name),
991
                                        )
992
                                    }
993 8
                                    RunTaskName::Multiple(ref names) => {
994 8
                                        let mut updated_names = vec![];
995 8
                                        for name in names {
996 8
                                            updated_names
997 8
                                                .push(get_namespaced_task_name(namespace, name));
998
                                        }
999

1000 8
                                        run_task_details.name =
1001 8
                                            RunTaskName::Multiple(updated_names);
1002 8
                                    }
1003
                                };
1004

1005 8
                                RunTaskInfo::Details(run_task_details)
1006 0
                            }
1007 8
                            RunTaskInfo::Routing(mut routing_info_vector) => {
1008 8
                                for mut routing_info in &mut routing_info_vector {
1009 8
                                    match routing_info.name {
1010 8
                                        RunTaskName::Single(ref name) => {
1011 8
                                            routing_info.name = RunTaskName::Single(
1012 8
                                                get_namespaced_task_name(namespace, name),
1013
                                            )
1014
                                        }
1015 8
                                        RunTaskName::Multiple(ref names) => {
1016 8
                                            let mut updated_names = vec![];
1017 8
                                            for name in names {
1018 8
                                                updated_names.push(get_namespaced_task_name(
1019 8
                                                    namespace, name,
1020
                                                ));
1021
                                            }
1022

1023 8
                                            routing_info.name =
1024 8
                                                RunTaskName::Multiple(updated_names);
1025 8
                                        }
1026
                                    };
1027
                                }
1028

1029 8
                                RunTaskInfo::Routing(routing_info_vector)
1030 0
                            }
1031 0
                        };
1032

1033 8
                        self.run_task = Some(run_task);
1034 8
                    }
1035

1036 8
                    if self.dependencies.is_some() {
1037 8
                        let dependencies = self.dependencies.clone().unwrap();
1038 8
                        let mut modified_dependencies = vec![];
1039

1040 8
                        for task in &dependencies {
1041 8
                            modified_dependencies.push(get_namespaced_task_name(namespace, &task));
1042
                        }
1043

1044 8
                        self.dependencies = Some(modified_dependencies);
1045 8
                    }
1046
                }
1047
            }
1048
            None => (),
1049
        };
1050 8
    }
1051

1052
    /// Copies values from the task into self.
1053
    ///
1054
    /// # Arguments
1055
    ///
1056
    /// * `task` - The task to copy from
1057 8
    pub fn extend(self: &mut Task, task: &Task) {
1058 8
        let override_values = match task.clear {
1059 8
            Some(value) => value,
1060 8
            None => false,
1061
        };
1062

1063 8
        if task.clear.is_some() {
1064 8
            self.clear = task.clear.clone();
1065
        }
1066

1067 8
        if task.description.is_some() {
1068 8
            self.description = task.description.clone();
1069 8
        } else if override_values {
1070 8
            self.description = None;
1071
        }
1072

1073 8
        if task.category.is_some() {
1074 8
            self.category = task.category.clone();
1075 8
        } else if override_values {
1076 8
            self.category = None;
1077
        }
1078

1079 8
        if task.disabled.is_some() {
1080 8
            self.disabled = task.disabled.clone();
1081 8
        } else if override_values {
1082 8
            self.disabled = None;
1083
        }
1084

1085 8
        if task.private.is_some() {
1086 8
            self.private = task.private.clone();
1087 8
        } else if override_values {
1088 8
            self.private = None;
1089
        }
1090

1091 8
        if task.deprecated.is_some() {
1092 8
            self.deprecated = task.deprecated.clone();
1093 8
        } else if override_values {
1094 8
            self.deprecated = None;
1095
        }
1096

1097 8
        if task.extend.is_some() {
1098 8
            self.extend = task.extend.clone();
1099 8
        } else if override_values {
1100 8
            self.extend = None;
1101
        }
1102

1103 8
        if task.workspace.is_some() {
1104 8
            self.workspace = task.workspace.clone();
1105 8
        } else if override_values {
1106 8
            self.workspace = None;
1107
        }
1108

1109 8
        if task.watch.is_some() {
1110 8
            self.watch = task.watch.clone();
1111 8
        } else if override_values {
1112 8
            self.watch = None;
1113
        }
1114

1115 8
        if task.condition.is_some() {
1116 8
            self.condition = task.condition.clone();
1117 8
        } else if override_values {
1118 8
            self.condition = None;
1119
        }
1120

1121 8
        if task.condition_script.is_some() {
1122 8
            self.condition_script = task.condition_script.clone();
1123 8
        } else if override_values {
1124 8
            self.condition_script = None;
1125
        }
1126

1127 8
        if task.ignore_errors.is_some() {
1128 8
            self.ignore_errors = task.ignore_errors.clone();
1129 8
        } else if override_values {
1130 8
            self.ignore_errors = None;
1131
        }
1132

1133 8
        if task.force.is_some() {
1134 8
            self.force = task.force.clone();
1135 8
        } else if override_values {
1136 8
            self.force = None;
1137
        }
1138

1139 8
        if task.env_files.is_some() {
1140 8
            self.env_files = task.env_files.clone();
1141 8
        } else if override_values {
1142 8
            self.env_files = None;
1143
        }
1144

1145 8
        if task.env.is_some() {
1146 8
            self.env = task.env.clone();
1147 8
        } else if override_values {
1148 8
            self.env = None;
1149
        }
1150

1151 8
        if task.cwd.is_some() {
1152 8
            self.cwd = task.cwd.clone();
1153 8
        } else if override_values {
1154 8
            self.cwd = None;
1155
        }
1156

1157 8
        if task.alias.is_some() {
1158 8
            self.alias = task.alias.clone();
1159 8
        } else if override_values {
1160 8
            self.alias = None;
1161
        }
1162

1163 8
        if task.linux_alias.is_some() {
1164 8
            self.linux_alias = task.linux_alias.clone();
1165 8
        } else if override_values {
1166 8
            self.linux_alias = None;
1167
        }
1168

1169 8
        if task.windows_alias.is_some() {
1170 8
            self.windows_alias = task.windows_alias.clone();
1171 8
        } else if override_values {
1172 8
            self.windows_alias = None;
1173
        }
1174

1175 8
        if task.mac_alias.is_some() {
1176 8
            self.mac_alias = task.mac_alias.clone();
1177 8
        } else if override_values {
1178 8
            self.mac_alias = None;
1179
        }
1180

1181 8
        if task.install_crate.is_some() {
1182 8
            self.install_crate = task.install_crate.clone();
1183 8
        } else if override_values {
1184 8
            self.install_crate = None;
1185
        }
1186

1187 8
        if task.install_crate_args.is_some() {
1188 8
            self.install_crate_args = task.install_crate_args.clone();
1189 8
        } else if override_values {
1190 8
            self.install_crate_args = None;
1191
        }
1192

1193 8
        if task.install_script.is_some() {
1194 8
            self.install_script = task.install_script.clone();
1195 8
        } else if override_values {
1196 8
            self.install_script = None;
1197
        }
1198

1199 8
        if task.command.is_some() {
1200 8
            self.command = task.command.clone();
1201 8
        } else if override_values {
1202 8
            self.command = None;
1203
        }
1204

1205 8
        if task.args.is_some() {
1206 8
            self.args = task.args.clone();
1207 8
        } else if override_values {
1208 8
            self.args = None;
1209
        }
1210

1211 8
        if task.script.is_some() {
1212 8
            self.script = task.script.clone();
1213 8
        } else if override_values {
1214 8
            self.script = None;
1215
        }
1216

1217 8
        if task.script_runner.is_some() {
1218 8
            self.script_runner = task.script_runner.clone();
1219 8
        } else if override_values {
1220 8
            self.script_runner = None;
1221
        }
1222

1223 8
        if task.script_runner_args.is_some() {
1224 8
            self.script_runner_args = task.script_runner_args.clone();
1225 8
        } else if override_values {
1226 8
            self.script_runner_args = None;
1227
        }
1228

1229 8
        if task.script_extension.is_some() {
1230 8
            self.script_extension = task.script_extension.clone();
1231 8
        } else if override_values {
1232 8
            self.script_extension = None;
1233
        }
1234

1235 8
        if task.run_task.is_some() {
1236 8
            self.run_task = task.run_task.clone();
1237 8
        } else if override_values {
1238 8
            self.run_task = None;
1239
        }
1240

1241 8
        if task.dependencies.is_some() {
1242 8
            self.dependencies = task.dependencies.clone();
1243 8
        } else if override_values {
1244 8
            self.dependencies = None;
1245
        }
1246

1247 8
        if task.toolchain.is_some() {
1248 8
            self.toolchain = task.toolchain.clone();
1249 8
        } else if override_values {
1250 8
            self.toolchain = None;
1251
        }
1252

1253 8
        if task.linux.is_some() {
1254 8
            self.linux = task.linux.clone();
1255 8
        } else if override_values {
1256 8
            self.linux = None;
1257
        }
1258

1259 8
        if task.windows.is_some() {
1260 8
            self.windows = task.windows.clone();
1261 8
        } else if override_values {
1262 8
            self.windows = None;
1263
        }
1264

1265 8
        if task.mac.is_some() {
1266 8
            self.mac = task.mac.clone();
1267 8
        } else if override_values {
1268 8
            self.mac = None;
1269
        }
1270 8
    }
1271

1272
    /// Returns true if the task ignore_errors attribute is defined and true
1273 8
    pub fn should_ignore_errors(self: &Task) -> bool {
1274 8
        match self.ignore_errors {
1275 8
            Some(value) => value,
1276 8
            None => match self.force {
1277 8
                Some(value) => {
1278 8
                    legacy::show_deprecated_attriute_warning("force", "ignore_errors");
1279

1280 8
                    value
1281
                }
1282 8
                None => false,
1283
            },
1284
        }
1285 8
    }
1286

1287
    /// Returns the override task definition based on the current platform.
1288 8
    fn get_override(self: &Task) -> Option<PlatformOverrideTask> {
1289 8
        let platform_name = get_platform_name();
1290 8
        if platform_name == "windows" {
1291 0
            match self.windows {
1292 0
                Some(ref value) => Some(value.clone()),
1293 0
                _ => None,
1294
            }
1295 8
        } else if platform_name == "mac" {
1296 0
            match self.mac {
1297 0
                Some(ref value) => Some(value.clone()),
1298 0
                _ => None,
1299
            }
1300
        } else {
1301 8
            match self.linux {
1302 8
                Some(ref value) => Some(value.clone()),
1303 8
                _ => None,
1304
            }
1305
        }
1306 8
    }
1307

1308
    /// Returns a new task based on the override information and current platform.
1309 8
    pub fn get_normalized_task(self: &mut Task) -> Task {
1310 8
        match self.get_override() {
1311 8
            Some(ref mut override_task) => {
1312 8
                override_task.extend(self);
1313

1314 8
                Task {
1315 8
                    clear: self.clear.clone(),
1316 8
                    description: self.description.clone(),
1317 8
                    category: self.category.clone(),
1318 8
                    disabled: override_task.disabled.clone(),
1319 8
                    private: override_task.private.clone(),
1320 8
                    deprecated: override_task.deprecated.clone(),
1321 8
                    extend: override_task.extend.clone(),
1322 8
                    workspace: self.workspace.clone(),
1323 8
                    watch: override_task.watch.clone(),
1324 8
                    condition: override_task.condition.clone(),
1325 8
                    condition_script: override_task.condition_script.clone(),
1326 8
                    ignore_errors: override_task.ignore_errors.clone(),
1327 8
                    force: override_task.force.clone(),
1328 8
                    env_files: override_task.env_files.clone(),
1329 8
                    env: override_task.env.clone(),
1330 8
                    cwd: override_task.cwd.clone(),
1331 8
                    alias: None,
1332 8
                    linux_alias: None,
1333 8
                    windows_alias: None,
1334 8
                    mac_alias: None,
1335 8
                    install_crate: override_task.install_crate.clone(),
1336 8
                    install_crate_args: override_task.install_crate_args.clone(),
1337 8
                    install_script: override_task.install_script.clone(),
1338 8
                    command: override_task.command.clone(),
1339 8
                    args: override_task.args.clone(),
1340 8
                    script: override_task.script.clone(),
1341 8
                    script_runner: override_task.script_runner.clone(),
1342 8
                    script_runner_args: override_task.script_runner_args.clone(),
1343 8
                    script_extension: override_task.script_extension.clone(),
1344 8
                    run_task: override_task.run_task.clone(),
1345 8
                    dependencies: override_task.dependencies.clone(),
1346 8
                    toolchain: override_task.toolchain.clone(),
1347 8
                    linux: None,
1348 8
                    windows: None,
1349 8
                    mac: None,
1350 0
                }
1351
            }
1352 8
            None => self.clone(),
1353
        }
1354 8
    }
1355

1356
    /// Returns the alias value based on the current platform and task definition.
1357 8
    pub fn get_alias(self: &Task) -> Option<String> {
1358 2
        let alias = if cfg!(windows) {
1359 0
            match self.windows_alias {
1360 0
                Some(ref value) => Some(value),
1361 0
                _ => None,
1362
            }
1363 2
        } else if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
1364 0
            match self.mac_alias {
1365 0
                Some(ref value) => Some(value),
1366 0
                _ => None,
1367
            }
1368
        } else {
1369 8
            match self.linux_alias {
1370 8
                Some(ref value) => Some(value),
1371 8
                _ => None,
1372
            }
1373
        };
1374

1375 8
        match alias {
1376 8
            Some(os_alias) => Some(os_alias.clone()),
1377 8
            _ => match self.alias {
1378 8
                Some(ref alias) => Some(alias.clone()),
1379 8
                _ => None,
1380
            },
1381
        }
1382 8
    }
1383

1384
    /// Returns the amount of actions defined on the task
1385 8
    pub fn get_actions_count(self: &Task) -> u8 {
1386 8
        let mut actions_count = 0;
1387

1388 8
        if self.run_task.is_some() {
1389 8
            actions_count = actions_count + 1;
1390
        }
1391 8
        if self.command.is_some() {
1392 8
            actions_count = actions_count + 1;
1393
        }
1394 8
        if self.script.is_some() {
1395 8
            actions_count = actions_count + 1;
1396
        }
1397

1398 2
        actions_count
1399 8
    }
1400

1401
    /// Returns true if the task has any actions on its own
1402
    /// or if it modifies the environment in any way.
1403 8
    pub fn is_actionable(self: &Task) -> bool {
1404 8
        if self.disabled.unwrap_or(false) {
1405 8
            return false;
1406
        }
1407

1408 8
        let actions_count = self.get_actions_count();
1409 8
        if actions_count > 0 {
1410 8
            return true;
1411
        }
1412

1413 8
        if self.install_crate.is_some() || self.install_script.is_some() {
1414 8
            return true;
1415
        }
1416

1417 8
        let mut actionable = match self.env {
1418 8
            Some(ref value) => value.len() > 0,
1419 8
            None => false,
1420
        };
1421 8
        if actionable {
1422 8
            return true;
1423
        }
1424

1425 8
        actionable = match self.env_files {
1426 8
            Some(ref value) => value.len() > 0,
1427 8
            None => false,
1428
        };
1429 8
        if actionable {
1430 8
            return true;
1431
        }
1432

1433 8
        actionable = match self.dependencies {
1434 8
            Some(ref value) => value.len() > 0,
1435 8
            None => false,
1436
        };
1437 8
        if actionable {
1438 8
            return true;
1439
        }
1440

1441 8
        actionable = match self.watch {
1442 8
            Some(ref options) => match options {
1443 8
                TaskWatchOptions::Boolean(value) => *value,
1444 8
                _ => true,
1445
            },
1446 8
            None => false,
1447
        };
1448

1449 8
        actionable
1450 8
    }
1451

1452
    /// Returns true if the task is valid
1453 8
    pub fn is_valid(self: &Task) -> bool {
1454 8
        let actions_count = self.get_actions_count();
1455

1456 8
        if actions_count <= 1 {
1457 2
            true
1458
        } else {
1459 2
            false
1460
        }
1461 8
    }
1462
}
1463

1464 8
#[derive(Serialize, Deserialize, Debug, Clone)]
1465
/// Holds a single task configuration for a specific platform as an override of another task
1466
pub struct PlatformOverrideTask {
1467
    /// if true, it should ignore all data in base task
1468 8
    pub clear: Option<bool>,
1469
    /// if true, the command/script of this task will not be invoked, dependencies however will be
1470 8
    pub disabled: Option<bool>,
1471
    /// if true, the task is hidden from the list of available tasks and also cannot be invoked directly from cli
1472 8
    pub private: Option<bool>,
1473
    /// if not false, this task is defined as deprecated
1474 8
    pub deprecated: Option<DeprecationInfo>,
1475
    /// Extend any task based on the defined name
1476 8
    pub extend: Option<String>,
1477
    /// set to true to watch for file changes and invoke the task operation
1478 8
    pub watch: Option<TaskWatchOptions>,
1479
    /// if provided all condition values must be met in order for the task to be invoked (will not stop dependencies)
1480 8
    pub condition: Option<TaskCondition>,
1481
    /// if script exit code is not 0, the command/script of this task will not be invoked, dependencies however will be
1482 8
    pub condition_script: Option<Vec<String>>,
1483
    /// if true, any error while executing the task will be printed but will not break the build
1484 8
    pub ignore_errors: Option<bool>,
1485
    /// DEPRECATED, replaced with ignore_errors
1486 8
    pub force: Option<bool>,
1487
    /// The env files to setup before running the task commands
1488 8
    pub env_files: Option<Vec<EnvFile>>,
1489
    /// The env vars to setup before running the task commands
1490 8
    pub env: Option<IndexMap<String, EnvValue>>,
1491
    /// The working directory for the task to execute its command/script
1492 8
    pub cwd: Option<String>,
1493
    /// if defined, the provided crate will be installed (if needed) before running the task
1494 8
    pub install_crate: Option<InstallCrate>,
1495
    /// additional cargo install arguments
1496 8
    pub install_crate_args: Option<Vec<String>>,
1497
    /// if defined, the provided script will be executed before running the task
1498 8
    pub install_script: Option<Vec<String>>,
1499
    /// The command to execute
1500 8
    pub command: Option<String>,
1501
    /// The command args
1502 8
    pub args: Option<Vec<String>>,
1503
    /// If command is not defined, and script is defined, the provided script will be executed
1504 8
    pub script: Option<ScriptValue>,
1505
    /// The script runner (defaults to cmd in windows and sh for other platforms)
1506 8
    pub script_runner: Option<String>,
1507
    /// The script runner arguments before the script file path
1508 8
    pub script_runner_args: Option<Vec<String>>,
1509
    /// The script file extension
1510 8
    pub script_extension: Option<String>,
1511
    /// The task name to execute
1512 8
    pub run_task: Option<RunTaskInfo>,
1513
    /// A list of tasks to execute before this task
1514 8
    pub dependencies: Option<Vec<String>>,
1515
    /// The rust toolchain used to invoke the command or install the needed crates/components
1516 8
    pub toolchain: Option<String>,
1517
}
1518

1519
impl PlatformOverrideTask {
1520
    /// Copies values from the task into self.
1521
    ///
1522
    /// # Arguments
1523
    ///
1524
    /// * `task` - The task to copy from
1525 8
    pub fn extend(self: &mut PlatformOverrideTask, task: &mut Task) {
1526 8
        let copy_values = match self.clear {
1527 8
            Some(value) => !value,
1528 8
            None => true,
1529
        };
1530

1531 8
        if copy_values {
1532 8
            if self.disabled.is_none() && task.disabled.is_some() {
1533 8
                self.disabled = task.disabled.clone();
1534
            }
1535

1536 8
            if self.private.is_none() && task.private.is_some() {
1537 8
                self.private = task.private.clone();
1538
            }
1539

1540 8
            if self.deprecated.is_none() && task.deprecated.is_some() {
1541 8
                self.deprecated = task.deprecated.clone();
1542
            }
1543

1544 8
            if self.extend.is_none() && task.extend.is_some() {
1545 8
                self.extend = task.extend.clone();
1546
            }
1547

1548 8
            if self.watch.is_none() && task.watch.is_some() {
1549 8
                self.watch = task.watch.clone();
1550
            }
1551

1552 8
            if self.condition.is_none() && task.condition.is_some() {
1553 8
                self.condition = task.condition.clone();
1554
            }
1555

1556 8
            if self.condition_script.is_none() && task.condition_script.is_some() {
1557 8
                self.condition_script = task.condition_script.clone();
1558
            }
1559

1560 8
            if self.ignore_errors.is_none() && task.ignore_errors.is_some() {
1561 8
                self.ignore_errors = task.ignore_errors.clone();
1562
            }
1563

1564 8
            if self.force.is_none() && task.force.is_some() {
1565 8
                self.force = task.force.clone();
1566
            }
1567

1568 8
            if self.env_files.is_none() && task.env_files.is_some() {
1569 8
                self.env_files = task.env_files.clone();
1570
            }
1571

1572 8
            if self.env.is_none() && task.env.is_some() {
1573 8
                self.env = task.env.clone();
1574
            }
1575

1576 8
            if self.cwd.is_none() && task.cwd.is_some() {
1577 8
                self.cwd = task.cwd.clone();
1578
            }
1579

1580 8
            if self.install_crate.is_none() && task.install_crate.is_some() {
1581 8
                self.install_crate = task.install_crate.clone();
1582
            }
1583

1584 8
            if self.install_crate_args.is_none() && task.install_crate_args.is_some() {
1585 8
                self.install_crate_args = task.install_crate_args.clone();
1586
            }
1587

1588 8
            if self.install_script.is_none() && task.install_script.is_some() {
1589 8
                self.install_script = task.install_script.clone();
1590
            }
1591

1592 8
            if self.command.is_none() && task.command.is_some() {
1593 8
                self.command = task.command.clone();
1594
            }
1595

1596 8
            if self.args.is_none() && task.args.is_some() {
1597 8
                self.args = task.args.clone();
1598
            }
1599

1600 8
            if self.script.is_none() && task.script.is_some() {
1601 8
                self.script = task.script.clone();
1602
            }
1603

1604 8
            if self.script_runner.is_none() && task.script_runner.is_some() {
1605 8
                self.script_runner = task.script_runner.clone();
1606
            }
1607

1608 8
            if self.script_runner_args.is_none() && task.script_runner_args.is_some() {
1609 8
                self.script_runner_args = task.script_runner_args.clone();
1610
            }
1611

1612 8
            if self.script_extension.is_none() && task.script_extension.is_some() {
1613 8
                self.script_extension = task.script_extension.clone();
1614
            }
1615

1616 8
            if self.run_task.is_none() && task.run_task.is_some() {
1617 8
                self.run_task = task.run_task.clone();
1618
            }
1619

1620 8
            if self.dependencies.is_none() && task.dependencies.is_some() {
1621 8
                self.dependencies = task.dependencies.clone();
1622
            }
1623

1624 8
            if self.toolchain.is_none() && task.toolchain.is_some() {
1625 8
                self.toolchain = task.toolchain.clone();
1626
            }
1627
        }
1628 8
    }
1629
}
1630

1631 2
#[derive(Serialize, Deserialize, Debug, Clone)]
1632
/// Extend with more fine tuning options
1633
pub struct ExtendOptions {
1634
    /// Path to another makefile
1635 2
    pub path: String,
1636
    /// Enable optional extend (default to false)
1637 2
    pub optional: Option<bool>,
1638
}
1639

1640 8
#[derive(Serialize, Deserialize, Debug, Clone)]
1641
#[serde(untagged)]
1642
/// Holds makefile extend value
1643
pub enum Extend {
1644
    /// Path to another makefile
1645 8
    Path(String),
1646
    /// Extend options for more fine tune control
1647 0
    Options(ExtendOptions),
1648
    /// Multiple extends list
1649 0
    List(Vec<ExtendOptions>),
1650
}
1651

1652 8
#[derive(Serialize, Deserialize, Debug, Clone)]
1653
/// Holds properties to modify the core tasks
1654
pub struct ModifyConfig {
1655
    /// If true, all core tasks will be set to private (default false)
1656 8
    pub private: Option<bool>,
1657
    /// If set to some value, all core tasks are modified to: <namespace>::<name> for example default::build
1658 8
    pub namespace: Option<String>,
1659
}
1660

1661
impl ModifyConfig {
1662
    /// Returns true if config modifications is needed based on the current state
1663 2
    pub fn is_modifications_defined(self: &ModifyConfig) -> bool {
1664 2
        if self.private.unwrap_or(false) {
1665 2
            true
1666
        } else {
1667 0
            match self.namespace {
1668 0
                Some(ref value) => value.len() > 0,
1669 0
                None => false,
1670
            }
1671
        }
1672 2
    }
1673

1674
    /// Returns the namespace prefix for task names
1675 8
    pub fn get_namespace_prefix(self: &ModifyConfig) -> String {
1676 8
        match self.namespace {
1677 8
            Some(ref value) => get_namespaced_task_name(value, ""),
1678 0
            None => "".to_string(),
1679
        }
1680 8
    }
1681
}
1682

1683 8
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
1684
/// Holds the configuration found in the makefile toml config section.
1685
pub struct ConfigSection {
1686
    /// If true, the default core tasks will not be loaded
1687 8
    pub skip_core_tasks: Option<bool>,
1688
    /// Modify core tasks config
1689 8
    pub modify_core_tasks: Option<ModifyConfig>,
1690
    /// Init task name which will be invoked at the start of every run
1691 8
    pub init_task: Option<String>,
1692
    /// End task name which will be invoked at the end of every run
1693 8
    pub end_task: Option<String>,
1694
    /// The name of the task to run in case of any error during the invocation of the flow
1695 8
    pub on_error_task: Option<String>,
1696
    /// Additional profile names to load
1697 8
    pub additional_profiles: Option<Vec<String>>,
1698
    /// Minimum cargo-make/makers version
1699 8
    pub min_version: Option<String>,
1700
    /// The task.workspace default value
1701 8
    pub default_to_workspace: Option<bool>,
1702
    /// True to reduce console output for non CI execution
1703 8
    pub reduce_output: Option<bool>,
1704
    /// True to print time summary at the end of the flow
1705 8
    pub time_summary: Option<bool>,
1706
    /// The project information member (used by workspaces)
1707 8
    pub main_project_member: Option<String>,
1708
    /// Invoked while loading the descriptor file but before loading any extended descriptor
1709 8
    pub load_script: Option<Vec<String>>,
1710
    /// acts like load_script if runtime OS is Linux (takes precedence over load_script)
1711 8
    pub linux_load_script: Option<Vec<String>>,
1712
    /// acts like load_script if runtime OS is Windows (takes precedence over load_script)
1713 8
    pub windows_load_script: Option<Vec<String>>,
1714
    /// acts like load_script if runtime OS is Mac (takes precedence over load_script)
1715 8
    pub mac_load_script: Option<Vec<String>>,
1716
}
1717

1718
impl ConfigSection {
1719
    /// Creates and returns a new instance.
1720 8
    pub fn new() -> ConfigSection {
1721 8
        Default::default()
1722 8
    }
1723

1724
    /// Apply modifications
1725 8
    pub fn apply(self: &mut ConfigSection, modify_config: &ModifyConfig) {
1726 8
        match modify_config.namespace {
1727 8
            Some(ref namespace) => {
1728 8
                if self.init_task.is_some() {
1729 8
                    self.init_task = Some(get_namespaced_task_name(
1730 8
                        namespace,
1731 8
                        &self.init_task.clone().unwrap(),
1732 8
                    ));
1733
                }
1734

1735 8
                if self.end_task.is_some() {
1736 8
                    self.end_task = Some(get_namespaced_task_name(
1737 8
                        namespace,
1738 8
                        &self.end_task.clone().unwrap(),
1739 8
                    ));
1740
                }
1741

1742 8
                if self.on_error_task.is_some() {
1743 8
                    self.on_error_task = Some(get_namespaced_task_name(
1744 8
                        namespace,
1745 8
                        &self.on_error_task.clone().unwrap(),
1746 8
                    ));
1747
                }
1748
            }
1749
            None => (),
1750
        }
1751 8
    }
1752

1753
    /// Copies values from the config section into self.
1754
    ///
1755
    /// # Arguments
1756
    ///
1757
    /// * `task` - The task to copy from
1758 8
    pub fn extend(self: &mut ConfigSection, extended: &mut ConfigSection) {
1759 8
        if extended.skip_core_tasks.is_some() {
1760 8
            self.skip_core_tasks = extended.skip_core_tasks.clone();
1761
        }
1762

1763 8
        if extended.modify_core_tasks.is_some() {
1764 8
            self.modify_core_tasks = extended.modify_core_tasks.clone();
1765
        }
1766

1767 8
        if extended.init_task.is_some() {
1768 8
            self.init_task = extended.init_task.clone();
1769
        }
1770

1771 8
        if extended.end_task.is_some() {
1772 8
            self.end_task = extended.end_task.clone();
1773
        }
1774

1775 8
        if extended.on_error_task.is_some() {
1776 8
            self.on_error_task = extended.on_error_task.clone();
1777
        }
1778

1779 8
        if extended.additional_profiles.is_some() {
1780 8
            self.additional_profiles = extended.additional_profiles.clone();
1781
        }
1782

1783 8
        if extended.min_version.is_some() {
1784 8
            self.min_version = extended.min_version.clone();
1785
        }
1786

1787 8
        if extended.default_to_workspace.is_some() {
1788 8
            self.default_to_workspace = extended.default_to_workspace.clone();
1789
        }
1790

1791 8
        if extended.reduce_output.is_some() {
1792 8
            self.reduce_output = extended.reduce_output.clone();
1793
        }
1794

1795 8
        if extended.time_summary.is_some() {
1796 8
            self.time_summary = extended.time_summary.clone();
1797
        }
1798

1799 8
        if extended.main_project_member.is_some() {
1800 0
            self.main_project_member = extended.main_project_member.clone();
1801
        }
1802

1803 8
        if extended.load_script.is_some() {
1804 8
            self.load_script = extended.load_script.clone();
1805
        }
1806

1807 8
        if extended.linux_load_script.is_some() {
1808 8
            self.linux_load_script = extended.linux_load_script.clone();
1809
        }
1810

1811 8
        if extended.windows_load_script.is_some() {
1812 8
            self.windows_load_script = extended.windows_load_script.clone();
1813
        }
1814

1815 8
        if extended.mac_load_script.is_some() {
1816 8
            self.mac_load_script = extended.mac_load_script.clone();
1817
        }
1818 8
    }
1819

1820
    /// Returns the load script based on the current platform
1821 8
    pub fn get_load_script(self: &ConfigSection) -> Option<Vec<String>> {
1822 8
        let platform_name = get_platform_name();
1823

1824 8
        if platform_name == "windows" {
1825 0
            if self.windows_load_script.is_some() {
1826 0
                self.windows_load_script.clone()
1827
            } else {
1828 0
                self.load_script.clone()
1829
            }
1830 8
        } else if platform_name == "mac" {
1831 0
            if self.mac_load_script.is_some() {
1832 0
                self.mac_load_script.clone()
1833
            } else {
1834 0
                self.load_script.clone()
1835
            }
1836
        } else {
1837 8
            if self.linux_load_script.is_some() {
1838 8
                self.linux_load_script.clone()
1839
            } else {
1840 8
                self.load_script.clone()
1841
            }
1842
        }
1843 8
    }
1844
}
1845

1846 8
#[derive(Serialize, Deserialize, Debug, Clone)]
1847
/// Holds the entire configuration such as task definitions and env vars
1848
pub struct Config {
1849
    /// Runtime config
1850 8
    pub config: ConfigSection,
1851
    /// The env files to setup before running the flow
1852 8
    pub env_files: Vec<EnvFile>,
1853
    /// The env vars to setup before running the flow
1854 8
    pub env: IndexMap<String, EnvValue>,
1855
    /// The env scripts to execute before running the flow
1856 8
    pub env_scripts: Vec<String>,
1857
    /// All task definitions
1858 8
    pub tasks: IndexMap<String, Task>,
1859
}
1860

1861
impl Config {
1862
    /// Apply modifications
1863 8
    pub fn apply(self: &mut Config, modify_config: &ModifyConfig) {
1864 8
        self.config.apply(&modify_config);
1865

1866 8
        let namespace = match modify_config.namespace {
1867 8
            Some(ref namespace) => namespace,
1868 8
            None => "",
1869
        };
1870

1871 8
        let mut modified_tasks = IndexMap::<String, Task>::new();
1872

1873 8
        for (key, value) in self.tasks.iter() {
1874 8
            let namespaced_task = get_namespaced_task_name(namespace, &key);
1875 8
            let mut task = value.clone();
1876

1877 8
            task.apply(&modify_config);
1878

1879 8
            modified_tasks.insert(namespaced_task, task);
1880 8
        }
1881

1882 8
        self.tasks = modified_tasks;
1883 8
    }
1884
}
1885

1886 8
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
1887
/// Holds the entire externally read configuration such as task definitions and env vars where all values are optional
1888
pub struct ExternalConfig {
1889
    /// Path to another toml file to extend
1890 8
    pub extend: Option<Extend>,
1891
    /// Runtime config
1892 8
    pub config: Option<ConfigSection>,
1893
    /// The env files to setup before running the flow
1894 8
    pub env_files: Option<Vec<EnvFile>>,
1895
    /// The env vars to setup before running the flow
1896 8
    pub env: Option<IndexMap<String, EnvValue>>,
1897
    /// The env scripts to execute before running the flow
1898 8
    pub env_scripts: Option<Vec<String>>,
1899
    /// All task definitions
1900 8
    pub tasks: Option<IndexMap<String, Task>>,
1901
}
1902

1903
impl ExternalConfig {
1904
    /// Creates and returns a new instance.
1905 8
    pub fn new() -> ExternalConfig {
1906 8
        Default::default()
1907 8
    }
1908
}
1909

1910 8
#[derive(Serialize, Debug)]
1911
/// Execution plan step to execute
1912
pub struct Step {
1913
    /// The task name
1914 8
    pub name: String,
1915
    /// The task config
1916 8
    pub config: Task,
1917
}
1918

1919 8
#[derive(Debug)]
1920
/// Execution plan which defines all steps to run and the order to run them
1921
pub struct ExecutionPlan {
1922
    /// A list of steps to execute
1923 8
    pub steps: Vec<Step>,
1924
}
1925

1926
#[derive(Debug)]
1927
/// Command info
1928
pub struct CommandSpec {
1929
    /// The command to execute
1930
    pub command: String,
1931
    /// The command args
1932
    pub args: Option<Vec<String>>,
1933
}
1934

1935 2
#[derive(Debug, Deserialize, Default)]
1936
/// The output of cargo metadata command
1937
pub struct CargoMetadata {
1938
    /// The workspace root path
1939 0
    pub workspace_root: Option<String>,
1940
}
1941

1942
impl CargoMetadata {
1943
    /// Creates and returns a new instance.
1944 0
    pub fn new() -> CargoMetadata {
1945 0
        Default::default()
1946 0
    }
1947
}

Read our documentation on viewing source code .

Loading