forked from DGNum/colmena
Add check for Flakes support
This commit is contained in:
parent
e50ba82bf2
commit
67db0e73d1
6 changed files with 169 additions and 1 deletions
|
@ -73,6 +73,7 @@ For a sample configuration, see <https://github.com/zhaofengli/colmena>.
|
||||||
register_command!(introspect, app);
|
register_command!(introspect, app);
|
||||||
register_command!(upload_keys, app);
|
register_command!(upload_keys, app);
|
||||||
register_command!(exec, app);
|
register_command!(exec, app);
|
||||||
|
register_command!(nix_info, app);
|
||||||
|
|
||||||
app
|
app
|
||||||
}
|
}
|
||||||
|
@ -87,6 +88,7 @@ pub async fn run() {
|
||||||
handle_command!(introspect, matches);
|
handle_command!(introspect, matches);
|
||||||
handle_command!("upload-keys", upload_keys, matches);
|
handle_command!("upload-keys", upload_keys, matches);
|
||||||
handle_command!(exec, matches);
|
handle_command!(exec, matches);
|
||||||
|
handle_command!("nix-info", nix_info, matches);
|
||||||
|
|
||||||
if let Some(args) = matches.subcommand_matches("gen-completions") {
|
if let Some(args) = matches.subcommand_matches("gen-completions") {
|
||||||
return gen_completions(args);
|
return gen_completions(args);
|
||||||
|
|
|
@ -4,3 +4,4 @@ pub mod introspect;
|
||||||
pub mod apply_local;
|
pub mod apply_local;
|
||||||
pub mod upload_keys;
|
pub mod upload_keys;
|
||||||
pub mod exec;
|
pub mod exec;
|
||||||
|
pub mod nix_info;
|
||||||
|
|
14
src/command/nix_info.rs
Normal file
14
src/command/nix_info.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
use clap::{App, SubCommand, ArgMatches};
|
||||||
|
|
||||||
|
use crate::nix::NixCheck;
|
||||||
|
|
||||||
|
pub fn subcommand() -> App<'static, 'static> {
|
||||||
|
SubCommand::with_name("nix-info")
|
||||||
|
.about("Show information about the current Nix installation")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(_global_args: &ArgMatches<'_>, _local_args: &ArgMatches<'_>) {
|
||||||
|
let check = NixCheck::detect().await;
|
||||||
|
check.print_version_info();
|
||||||
|
check.print_flakes_info(false);
|
||||||
|
}
|
|
@ -11,10 +11,11 @@ use validator::Validate;
|
||||||
use super::{
|
use super::{
|
||||||
StoreDerivation,
|
StoreDerivation,
|
||||||
NixResult,
|
NixResult,
|
||||||
|
NixError,
|
||||||
NodeConfig,
|
NodeConfig,
|
||||||
ProfileMap,
|
ProfileMap,
|
||||||
};
|
};
|
||||||
use super::NixCommand;
|
use super::{NixCommand, NixCheck};
|
||||||
use crate::util::CommandExecution;
|
use crate::util::CommandExecution;
|
||||||
use crate::progress::TaskProgress;
|
use crate::progress::TaskProgress;
|
||||||
|
|
||||||
|
@ -58,6 +59,14 @@ impl HivePath {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_flake(&self) -> bool {
|
||||||
|
if let Self::Flake(_) = self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -120,6 +129,13 @@ impl Hive {
|
||||||
|
|
||||||
/// Retrieve deployment info for all nodes.
|
/// Retrieve deployment info for all nodes.
|
||||||
pub async fn deployment_info(&self) -> NixResult<HashMap<String, NodeConfig>> {
|
pub async fn deployment_info(&self) -> NixResult<HashMap<String, NodeConfig>> {
|
||||||
|
let nix_check = NixCheck::detect().await;
|
||||||
|
|
||||||
|
if self.path.is_flake() && !nix_check.flakes_supported() {
|
||||||
|
nix_check.print_flakes_info(true);
|
||||||
|
return Err(NixError::NoFlakesSupport);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Really ugly :(
|
// FIXME: Really ugly :(
|
||||||
let s: String = self.nix_instantiate("hive.deploymentConfigJson").eval()
|
let s: String = self.nix_instantiate("hive.deploymentConfigJson").eval()
|
||||||
.capture_json().await?;
|
.capture_json().await?;
|
||||||
|
|
129
src/nix/info.rs
Normal file
129
src/nix/info.rs
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
use std::fmt;
|
||||||
|
use std::process::Stdio;
|
||||||
|
|
||||||
|
use log::Level;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
use tokio::process::Command;
|
||||||
|
|
||||||
|
struct NixVersion {
|
||||||
|
major: usize,
|
||||||
|
minor: usize,
|
||||||
|
string: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NixVersion {
|
||||||
|
fn parse(string: String) -> Self {
|
||||||
|
let re = Regex::new(r" (?P<major>\d+)\.(?P<minor>\d+)").unwrap();
|
||||||
|
if let Some(caps) = re.captures(&string) {
|
||||||
|
let major = caps.name("major").unwrap().as_str().parse().unwrap();
|
||||||
|
let minor = caps.name("minor").unwrap().as_str().parse().unwrap();
|
||||||
|
|
||||||
|
Self { major, minor, string }
|
||||||
|
} else {
|
||||||
|
Self {
|
||||||
|
major: 0,
|
||||||
|
minor: 0,
|
||||||
|
string: String::from("unknown"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_flakes(&self) -> bool {
|
||||||
|
self.major > 2 || (self.major == 2 && self.minor >= 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for NixVersion {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
if self.major != 0 {
|
||||||
|
write!(f, "{}.{}", self.major, self.minor)
|
||||||
|
} else {
|
||||||
|
write!(f, "{}???", self.string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NixCheck {
|
||||||
|
version: Option<NixVersion>,
|
||||||
|
flakes_supported: bool,
|
||||||
|
flakes_enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NixCheck {
|
||||||
|
const NO_NIX: Self = Self {
|
||||||
|
version: None,
|
||||||
|
flakes_supported: false,
|
||||||
|
flakes_enabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub async fn detect() -> Self {
|
||||||
|
let version_cmd = Command::new("nix-instantiate")
|
||||||
|
.arg("--version")
|
||||||
|
.output().await;
|
||||||
|
|
||||||
|
if version_cmd.is_err() {
|
||||||
|
return Self::NO_NIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
let version = NixVersion::parse(String::from_utf8_lossy(&version_cmd.unwrap().stdout).to_string());
|
||||||
|
let flakes_supported = version.has_flakes();
|
||||||
|
|
||||||
|
let flake_cmd = Command::new("nix-instantiate")
|
||||||
|
.args(&["--eval", "-E", "builtins.getFlake"])
|
||||||
|
.stdout(Stdio::null())
|
||||||
|
.stderr(Stdio::null())
|
||||||
|
.status().await;
|
||||||
|
|
||||||
|
if flake_cmd.is_err() {
|
||||||
|
return Self::NO_NIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
let flakes_enabled = flake_cmd.unwrap().success();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
version: Some(version),
|
||||||
|
flakes_supported,
|
||||||
|
flakes_enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_version_info(&self) {
|
||||||
|
if let Some(v) = &self.version {
|
||||||
|
log::info!("Nix Version: {}", v);
|
||||||
|
} else {
|
||||||
|
log::info!("Nix Version: Not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_flakes_info(&self, required: bool) {
|
||||||
|
if self.version.is_none() {
|
||||||
|
log::error!("Nix doesn't appear to be installed.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.flakes_enabled {
|
||||||
|
log::info!("The Nix version you are using supports Flakes and it's enabled.");
|
||||||
|
} else if self.flakes_supported {
|
||||||
|
log::warn!("The Nix version you are using supports Flakes but it's disabled.");
|
||||||
|
log::warn!("Colmena will automatically enable Flakes for its operations, but you should enable it in your Nix configuration:");
|
||||||
|
log::warn!(" experimental-features = nix-command flakes");
|
||||||
|
} else {
|
||||||
|
let level = if required {
|
||||||
|
Level::Error
|
||||||
|
} else {
|
||||||
|
Level::Warn
|
||||||
|
};
|
||||||
|
log::log!(level, "The Nix version you are using does not support Flakes.");
|
||||||
|
log::log!(level, "Please install nixUnstable for a version that includes Flakes support.");
|
||||||
|
|
||||||
|
if required {
|
||||||
|
log::log!(level, "Cannot continue since Flakes support is required for this operation.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flakes_supported(&self) -> bool {
|
||||||
|
self.flakes_supported
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,9 @@ pub use profile::{Profile, ProfileMap};
|
||||||
pub mod deployment;
|
pub mod deployment;
|
||||||
pub use deployment::{Goal, Target, Deployment};
|
pub use deployment::{Goal, Target, Deployment};
|
||||||
|
|
||||||
|
pub mod info;
|
||||||
|
pub use info::NixCheck;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
@ -72,6 +75,9 @@ pub enum NixError {
|
||||||
#[snafu(display("Unknown active profile: {}", store_path))]
|
#[snafu(display("Unknown active profile: {}", store_path))]
|
||||||
ActiveProfileUnknown { store_path: String },
|
ActiveProfileUnknown { store_path: String },
|
||||||
|
|
||||||
|
#[snafu(display("Current Nix version does not support Flakes"))]
|
||||||
|
NoFlakesSupport,
|
||||||
|
|
||||||
#[snafu(display("Nix Error: {}", message))]
|
#[snafu(display("Nix Error: {}", message))]
|
||||||
Unknown { message: String },
|
Unknown { message: String },
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue