nix_query_tree_viewer/nix_query_tree/
exec_nix_store.rs

1use std::path::{Path, PathBuf};
2use std::process::{Command, Output};
3
4use super::parsing;
5use super::{NixQueryEntry, NixQueryPathMap, NixQueryTree};
6use crate::tree;
7
8#[derive(Clone, Debug, Eq, PartialEq)]
9pub enum NixStoreErr {
10    CommandErr(String),
11    Utf8Err(String),
12    NixStoreErr(String),
13    ParseErr(String),
14}
15
16impl std::fmt::Display for NixStoreErr {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        let string = match self {
19            NixStoreErr::CommandErr(string) => string,
20            NixStoreErr::Utf8Err(string) => string,
21            NixStoreErr::NixStoreErr(string) => string,
22            NixStoreErr::ParseErr(string) => string,
23        };
24        write!(f, "{}", string)
25    }
26}
27
28#[derive(Clone, Debug, Eq, PartialEq)]
29pub struct NixStoreRes {
30    pub raw: String,
31    pub tree: NixQueryTree,
32    pub map: NixQueryPathMap,
33}
34
35impl NixStoreRes {
36    pub fn new(raw: &str, tree: NixQueryTree) -> Self {
37        let map: NixQueryPathMap = tree.path_map();
38        NixStoreRes {
39            raw: String::from(raw),
40            tree,
41            map,
42        }
43    }
44
45    pub fn lookup_first_query_entry(
46        &self,
47        nix_query_entry: &NixQueryEntry,
48    ) -> Option<&tree::Path> {
49        self.map.lookup_first(&nix_query_entry.0)
50    }
51}
52
53#[derive(Clone, Debug, Eq, PartialEq)]
54pub struct ExecNixStoreRes {
55    pub nix_store_path: PathBuf,
56    pub res: Result<NixStoreRes, NixStoreErr>,
57}
58
59impl ExecNixStoreRes {
60    pub fn new(
61        nix_store_path: &Path,
62        res: Result<NixStoreRes, NixStoreErr>,
63    ) -> Self {
64        ExecNixStoreRes {
65            nix_store_path: nix_store_path.to_path_buf(),
66            res,
67        }
68    }
69}
70
71fn nix_store_res(nix_store_path: &Path) -> Result<NixStoreRes, NixStoreErr> {
72    let nix_store_output: Output = Command::new("nix-store")
73        .args(&["--query", "--tree", &nix_store_path.to_string_lossy()])
74        .output()
75        .map_err(|io_err| NixStoreErr::CommandErr(io_err.to_string()))?;
76
77    if nix_store_output.status.success() {
78        let stdout = from_utf8(nix_store_output.stdout)?;
79        parsing::nix_query_tree_parser(&stdout)
80            .map(|nix_query_tree| NixStoreRes::new(&stdout, nix_query_tree))
81            .map_err(|nom_err| NixStoreErr::ParseErr(nom_err.to_string()))
82    } else {
83        let stderr = from_utf8(nix_store_output.stderr)?;
84        Err(NixStoreErr::NixStoreErr(stderr))
85    }
86}
87
88/// Run `nix-store --query --tree` for the given nix store path.
89pub fn run(nix_store_path: &Path) -> ExecNixStoreRes {
90    ExecNixStoreRes {
91        nix_store_path: nix_store_path.to_path_buf(),
92        res: nix_store_res(nix_store_path),
93    }
94}
95
96/// Convert a `Vec<u8>` to a proper utf8 `String`, converting the error to `NixStoreErr::Utf8Err`.
97fn from_utf8(i: Vec<u8>) -> Result<String, NixStoreErr> {
98    String::from_utf8(i)
99        .map_err(|utf8_err| NixStoreErr::Utf8Err(utf8_err.to_string()))
100}