From b2e0ce28fcda07caca9c4b192900b6b3fb77c565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Favier?= Date: Fri, 18 Mar 2022 21:57:28 +0100 Subject: [PATCH] flake-info: enforce minimal nix version (#451) Co-authored-by: Yannik Sander --- flake-info/.cargo/config.toml | 2 + flake-info/Cargo.lock | 9 ++++- flake-info/Cargo.toml | 1 + flake-info/src/bin/flake-info.rs | 7 ++++ flake-info/src/commands/mod.rs | 2 + flake-info/src/commands/nix_check_version.rs | 42 ++++++++++++++++++++ 6 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 flake-info/.cargo/config.toml create mode 100644 flake-info/src/commands/nix_check_version.rs diff --git a/flake-info/.cargo/config.toml b/flake-info/.cargo/config.toml new file mode 100644 index 0000000..3c38084 --- /dev/null +++ b/flake-info/.cargo/config.toml @@ -0,0 +1,2 @@ +[env] +MIN_NIX_VERSION = "2.7.0" # we need PRs #5878 and #5922 for package outputs diff --git a/flake-info/Cargo.lock b/flake-info/Cargo.lock index 56dd780..bc0de4b 100644 --- a/flake-info/Cargo.lock +++ b/flake-info/Cargo.lock @@ -335,6 +335,7 @@ dependencies = [ "log", "pandoc", "reqwest", + "semver 1.0.6", "serde", "serde_json", "serde_path_to_error", @@ -1124,7 +1125,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver", + "semver 0.9.0", ] [[package]] @@ -1210,6 +1211,12 @@ dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d" + [[package]] name = "semver-parser" version = "0.7.0" diff --git a/flake-info/Cargo.toml b/flake-info/Cargo.toml index 0409e99..f83b8c1 100644 --- a/flake-info/Cargo.toml +++ b/flake-info/Cargo.toml @@ -25,6 +25,7 @@ tokio = { version = "*", features = ["full"] } reqwest = { version = "0.11", features = ["json", "blocking"] } sha2 = "0.9" pandoc = "0.8" +semver = "1.0" elasticsearch = {git = "https://github.com/elastic/elasticsearch-rs", features = ["rustls-tls"]} diff --git a/flake-info/src/bin/flake-info.rs b/flake-info/src/bin/flake-info.rs index a3573c9..9350548 100644 --- a/flake-info/src/bin/flake-info.rs +++ b/flake-info/src/bin/flake-info.rs @@ -1,10 +1,12 @@ use anyhow::{Context, Result}; use commands::run_gc; +use flake_info::commands::NixCheckError; use flake_info::data::import::{Kind, NixOption}; use flake_info::data::{self, Export, Nixpkgs, Source}; use flake_info::elastic::{ElasticsearchError, ExistsStrategy}; use flake_info::{commands, elastic}; use log::{debug, error, info, warn}; +use semver::VersionReq; use sha2::Digest; use std::path::{Path, PathBuf}; use std::ptr::hash; @@ -193,6 +195,9 @@ async fn main() -> Result<()> { #[derive(Debug, Error)] enum FlakeInfoError { + #[error("Nix check failed: {0}")] + NixCheck(#[from] NixCheckError), + #[error("Getting flake info caused an error: {0:?}")] Flake(anyhow::Error), #[error("Getting nixpkgs info caused an error: {0:?}")] @@ -208,6 +213,8 @@ async fn run_command( kind: Kind, extra: &[String], ) -> Result<(Vec, (String, String, String)), FlakeInfoError> { + flake_info::commands::check_nix_version(env!("MIN_NIX_VERSION"))?; + match command { Command::Flake { flake, diff --git a/flake-info/src/commands/mod.rs b/flake-info/src/commands/mod.rs index 4cc1efb..1ad6420 100644 --- a/flake-info/src/commands/mod.rs +++ b/flake-info/src/commands/mod.rs @@ -1,7 +1,9 @@ +mod nix_check_version; mod nix_flake_attrs; mod nix_flake_info; mod nix_gc; mod nixpkgs_info; +pub use nix_check_version::{check_nix_version, NixCheckError}; pub use nix_flake_attrs::get_derivation_info; pub use nix_flake_info::get_flake_info; pub use nix_gc::run_gc; diff --git a/flake-info/src/commands/nix_check_version.rs b/flake-info/src/commands/nix_check_version.rs new file mode 100644 index 0000000..07e7e2e --- /dev/null +++ b/flake-info/src/commands/nix_check_version.rs @@ -0,0 +1,42 @@ +use command_run::Command; +use log::info; +use semver::{Version, VersionReq}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum NixCheckError { + #[error("Installed nix doesn't match version requirement: {0} (required {1})")] + IncompatibleNixVersion(Version, VersionReq), + + #[error("SemVer error (this should not occur, please file a bug report): {0}")] + CheckError(#[from] semver::Error), + + #[error("Failed to run nix command: {0}")] + CommandError(#[from] command_run::Error), +} + +pub fn check_nix_version(min_version: &str) -> Result<(), NixCheckError> { + info!("Checking nix version"); + + let nix_version_requirement = VersionReq::parse(&format!(">={}", min_version))?; + + let mut command = + Command::with_args("nix", &["eval", "--raw", "--expr", "builtins.nixVersion"]); + command.log_command = false; + command.enable_capture(); + let output = command.run()?; + let nix_version = Version::parse( + output + .stdout_string_lossy() + .split(|c: char| c != '.' && !c.is_ascii_digit()) + .next() + .unwrap(), + )?; + if !nix_version_requirement.matches(&nix_version) { + return Err(NixCheckError::IncompatibleNixVersion( + nix_version, + nix_version_requirement, + )); + } + Ok(()) +}