1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use anyhow::Result;
use clap::{Parser, Subcommand};

#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// Coverage with tech instrument-coverage, deps llvm-tools-preview & grcov
    Coverage {
        /// generate an html report
        #[arg(short, long, default_value_t = false)]
        dev: bool,
        /// coveralls to stdout for neovim plugin
        #[arg(long, default_value_t = false)]
        neo: bool,
    },
    /// Regular ci tests: fmt, clippy, test
    Ci,
    /// Run cargo docs in watch mode
    Docs,
    /// Bump version and commit
    Bump {
        /// increment version part
        #[arg(default_value = "patch")]
        bump: String,
    },
    /// Publish and bump version auto commit
    Publish,
    /// Holder for per-project distribution receipt
    Dist,
    /// General addon targets
    Rule {
        #[arg(default_value = "default")]
        target: String,
        rule_options: Vec<String>,
    },
}

pub mod ops;

pub trait Addon {
    /// Command dist
    /// # Errors
    /// User throw errors.
    fn dist() -> Result<()> {
        println!("Warning: Empty dist receipt.");
        Ok(())
    }
    /// Command rule
    /// # Errors
    /// User throw errors.
    fn rule(target: String, options: Vec<String>) -> Result<()> {
        println!("Warning: Empty receipt for target {target}, options: {options:?}");
        Ok(())
    }
}

pub trait Make: Addon {
    /// Main entrypoint.
    ///
    /// # Errors
    /// error if tasks failed.
    fn make() -> Result<()> {
        let cli = Cli::parse();
        match &cli.command {
            Commands::Ci => xtaskops::tasks::ci(),
            Commands::Docs => xtaskops::tasks::docs(),
            Commands::Coverage { dev, neo: false } => xtaskops::tasks::coverage(*dev),
            Commands::Coverage { neo: true, .. } => ops::neo_coverage(),
            Commands::Bump { bump } => ops::bump_version(bump),
            Commands::Publish => ops::publish(),
            Commands::Dist => Self::dist(),
            Commands::Rule {
                target,
                rule_options,
            } => Self::rule(target.clone(), rule_options.clone()),
        }
    }
}

impl<T> Make for T where T: Addon {}

struct MakeImpl();
impl Addon for MakeImpl {}

/// Main entrypoint.
///
/// # Errors
/// error if tasks failed.
pub fn make() -> Result<()> {
    MakeImpl::make()
}