fixture_manager/
hakari_toml.rs1use crate::context::ContextImpl;
5use anyhow::Result;
6use camino::{Utf8Path, Utf8PathBuf};
7use fixtures::json::*;
8use hakari::{Hakari, HakariBuilder, HakariCargoToml, HakariOutputOptions, diffy::PatchFormatter};
9use once_cell::sync::Lazy;
10use proptest::prelude::*;
11use proptest_ext::ValueGenerator;
12
13pub struct HakariTomlContext;
14
15impl<'g> ContextImpl<'g> for HakariTomlContext {
16 type IterArgs = usize;
17 type IterItem = (usize, HakariTomlItem<'g>);
18 type Existing = HakariCargoToml;
19
20 fn dir_name(fixture: &'g JsonFixture) -> Utf8PathBuf {
21 fixture
22 .abs_path()
23 .parent()
24 .expect("up to dirname of summary")
25 .join("hakari")
26 }
27
28 fn file_name(fixture: &'g JsonFixture, &(count, _): &Self::IterItem) -> String {
29 format!("{}-{}.toml", fixture.name(), count)
30 }
31
32 fn iter(
33 fixture: &'g JsonFixture,
34 &count: &Self::IterArgs,
35 ) -> Box<dyn Iterator<Item = Self::IterItem> + 'g> {
36 let mut generator = ValueGenerator::from_seed(fixture.name());
39
40 let graph = fixture.graph();
41 let hakari_builder_strategy = HakariBuilder::proptest1_strategy(graph, Just(None));
44
45 let iter = (0..count).map(move |idx| {
46 let mut iter_generator = generator.partial_clone();
49 let mut builder = iter_generator
50 .partial_clone()
51 .generate(&hakari_builder_strategy);
52
53 if fixture.name() == "metadata_alternate_registries" {
55 builder.add_registries([("my-registry", METADATA_ALTERNATE_REGISTRY_URL)]);
56 }
57
58 let hakari = builder.compute();
59 let mut output_options = HakariOutputOptions::default();
60 output_options
61 .set_builder_summary(true)
62 .set_absolute_paths(true);
63 let toml = hakari
64 .to_toml_string(&output_options)
65 .expect("to_toml_string worked");
66
67 (idx, HakariTomlItem { hakari, toml })
68 });
69 Box::new(iter)
70 }
71
72 fn parse_existing(path: &Utf8Path, contents: String) -> Result<Self::Existing> {
73 Ok(HakariCargoToml::new_in_memory(path, contents)?)
74 }
75
76 fn is_changed((_, item): &Self::IterItem, existing: &Self::Existing) -> bool {
77 existing.is_changed(&item.toml)
78 }
79
80 fn diff(
81 _fixture: &'g JsonFixture,
82 (_, item): &Self::IterItem,
83 existing: Option<&Self::Existing>,
84 ) -> String {
85 static DEFAULT_EXISTING: Lazy<HakariCargoToml> = Lazy::new(|| {
86 let contents = format!(
87 "{}{}",
88 HakariCargoToml::BEGIN_SECTION,
89 HakariCargoToml::END_SECTION
90 );
91 HakariCargoToml::new_in_memory("default", contents)
92 .expect("contents are in correct format")
93 });
94
95 let existing = existing.unwrap_or(&*DEFAULT_EXISTING);
96
97 let diff = existing.diff_toml(&item.toml);
98 let formatter = PatchFormatter::new();
99
100 format!("{}", formatter.fmt_patch(&diff))
101
102 }
113
114 fn write_to_string(
115 fixture: &'g JsonFixture,
116 (_, item): &Self::IterItem,
117 out: &mut String,
118 ) -> Result<()> {
119 let out_contents = format!(
121 "# This file is @generated. To regenerate, run:\n\
122 # cargo run -p fixture-manager -- generate-hakari --fixture {}\n\
123 \n\
124 ### BEGIN HAKARI SECTION\n\
125 \n\
126 ### END HAKARI SECTION\n\
127 \n\
128 # This part of the file should be preserved at the end.\n",
129 fixture.name()
130 );
131
132 let new_toml = HakariCargoToml::new_in_memory("bogus", out_contents)?;
133 Ok(new_toml.write_to_fmt(&item.toml, out)?)
134 }
135}
136
137pub struct HakariTomlItem<'g> {
138 #[allow(dead_code)]
139 hakari: Hakari<'g>,
140 toml: String,
141}