fpm_core/
utils.rs

1use std::collections::hash_map::DefaultHasher;
2use std::fs;
3use std::hash::{Hash, Hasher};
4use std::io::{stdin, stdout, Write};
5use std::path::Path;
6
7pub const DEFAULT_FLATPAK_BUILDER_CACHE_DIR: &str = ".flatpak-builder/";
8pub const DEFAULT_FLATPAK_BUILDER_OUTPUT_DIR: &str = ".flatpak-builder-out/";
9pub const DEFAULT_GIT_CACHE_DIR: &str = ".git/";
10
11pub fn get_module_hash(module: &flatpak_rs::module::FlatpakModule) -> String {
12    // TODO maybe this should go into flatpak_rs??
13    let mut s = DefaultHasher::new();
14    module.hash(&mut s);
15    s.finish().to_string()
16}
17
18pub fn get_all_paths(dir: &Path) -> Result<Vec<std::path::PathBuf>, String> {
19    let mut all_paths: Vec<std::path::PathBuf> = vec![];
20
21    let dir_entries = match fs::read_dir(dir) {
22        Ok(entries) => entries,
23        Err(err) => {
24            return Err(format!(
25                "Could not read dir {}: {}",
26                dir.to_str().unwrap(),
27                err.to_string()
28            ))
29        }
30    };
31    for entry in dir_entries {
32        let entry_path = entry.unwrap().path();
33        let entry_path_str = match entry_path.to_str() {
34            Some(p) => p,
35            None => continue,
36        };
37        if entry_path_str.contains(DEFAULT_GIT_CACHE_DIR) {
38            continue;
39        }
40        if entry_path_str.contains(DEFAULT_FLATPAK_BUILDER_CACHE_DIR) {
41            continue;
42        }
43        if entry_path_str.contains(DEFAULT_FLATPAK_BUILDER_OUTPUT_DIR) {
44            continue;
45        }
46
47        if entry_path.is_dir() {
48            let mut dir_paths: Vec<std::path::PathBuf> = get_all_paths(&entry_path)?;
49            all_paths.append(&mut dir_paths);
50        } else {
51            all_paths.push(entry_path);
52        }
53    }
54
55    Ok(all_paths)
56}
57
58pub fn get_build_system(file_path: String) -> Option<String> {
59    if file_path.ends_with("CMakeLists.txt") {
60        return Some("cmake".to_string());
61    }
62    if file_path.ends_with("autogen.sh") || file_path.ends_with("autogen") {
63        return Some("autotools".to_string());
64    }
65    if file_path.ends_with("bootstrap.sh") || file_path.ends_with("bootstrap") {
66        return Some("autotools".to_string());
67    }
68    if file_path.ends_with(".pro") {
69        return Some("qmake".to_string());
70    }
71    if file_path.ends_with("meson.build") || file_path.ends_with("meson_options.txt") {
72        return Some("meson".to_string());
73    }
74    if file_path.ends_with("Cargo.toml") || file_path.ends_with("Cargo.lock") {
75        return Some("cargo".to_string());
76    }
77    if file_path.ends_with("pom.xml") {
78        return Some("maven".to_string());
79    }
80    if file_path.ends_with("debian/control") {
81        return Some("debian".to_string());
82    }
83    if file_path.ends_with("snapcraft.yml") || file_path.ends_with("snapcraft.yaml") {
84        return Some("snap".to_string());
85    }
86    if file_path.ends_with("go.mod") || file_path.ends_with("go.sum") {
87        return Some("go".to_string());
88    }
89    if file_path.ends_with("package.json") || file_path.ends_with("package-lock.json") {
90        return Some("npm".to_string());
91    }
92    if file_path.ends_with("pyproject.toml") {
93        return Some("pip".to_string());
94    }
95    if file_path.ends_with("vcpkg.json") {
96        return Some("vcpkg".to_string());
97    }
98
99    None
100}
101
102///```
103///let formatted_bytes = fpm_core::utils::format_bytes(100);
104///assert_eq!(formatted_bytes, "100.00 B");
105///let formatted_bytes = fpm_core::utils::format_bytes(23746178);
106///assert_eq!(formatted_bytes, "22.65 MB");
107///let formatted_bytes = fpm_core::utils::format_bytes(9823453784599);
108///assert_eq!(formatted_bytes, "8.93 TB");
109///let formatted_bytes = fpm_core::utils::format_bytes(7124362542);
110///assert_eq!(formatted_bytes, "6.64 GB");
111///let formatted_bytes = fpm_core::utils::format_bytes(0);
112///assert_eq!(formatted_bytes, "0.00 B");
113///```
114pub fn format_bytes(bytes: usize) -> String {
115    let sizes: Vec<&str> = vec!["B", "KB", "MB", "GB", "TB"];
116
117    let mut i = 0;
118    let mut approximated_bytes = bytes as f64;
119    while i < 5 && approximated_bytes >= 1024.0 {
120        i += 1;
121        approximated_bytes = approximated_bytes / 1024.0;
122    }
123    return format!("{:.2} {}", approximated_bytes, sizes[i]);
124}
125
126pub fn ask_yes_no_question(question: String) -> bool {
127    let mut answer = String::new();
128    print!("{}? [Y/n]: ", question);
129    let _ = stdout().flush();
130    stdin()
131        .read_line(&mut answer)
132        .expect("Error while reading answer for question.");
133    if let Some('\n') = answer.chars().next_back() {
134        answer.pop();
135    }
136    if let Some('\r') = answer.chars().next_back() {
137        answer.pop();
138    }
139    if answer == "Y" || answer == "y" {
140        return true;
141    }
142    return false;
143}