snix_glue/builder/export_reference_graph/
validity_registration.rs

1use nix_compat::store_path::StorePath;
2
3/// Produces the format that Nix calls "makeValidityRegistration" and describes as:
4/// "A string accepted by decodeValidPathInfo() that registers the specified paths as valid."
5/// Explained differently, this is the text format used in exportReferencesGraph,
6/// in the non-structured attrs case, which can be passed to `nix-store --register-validity`.
7/// We don't implement the showDerivers and showHash functionality,
8/// as that doesn't seem to be used for exportReferenceGraph.
9pub fn make_validity_registration<
10    W: std::fmt::Write,
11    E: Iterator<Item = (StorePath<S1>, R)>,
12    R: Iterator<Item = StorePath<S2>> + ExactSizeIterator,
13    S1: std::convert::AsRef<str>,
14    S2: std::convert::AsRef<str>,
15>(
16    w: &mut W,
17    elems: E,
18) -> std::fmt::Result {
19    for (store_path, references) in elems {
20        let num_references = references.len();
21        write!(
22            w,
23            "{0}\n\n{num_references}\n",
24            store_path.to_absolute_path()
25        )?;
26
27        for reference in references {
28            writeln!(w, "{}", reference.to_absolute_path())?;
29        }
30    }
31
32    Ok(())
33}
34
35#[cfg(test)]
36mod test {
37    use std::sync::LazyLock;
38
39    use nix_compat::store_path::{StorePath, StorePathRef};
40
41    use crate::builder::export_reference_graph::make_validity_registration;
42
43    #[derive(serde::Deserialize)]
44    #[allow(unused)]
45    struct PathData<'a> {
46        #[serde(rename = "closureSize")]
47        closure_size: u64,
48
49        #[serde(
50            rename = "narHash",
51            deserialize_with = "nix_compat::nixhash::serde::from_nix_nixbase32_or_sri"
52        )]
53        nar_sha256: [u8; 32],
54
55        #[serde(rename = "narSize")]
56        nar_size: u64,
57
58        #[serde(borrow)]
59        pub path: StorePathRef<'a>,
60
61        pub references: Vec<StorePathRef<'a>>,
62    }
63    static CLOSURE_HELLO: LazyLock<Vec<PathData<'static>>> = LazyLock::new(|| {
64        let json_str = r#"
65    [
66      {
67        "closureSize": 2447000,
68        "narHash": "sha256:1b34sg5s4padn47z032p8rn0yvp5ji5ls2p9bsc4p7z37w3r6f2h",
69        "narSize": 368208,
70        "path": "/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8",
71        "references": [
72          "/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8",
73          "/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1"
74        ],
75        "valid": true
76      },
77      {
78        "closureSize": 197752,
79        "narHash": "sha256:0bvlqny00vmrx0x95ai9bcl3qzr0iyy4fwhngng648psr12zff55",
80        "narSize": 197752,
81        "path": "/nix/store/kbijm6lc9va8xann3cfyam0vczzmwkxj-xgcc-15.2.0-libgcc",
82        "references": [],
83        "valid": true
84      },
85      {
86        "closureSize": 33294120,
87        "narHash": "sha256:16xw6ngrqak6fm91njbgpyq70rjjrmf4y1gcmrwzi199p01lbxcg",
88        "narSize": 274640,
89        "path": "/nix/store/mi08jhbcjib1i1kgvbd0fxn2yrnzdv4a-hello-2.12.2",
90        "references": [
91          "/nix/store/mi08jhbcjib1i1kgvbd0fxn2yrnzdv4a-hello-2.12.2",
92          "/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47"
93        ],
94        "valid": true
95      },
96      {
97        "closureSize": 2078792,
98        "narHash": "sha256:1vy1c2rfgdgfy5lpgfkd58d0ly7ripfxsx4m99rx434sh3rdy45d",
99        "narSize": 2078792,
100        "path": "/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1",
101        "references": [
102          "/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1"
103        ],
104        "valid": true
105      },
106      {
107        "closureSize": 33019480,
108        "narHash": "sha256:1r6rinhxn3a2mrmvdkmakvqvn9cn302yi08vqzwvjjzjjl77fy0k",
109        "narSize": 30374728,
110        "path": "/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47",
111        "references": [
112          "/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8",
113          "/nix/store/kbijm6lc9va8xann3cfyam0vczzmwkxj-xgcc-15.2.0-libgcc",
114          "/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47"
115        ],
116        "valid": true
117      }
118    ]
119    "#;
120        serde_json::from_str::<Vec<PathData<'static>>>(json_str).expect("must deserialize")
121    });
122
123    #[test]
124    fn test_validity_registration_complex() {
125        let mut s = String::new();
126        make_validity_registration(
127            &mut s,
128            CLOSURE_HELLO.iter().map(|elem| {
129                (
130                    elem.path.to_owned(),
131                    elem.references.iter().map(|sp| sp.to_owned()),
132                )
133            }),
134        )
135        .expect("must succeed");
136
137        assert_eq!(
138            r#"/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8
139
1402
141/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8
142/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1
143/nix/store/kbijm6lc9va8xann3cfyam0vczzmwkxj-xgcc-15.2.0-libgcc
144
1450
146/nix/store/mi08jhbcjib1i1kgvbd0fxn2yrnzdv4a-hello-2.12.2
147
1482
149/nix/store/mi08jhbcjib1i1kgvbd0fxn2yrnzdv4a-hello-2.12.2
150/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47
151/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1
152
1531
154/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1
155/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47
156
1573
158/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8
159/nix/store/kbijm6lc9va8xann3cfyam0vczzmwkxj-xgcc-15.2.0-libgcc
160/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47
161"#,
162            s
163        );
164    }
165
166    #[test]
167    fn test_validity_registration_simple() {
168        let mut s = String::new();
169
170        let sp_libiconv: StorePath<&str> = StorePath::from_absolute_path(
171            b"/nix/store/2ilm1l0xy457r1py73n1sxh2c8pc1sq1-libiconv-109",
172        )
173        .expect("must parse");
174        let sp_hello = StorePath::from_absolute_path(
175            b"/nix/store/8ha1dhmx807czjczmwy078s4r9s254il-hello-2.12.2",
176        )
177        .expect("must parse");
178
179        let elems = vec![(&sp_libiconv, [&sp_libiconv]), (&sp_hello, [&sp_libiconv])];
180
181        make_validity_registration(
182            &mut s,
183            elems
184                .as_slice()
185                .iter()
186                .map(|(path, refs)| ((*path).to_owned(), refs.iter().map(|sp| (*sp).to_owned()))),
187        )
188        .expect("must succeed");
189
190        assert_eq!(
191            r#"/nix/store/2ilm1l0xy457r1py73n1sxh2c8pc1sq1-libiconv-109
192
1931
194/nix/store/2ilm1l0xy457r1py73n1sxh2c8pc1sq1-libiconv-109
195/nix/store/8ha1dhmx807czjczmwy078s4r9s254il-hello-2.12.2
196
1971
198/nix/store/2ilm1l0xy457r1py73n1sxh2c8pc1sq1-libiconv-109
199"#,
200            s
201        );
202    }
203}