-
-
Notifications
You must be signed in to change notification settings - Fork 92
Expand file tree
/
Copy pathchecks.rs
More file actions
152 lines (130 loc) · 4.82 KB
/
checks.rs
File metadata and controls
152 lines (130 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use std::{cmp::Ordering, env};
use color_eyre::{eyre, Result};
use semver::Version;
use crate::util;
/// Verifies if the installed Nix version meets requirements
///
/// # Returns
///
/// * `Result<()>` - Ok if version requirements are met, error otherwise
pub fn check_nix_version() -> Result<()> {
if env::var("NH_NO_CHECKS").is_ok() {
return Ok(());
}
let version = util::get_nix_version()?;
let is_lix_binary = util::is_lix()?;
// XXX: Both Nix and Lix follow semantic versioning (semver). Update the
// versions below once latest stable for either of those packages change.
// TODO: Set up a CI to automatically update those in the future.
const MIN_LIX_VERSION: &str = "2.91.1";
const MIN_NIX_VERSION: &str = "2.24.14";
// Minimum supported versions. Those should generally correspond to
// latest package versions in the stable branch.
//
// Q: Why are you doing this?
// A: First of all to make sure we do not make baseless assumptions
// about the user's system; we should only work around APIs that we
// are fully aware of, and not try to work around every edge case.
// Also, nh should be responsible for nudging the user to use the
// relevant versions of the software it wraps, so that we do not have
// to try and support too many versions. NixOS stable and unstable
// will ALWAYS be supported, but outdated versions will not. If your
// Nix fork uses a different versioning scheme, please open an issue.
let min_version = if is_lix_binary {
MIN_LIX_VERSION
} else {
MIN_NIX_VERSION
};
let current = Version::parse(&version)?;
let required = Version::parse(min_version)?;
match current.cmp(&required) {
Ordering::Less => {
let binary_name = if is_lix_binary { "Lix" } else { "Nix" };
Err(eyre::eyre!(
"{} version {} is too old. Minimum required version is {}",
binary_name,
version,
min_version
))
}
_ => Ok(()),
}
}
/// Verifies if the required experimental features are enabled
///
/// # Returns
///
/// * `Result<()>` - Ok if all required features are enabled, error otherwise
pub fn check_nix_features() -> Result<()> {
if env::var("NH_NO_CHECKS").is_ok() {
return Ok(());
}
let mut required_features = vec!["nix-command", "flakes"];
// Lix still uses repl-flake, which is removed in the latest version of Nix.
if util::is_lix()? {
required_features.push("repl-flake");
}
tracing::debug!("Required Nix features: {}", required_features.join(", "));
// Get currently enabled features
match util::get_nix_experimental_features() {
Ok(enabled_features) => {
let features_vec: Vec<_> = enabled_features.into_iter().collect();
tracing::debug!("Enabled Nix features: {}", features_vec.join(", "));
}
Err(e) => {
tracing::warn!("Failed to get enabled Nix features: {}", e);
}
}
let missing_features = util::get_missing_experimental_features(&required_features)?;
if !missing_features.is_empty() {
tracing::warn!(
"Missing required Nix features: {}",
missing_features.join(", ")
);
return Err(eyre::eyre!(
"Missing required experimental features. Please enable: {}",
missing_features.join(", ")
));
}
tracing::debug!("All required Nix features are enabled");
Ok(())
}
/// Handles environment variable setup and returns if a warning should be shown
///
/// # Returns
///
/// * `Result<bool>` - True if a warning should be shown about the FLAKE
/// variable, false otherwise
pub fn setup_environment() -> Result<bool> {
let mut do_warn = false;
if let Ok(f) = std::env::var("FLAKE") {
// Set NH_FLAKE if it's not already set
if std::env::var("NH_FLAKE").is_err() {
std::env::set_var("NH_FLAKE", f);
// Only warn if FLAKE is set and we're using it to set NH_FLAKE
// AND none of the command-specific env vars are set
if std::env::var("NH_OS_FLAKE").is_err()
&& std::env::var("NH_HOME_FLAKE").is_err()
&& std::env::var("NH_DARWIN_FLAKE").is_err()
{
do_warn = true;
}
}
}
Ok(do_warn)
}
/// Consolidate all necessary checks for Nix functionality into a single
/// function. This will be executed in the main function, but can be executed
/// before critical commands to double-check if necessary.
///
/// # Returns
///
/// * `Result<()>` - Ok if all checks pass, error otherwise
pub fn verify_nix_environment() -> Result<()> {
if env::var("NH_NO_CHECKS").is_ok() {
return Ok(());
}
check_nix_version()?;
check_nix_features()?;
Ok(())
}