Skip to main content

has_binary/
lib.rs

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}