Skip to main content

nix_compat/path_info/export_reference_graph/
validity_registration.rs

1use nix_compat::store_path::StorePathRef;
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    'a,
11    W: std::fmt::Write,
12    E: Iterator<Item = (&'a StorePathRef<'a>, R)>,
13    R: Iterator<Item = &'a StorePathRef<'a>> + ExactSizeIterator + 'a,
14>(
15    w: &mut W,
16    elems: E,
17) -> std::fmt::Result {
18    for (store_path, references) in elems {
19        let num_references = references.len();
20        write!(
21            w,
22            "{0}\n\n{num_references}\n",
23            store_path.as_absolute_path_fmt()
24        )?;
25
26        for reference in references {
27            writeln!(w, "{}", reference.as_absolute_path_fmt())?;
28        }
29    }
30
31    Ok(())
32}
33
34#[cfg(feature = "serde")] // Test fixtures rely on nix-compat serde features
35#[cfg(test)]
36mod test {
37    use std::sync::LazyLock;
38
39    use nix_compat::store_path::StorePathRef;
40
41    use super::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
64    static CLOSURE_HELLO: LazyLock<Vec<PathData<'static>>> = LazyLock::new(|| {
65        let json_str = r#"
66    [
67      {
68        "closureSize": 2447000,
69        "narHash": "sha256:1b34sg5s4padn47z032p8rn0yvp5ji5ls2p9bsc4p7z37w3r6f2h",
70        "narSize": 368208,
71        "path": "/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8",
72        "references": [
73          "/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8",
74          "/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1"
75        ],
76        "valid": true
77      },
78      {
79        "closureSize": 197752,
80        "narHash": "sha256:0bvlqny00vmrx0x95ai9bcl3qzr0iyy4fwhngng648psr12zff55",
81        "narSize": 197752,
82        "path": "/nix/store/kbijm6lc9va8xann3cfyam0vczzmwkxj-xgcc-15.2.0-libgcc",
83        "references": [],
84        "valid": true
85      },
86      {
87        "closureSize": 33294120,
88        "narHash": "sha256:16xw6ngrqak6fm91njbgpyq70rjjrmf4y1gcmrwzi199p01lbxcg",
89        "narSize": 274640,
90        "path": "/nix/store/mi08jhbcjib1i1kgvbd0fxn2yrnzdv4a-hello-2.12.2",
91        "references": [
92          "/nix/store/mi08jhbcjib1i1kgvbd0fxn2yrnzdv4a-hello-2.12.2",
93          "/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47"
94        ],
95        "valid": true
96      },
97      {
98        "closureSize": 2078792,
99        "narHash": "sha256:1vy1c2rfgdgfy5lpgfkd58d0ly7ripfxsx4m99rx434sh3rdy45d",
100        "narSize": 2078792,
101        "path": "/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1",
102        "references": [
103          "/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1"
104        ],
105        "valid": true
106      },
107      {
108        "closureSize": 33019480,
109        "narHash": "sha256:1r6rinhxn3a2mrmvdkmakvqvn9cn302yi08vqzwvjjzjjl77fy0k",
110        "narSize": 30374728,
111        "path": "/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47",
112        "references": [
113          "/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8",
114          "/nix/store/kbijm6lc9va8xann3cfyam0vczzmwkxj-xgcc-15.2.0-libgcc",
115          "/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47"
116        ],
117        "valid": true
118      }
119    ]
120    "#;
121        serde_json::from_str::<Vec<PathData<'static>>>(json_str).expect("must deserialize")
122    });
123
124    #[test]
125    fn test_validity_registration_complex() {
126        let mut s = String::new();
127        make_validity_registration(
128            &mut s,
129            CLOSURE_HELLO
130                .iter()
131                .map(|elem| (&elem.path, elem.references.iter())),
132        )
133        .expect("must succeed");
134
135        assert_eq!(
136            r#"/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8
137
1382
139/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8
140/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1
141/nix/store/kbijm6lc9va8xann3cfyam0vczzmwkxj-xgcc-15.2.0-libgcc
142
1430
144/nix/store/mi08jhbcjib1i1kgvbd0fxn2yrnzdv4a-hello-2.12.2
145
1462
147/nix/store/mi08jhbcjib1i1kgvbd0fxn2yrnzdv4a-hello-2.12.2
148/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47
149/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1
150
1511
152/nix/store/pkphs076yz5ajnqczzj0588n6miph269-libunistring-1.4.1
153/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47
154
1553
156/nix/store/d0d9wqmw5saaynfvmszsda3dmh5q82z8-libidn2-2.3.8
157/nix/store/kbijm6lc9va8xann3cfyam0vczzmwkxj-xgcc-15.2.0-libgcc
158/nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47
159"#,
160            s
161        );
162    }
163
164    #[test]
165    fn test_validity_registration_simple() {
166        let mut s = String::new();
167
168        let sp_libiconv = StorePathRef::from_absolute_path(
169            b"/nix/store/2ilm1l0xy457r1py73n1sxh2c8pc1sq1-libiconv-109",
170        )
171        .expect("must parse");
172        let sp_hello = StorePathRef::from_absolute_path(
173            b"/nix/store/8ha1dhmx807czjczmwy078s4r9s254il-hello-2.12.2",
174        )
175        .expect("must parse");
176
177        let elems = vec![(&sp_libiconv, [&sp_libiconv]), (&sp_hello, [&sp_libiconv])];
178
179        make_validity_registration(
180            &mut s,
181            elems
182                .as_slice()
183                .iter()
184                .map(|(path, refs)| ((*path), refs.iter().copied())),
185        )
186        .expect("must succeed");
187
188        assert_eq!(
189            r#"/nix/store/2ilm1l0xy457r1py73n1sxh2c8pc1sq1-libiconv-109
190
1911
192/nix/store/2ilm1l0xy457r1py73n1sxh2c8pc1sq1-libiconv-109
193/nix/store/8ha1dhmx807czjczmwy078s4r9s254il-hello-2.12.2
194
1951
196/nix/store/2ilm1l0xy457r1py73n1sxh2c8pc1sq1-libiconv-109
197"#,
198            s
199        );
200    }
201}