1use std::process::exit;
2
3pub fn has_binary<'a>(binary_name: impl Into<String>) -> bool {
4 which::which(binary_name.into()).is_ok()
5}
6
7pub fn require_binary(binary_name: impl Into<String>) {
8 let name = binary_name.into();
9
10 if !has_binary(name.clone()) {
11 eprintln!("This program requires '{name}' to be installed");
12 exit(1)
13 }
14}
15pub fn require_binaries(binary_names: Vec<impl Into<String>>) {
16 let missing = get_missing_binaries(binary_names);
17
18 if let Some(missing) = missing {
19 eprintln!("This program requires the following binaries to be installed");
20 for missing in missing {
21 eprintln!(" - {missing}");
22 }
23
24 exit(1)
25 }
26}
27
28pub fn get_missing_binaries<'a>(binary_names: Vec<impl Into<String>>) -> Option<Vec<String>> {
29 let mut missing: Vec<String> = vec![];
30
31 for binary_name in binary_names {
32 let binary_name = binary_name.into();
33 if !has_binary(binary_name.clone()) {
34 missing.push(binary_name);
35 }
36 }
37
38 if missing.is_empty() {
39 return None;
40 }
41
42 return Some(missing);
43}
44
45#[cfg(test)]
46mod test {
47 use crate::*;
48
49 #[test]
50 fn test_has_binary() {
51 assert!(has_binary("cargo"));
52 assert!(!has_binary("oigsuiodfg"));
53 }
54
55 #[test]
56 fn test_get_missing_binaries() {
57 assert!(get_missing_binaries(vec!["cargo", "bash", "rustc", "rustup"]).is_none());
58 assert_eq!(
59 get_missing_binaries(vec![
60 "cargo",
61 "bash",
62 "rustc",
63 "rustup",
64 "random_binary_that_does_not_exist"
65 ]),
66 Some(vec!["random_binary_that_does_not_exist".to_string()])
67 );
68 }
69}