1pub const FC_VERSION_DEFAULT: &str = match option_env!("MVM_FC_VERSION") {
3 Some(v) => v,
4 None => "v1.14.1",
5};
6
7pub const ARCH: &str = "aarch64";
8
9pub fn normalize_fc_version(raw: &str) -> String {
11 let re = regex::Regex::new(r"(?:v)?\d+\.\d+(?:\.\d+)?").expect("valid regex");
13 let candidate = re
14 .captures_iter(raw)
15 .last()
16 .map(|c| c.get(0).unwrap().as_str().to_string())
17 .unwrap_or_else(|| FC_VERSION_DEFAULT.to_string());
18
19 if candidate.starts_with('v') {
20 candidate
21 } else {
22 format!("v{}", candidate)
23 }
24}
25
26pub fn fc_version() -> String {
30 let raw = std::env::var("MVM_FC_VERSION").unwrap_or_else(|_| FC_VERSION_DEFAULT.to_string());
31 normalize_fc_version(&raw)
32}
33
34pub fn fc_version_short() -> String {
37 let full = fc_version();
38 let trimmed = full.trim_start_matches('v');
39 let parts = trimmed.split('.').collect::<Vec<_>>();
40 if parts.len() >= 2 {
41 format!("v{}.{}", parts[0], parts[1])
42 } else {
43 full
44 }
45}
46
47pub fn mvm_data_dir() -> String {
57 if let Ok(d) = std::env::var("MVM_DATA_DIR")
58 && !d.is_empty()
59 {
60 return d;
61 }
62 let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string());
63 format!("{}/.mvm", home)
64}
65
66pub fn is_production_mode() -> bool {
68 std::env::var("MVM_PRODUCTION")
69 .map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
70 .unwrap_or(false)
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn test_not_production_by_default() {
79 let _ = is_production_mode();
80 }
81
82 #[test]
83 fn test_fc_version_default() {
84 let v = fc_version();
86 assert!(v.starts_with('v'), "FC version should start with 'v'");
87 assert!(v.contains('.'), "FC version should contain a dot");
88 }
89
90 #[test]
91 fn test_fc_version_short() {
92 let short = fc_version_short();
93 assert!(short.starts_with('v'));
94 assert_eq!(short.matches('.').count(), 1);
96 }
97
98 #[test]
99 fn normalize_firecracker_banner() {
100 let raw = "Firecracker v1.14.1";
101 assert_eq!(normalize_fc_version(raw), "v1.14.1");
102 }
103
104 #[test]
105 fn normalize_with_leading_v() {
106 let raw = "v1.14.1";
107 assert_eq!(normalize_fc_version(raw), "v1.14.1");
108 }
109
110 #[test]
111 fn normalize_without_v() {
112 let raw = "1.14.1";
113 assert_eq!(normalize_fc_version(raw), "v1.14.1");
114 }
115
116 #[test]
117 fn normalize_minor_only() {
118 let raw = "Firecracker v1.14";
119 assert_eq!(normalize_fc_version(raw), "v1.14");
120 assert_eq!(fc_version_short_from(raw), "v1.14");
122 }
123
124 #[test]
125 fn normalize_garbage_falls_back() {
126 let raw = "nonsense";
127 assert_eq!(normalize_fc_version(raw), FC_VERSION_DEFAULT);
128 }
129
130 fn fc_version_short_from(raw: &str) -> String {
132 unsafe { std::env::set_var("MVM_FC_VERSION", raw) };
134 let short = fc_version_short();
135 unsafe { std::env::remove_var("MVM_FC_VERSION") };
136 short
137 }
138}