Skip to main content

tinyrick/
lib.rs

1//! Common build patterns
2
3extern crate proc_macro;
4extern crate quote;
5extern crate syn;
6extern crate tinyrick_macros;
7extern crate tinyrick_models;
8
9pub use ctor::ctor;
10pub use die::die;
11pub use tinyrick_macros::{default_task, task};
12pub use tinyrick_models::{DEFAULT_TASK, DEPENDENCY_CACHE, TASKS};
13
14use std::env;
15use std::process;
16
17/// Cargo toggle
18pub static FEATURE: &str = "letmeout";
19
20/// Environment name controlling verbosity
21pub static VERBOSE_ENVIRONMENT_NAME: &str = "VERBOSE";
22
23/// deps registers a task prerequisite.
24#[macro_export]
25macro_rules! deps {
26    ($t : expr) => {
27        {
28            let mut has_run = false;
29
30            {
31                let cache_lock = ::tinyrick::DEPENDENCY_CACHE.lock();
32                has_run = match cache_lock {
33                    Err(e) => ::die::die!(1; e.to_string()),
34                    Ok(cache) => cache.contains_key("$t"),
35                };
36            }
37
38            if !has_run {
39                $t();
40
41                let mut cache_lock = ::tinyrick::DEPENDENCY_CACHE.lock();
42
43                match cache_lock {
44                    Err(e) => ::die::die!(1; e.to_string()),
45                    Ok(mut cache) => cache.insert("$t", true),
46                };
47            }
48        }
49    };
50}
51
52/// Show registered tasks
53pub fn list_tasks() {
54    let d = &match DEFAULT_TASK.lock() {
55        Err(e) => die!(1; e.to_string()),
56        Ok(d_guard) => d_guard.unwrap_or(""),
57    };
58
59    if d != &"" {
60        println!("Default Task: {}\n", d);
61    }
62
63    let t_guard = match TASKS.lock() {
64        Err(e) => die!(1; e.to_string()),
65        Ok(guard) => guard,
66    };
67    let mut ts = t_guard.keys().collect::<Vec<&&str>>();
68    ts.sort();
69
70    println!("Tasks:");
71
72    if ts.is_empty() {
73        println!("(none)")
74    }
75
76    for t in ts {
77        println!(" * {}", t);
78    }
79}
80
81/// Run processes task name(s) from CLI arguments.
82pub fn run() {
83    let task_string_names = env::args().collect::<Vec<String>>();
84
85    let mut task_names: Vec<&str> = task_string_names
86        .iter()
87        .skip(1)
88        .map(String::as_str)
89        .collect();
90
91    if task_names.is_empty() {
92        let t_lock = DEFAULT_TASK.lock();
93
94        match t_lock {
95            Err(e) => die!(1; e.to_string()),
96            Ok(t_guard) => match t_guard.as_ref() {
97                Some(t) => task_names.push(t),
98                _ => {
99                    die!(1; "error: missing default task");
100                }
101            },
102        }
103    }
104
105    if task_names.contains(&"-l") || task_names.contains(&"--list") {
106        list_tasks();
107        die!(0);
108    }
109
110    let ts_lock = TASKS.lock();
111    let ts = match ts_lock {
112        Err(e) => die!(1; e.to_string()),
113        Ok(ts_guard) => ts_guard,
114    };
115
116    for task_name in task_names {
117        match ts.get(task_name) {
118            Some(t) => t(),
119            _ => die!(1; format!("error: unknown task: {}", task_name)),
120        }
121    }
122}
123
124/// Query common host binary suffix
125pub fn binary_suffix() -> String {
126    if cfg!(windows) {
127        return ".exe".to_string();
128    }
129
130    String::new()
131}
132
133/// exec runs the given command.
134///
135/// On error, terminates the current process nonzero.
136pub fn exec(command: &str, args: &[&str]) {
137    if command.is_empty() {
138        die!("error: blank command");
139    }
140
141    let command_str = if args.is_empty() {
142        command
143    } else {
144        &format!("{} {}", command, args.join(" "))
145    };
146
147    if env::var(VERBOSE_ENVIRONMENT_NAME).is_ok() {
148        println!("info: running command: {}", command_str);
149    }
150
151    let success = match process::Command::new(command).args(args).status() {
152        Err(e) => die!(format!(
153            "error: unprocessable command: {}: {}",
154            command_str,
155            e.to_string()
156        )),
157        Ok(status) => status.success(),
158    };
159
160    if !success {
161        die!(1; format!("error: command failed: {}", command_str));
162    }
163}
164
165/// exec! runs the given command.
166///
167/// On error, terminates the current process nonzero.
168#[macro_export]
169macro_rules! exec {
170    ($p : expr $(, $a:expr)* $(,)?) => {
171        ::tinyrick::exec($p, &[ $( $a, )* ])
172    };
173}