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
use crate::command::{CommandError, NixCmd, NixCmdError};

use super::url::FlakeUrl;

/// Run `nix eval <url> --json` and parse its JSON
///
/// If the flake does not output the given attribute, return the [Default]
/// value of `T`.
pub async fn nix_eval_attr_json<T>(url: &FlakeUrl) -> Result<T, NixCmdError>
where
    T: Default + serde::de::DeserializeOwned,
{
    let nix = NixCmd::default();
    let result = nix
        .run_with_args_expecting_json(&["eval", url.0.as_str(), "--json"])
        .await;
    match result {
        Err(err) if error_is_missing_attribute(&err) => {
            // The 'nixci' flake output attr is missing. User wants the default config.
            Ok(T::default())
        }
        r => r,
    }
}

/// Check that [NixCmdError] is a missing attribute error
fn error_is_missing_attribute(err: &NixCmdError) -> bool {
    match err {
        NixCmdError::CmdError(CommandError::ProcessFailed { stderr, .. }) => {
            stderr.contains("does not provide attribute")
        }
        _ => false,
    }
}