summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nix.rs34
1 files changed, 30 insertions, 4 deletions
diff --git a/src/nix.rs b/src/nix.rs
index 165fabf..65cdc2d 100644
--- a/src/nix.rs
+++ b/src/nix.rs
@@ -3,10 +3,10 @@ use crate::Error;
use std::{collections::HashMap, process::Command};
-use anyhow::{Context, Result};
+use anyhow::{bail, Context, Result};
use serde::{Deserialize, Serialize};
use serde_json::Value;
-use tracing::{event, instrument, Level};
+use tracing::{debug, event, instrument, Level};
/// JSON output of `nix build`
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
@@ -17,6 +17,13 @@ struct Build {
outputs: HashMap<String, String>,
}
+/// JSON output of `nix path-info` pre Nix 2.19
+#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+struct PathInfo {
+ path: String,
+}
+
#[instrument(skip(installable))]
pub fn dry_build_output(installable: &str) -> Result<Vec<u8>> {
event!(Level::TRACE, "Running command `nix build --extra-experimental-features 'nix-command flakes' --dry-run --json {installable}`");
@@ -87,8 +94,27 @@ pub fn closure_paths(store_path: &str) -> Result<Vec<String>> {
.output()?;
if output.status.success() {
- let path_infos: HashMap<String, Value> = serde_json::from_slice(&output.stdout)?;
- let paths = path_infos.into_keys().collect();
+ // NOTE: See https://github.com/getchoo/nix-forecast/issues/26
+ let paths: Vec<String> = match serde_json::from_slice(&output.stdout)? {
+ // Output schema prior to Nix 2.19/currently on Lix
+ Value::Array(paths_info) => {
+ debug!("Detected Nix < 2.19 or Lix");
+ let paths_info: Vec<PathInfo> = serde_json::from_value(Value::Array(paths_info))?;
+ paths_info
+ .into_iter()
+ .map(|path_info| path_info.path)
+ .collect()
+ }
+ // Output schema from Nix 2.19 onwards
+ Value::Object(paths_info) => {
+ debug!("Detected Nix >= 2.19");
+ let paths_info: HashMap<String, Value> =
+ serde_json::from_value(Value::Object(paths_info))?;
+ paths_info.into_keys().collect()
+ }
+ _ => bail!("`nix path-info` output schema is not recognized!"),
+ };
+
Ok(paths)
} else {
let code = output.status.code().unwrap_or(1);