From 63be1b7da0e4da1d64bfd50558e8b98a369b2f6e Mon Sep 17 00:00:00 2001 From: Fernando Ayats Date: Thu, 15 Aug 2024 22:22:59 +0200 Subject: [PATCH] Query the proper nixpkgs flake node Closes #144 --- src/clean.rs | 4 +-- src/json.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + src/nixos.rs | 5 +-- src/search.rs | 79 ++++++++++++++++++++--------------------------- 5 files changed, 122 insertions(+), 52 deletions(-) create mode 100644 src/json.rs diff --git a/src/clean.rs b/src/clean.rs index a4ca1fe..24bf21d 100644 --- a/src/clean.rs +++ b/src/clean.rs @@ -72,10 +72,10 @@ impl NHRunnable for interface::CleanMode { } let user = nix::unistd::User::from_uid(uid)?.unwrap(); profiles.extend(profiles_in_dir( - &PathBuf::from(std::env::var("HOME")?).join(".local/state/nix/profiles"), + PathBuf::from(std::env::var("HOME")?).join(".local/state/nix/profiles"), )); profiles.extend(profiles_in_dir( - &PathBuf::from("/nix/var/nix/profiles/per-user").join(user.name), + PathBuf::from("/nix/var/nix/profiles/per-user").join(user.name), )); args } diff --git a/src/json.rs b/src/json.rs new file mode 100644 index 0000000..2e0ee35 --- /dev/null +++ b/src/json.rs @@ -0,0 +1,85 @@ +use std::fmt::Display; + + + +#[derive(Debug, Clone)] +pub struct Value<'v> { + pub inner: &'v serde_json::Value, + get_stack: Vec, +} + +#[derive(Debug)] +pub struct Error { + get_stack: Vec, +} + +impl Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Failed to index json value with ")?; + + for (i, elem) in self.get_stack.iter().enumerate() { + if i != 0 { + write!(f, ".")?; + } + write!(f, "{}", elem)?; + } + + Ok(()) + } +} + +impl std::error::Error for Error {} + +impl<'v> Value<'v> { + pub fn new(value: &'v serde_json::Value) -> Self { + Self { + inner: value, + get_stack: vec![], + } + } + + pub fn get(&self, index: &str) -> Result { + let mut get_stack = self.get_stack.clone(); + get_stack.push(index.to_owned()); + + match self.inner.get(index) { + Some(value) => Ok(Self { + inner: value, + get_stack, + }), + None => Err(Error { get_stack }), + } + } +} + +#[test] +fn test_value() { + let input = serde_json::json!({ + "foo": { + "bar": "baz", + "some": { + "other": "value" + } + } + }); + + let i = Value::new(&input); + + assert!(i.get("foo").is_ok()); + assert!(i.get("foo_bad").is_err()); + assert!(i.get("foo").unwrap().get("bar").is_ok()); + assert!(i + .get("foo") + .unwrap() + .get("some") + .unwrap() + .get("other_bad") + .is_err()); + assert!(i + .get("foo") + .unwrap() + .get("some") + .unwrap() + .get("other") + .is_ok()); +} diff --git a/src/main.rs b/src/main.rs index 8b164d3..2542f7a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod commands; mod completion; mod home; mod interface; +mod json; mod logging; mod nixos; mod search; diff --git a/src/nixos.rs b/src/nixos.rs index bfb0cf8..1be0ac1 100644 --- a/src/nixos.rs +++ b/src/nixos.rs @@ -104,10 +104,7 @@ impl OsRebuildArgs { commands::CommandBuilder::default() .args(self.common.diff_provider.split_ascii_whitespace()) - .args([ - CURRENT_PROFILE, - target_profile.to_str().unwrap(), - ]) + .args([CURRENT_PROFILE, target_profile.to_str().unwrap()]) .message("Comparing changes") .build()? .exec()?; diff --git a/src/search.rs b/src/search.rs index 94ff84c..4a47291 100644 --- a/src/search.rs +++ b/src/search.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, process::Stdio, time::Instant}; +use std::{process::Stdio, time::Instant}; use color_eyre::eyre::{eyre, Context, ContextCompat}; use elasticsearch_dsl::*; @@ -219,21 +219,31 @@ fn my_nix_branch(flake: &FlakeRef) -> Result { .arg(flake.as_str()) .output()?; - let stdout = String::from_utf8(output.stdout)?; - let mut metadata: FlakeMetadata = serde_json::from_str(&stdout)?; - - let branch = metadata - .locks - .nodes - .remove("nixpkgs") - .wrap_err(r#"Couldn't find input "nixpkgs" on the flake"#)? - .original - .wrap_err("Couldn't find original")? - .r#ref - .wrap_err("Couldn't find ref field")?; - - if supported_branch(&branch) { - Ok(branch) + let metadata: serde_json::Value = serde_json::from_slice(&output.stdout)?; + let m = crate::json::Value::new(&metadata); + + let nixpkgs_input = m + .get("locks")? + .get("nodes")? + .get("root")? + .get("inputs")? + .get("nixpkgs")? + .inner + .as_str() + .wrap_err("Failed to read as string")?; + + let branch = m + .get("locks")? + .get("nodes")? + .get(nixpkgs_input)? + .get("original")? + .get("ref")? + .inner + .as_str() + .wrap_err("Failed to read as string")?; + + if supported_branch(branch) { + Ok(branch.to_owned()) } else { Err(eyre!("Branch {} is not supported", &branch)) } @@ -247,38 +257,15 @@ fn supported_branch>(branch: S) -> bool { } let re = Regex::new(r"nixos-[0-9]+\.[0-9]+").unwrap(); - return re.is_match(branch); + re.is_match(branch) } #[test] fn test_supported_branch() { - assert_eq!(supported_branch("nixos-unstable"), true); - assert_eq!(supported_branch("nixos-unstable-small"), false); - assert_eq!(supported_branch("nixos-24.05"), true); - assert_eq!(supported_branch("24.05"), false); - assert_eq!(supported_branch("nixpkgs-darwin"), false); - assert_eq!(supported_branch("nixpks-21.11-darwin"), false); -} - -#[derive(Debug, Deserialize, Clone)] -struct FlakeMetadata { - locks: FlakeLocks, -} - -#[derive(Debug, Deserialize, Clone)] -struct FlakeLocks { - nodes: HashMap, -} - -#[derive(Debug, Deserialize, Clone)] -struct FlakeLockedNode { - original: Option, -} - -#[derive(Debug, Deserialize, Clone)] -struct FlakeLockedOriginal { - r#ref: Option, - // owner: String, - // repo: String, - // r#type: String, + assert!(supported_branch("nixos-unstable")); + assert!(!supported_branch("nixos-unstable-small")); + assert!(supported_branch("nixos-24.05")); + assert!(!supported_branch("24.05")); + assert!(!supported_branch("nixpkgs-darwin")); + assert!(!supported_branch("nixpks-21.11-darwin")); }