1#![allow(clippy::useless_vec)]
6
7pub mod context;
8pub mod hakari_toml;
9pub mod summaries;
10
11use crate::{
12 context::{ContextImpl, GenerateContext},
13 hakari_toml::HakariTomlContext,
14 summaries::*,
15};
16use anyhow::{anyhow, bail, Result};
17use clap::arg_enum;
18use fixtures::json::JsonFixture;
19use structopt::StructOpt;
20
21#[derive(Debug, StructOpt)]
22pub struct FixtureManager {
23 #[structopt(subcommand)]
25 cmd: Command,
26}
27
28impl FixtureManager {
29 pub fn exec(self) -> Result<()> {
30 match self.cmd {
31 Command::List => list(),
32 Command::GenerateSummaries(opts) => opts.exec(),
33 Command::GenerateHakari(opts) => opts.exec(),
34 }
35 }
36}
37
38#[derive(Debug, StructOpt)]
39enum Command {
40 #[structopt(name = "list")]
41 List,
43 GenerateSummaries(GenerateSummariesOpts),
45 GenerateHakari(GenerateHakariOpts),
47}
48
49pub fn list() -> Result<()> {
50 for (name, fixture) in JsonFixture::all_fixtures().iter() {
51 println!("{}: {}", name, fixture.workspace_path());
52 }
53
54 Ok(())
55}
56
57#[derive(Debug, StructOpt)]
58pub struct GenerateSummariesOpts {
59 #[structopt(long, default_value = Self::DEFAULT_COUNT_STR)]
61 pub count: usize,
62
63 #[structopt(flatten)]
64 pub generate_opts: GenerateOpts,
65}
66
67impl GenerateSummariesOpts {
68 pub const DEFAULT_COUNT_STR: &'static str = "8";
70
71 pub fn default_count() -> usize {
73 Self::DEFAULT_COUNT_STR
74 .parse()
75 .expect("DEFAULT_COUNT_STR should parse as a usize")
76 }
77}
78
79#[derive(Debug, StructOpt)]
80pub struct GenerateHakariOpts {
81 #[structopt(long, default_value = Self::DEFAULT_COUNT_STR)]
83 pub count: usize,
84
85 #[structopt(flatten)]
86 pub generate_opts: GenerateOpts,
87}
88
89impl GenerateHakariOpts {
90 pub const DEFAULT_COUNT_STR: &'static str = "4";
92
93 pub fn default_count() -> usize {
95 Self::DEFAULT_COUNT_STR
96 .parse()
97 .expect("DEFAULT_COUNT_STR should parse as a usize")
98 }
99}
100
101#[derive(Debug, StructOpt)]
102pub struct GenerateOpts {
103 #[structopt(long, short, possible_values = &GenerateMode::variants(), case_insensitive = true, default_value = "generate")]
105 pub mode: GenerateMode,
106
107 #[structopt(long)]
109 pub fixtures: Vec<String>,
110}
111
112arg_enum! {
113 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
114 pub enum GenerateMode {
115 Generate,
116 Check,
117 Force,
118 }
119}
120
121impl GenerateSummariesOpts {
122 pub fn exec(self) -> Result<()> {
123 self.generate_opts.exec::<SummaryContext>(self.count)
124 }
125}
126
127impl GenerateHakariOpts {
128 pub fn exec(self) -> Result<()> {
129 self.generate_opts.exec::<HakariTomlContext>(self.count)
130 }
131}
132
133impl GenerateOpts {
134 pub fn exec<'g, T: ContextImpl<'g>>(self, args: T::IterArgs) -> Result<()> {
135 let fixtures: Box<dyn Iterator<Item = (&str, &JsonFixture)>> = if self.fixtures.is_empty() {
136 Box::new(
137 JsonFixture::all_fixtures()
138 .iter()
139 .map(|(name, fixture)| (*name, fixture)),
140 )
141 } else {
142 let fixtures = self
143 .fixtures
144 .iter()
145 .map(|name| {
146 let fixture = JsonFixture::by_name(name)
147 .ok_or_else(|| anyhow!("unknown fixture: {}", name))?;
148 Ok((name.as_str(), fixture))
149 })
150 .collect::<Result<Vec<_>>>()?;
151 Box::new(fixtures.into_iter())
152 };
153
154 let mut num_changed = 0;
155
156 for (name, fixture) in fixtures {
157 println!("generating outputs for {}...", name);
158
159 let context: GenerateContext<'_, T> =
160 GenerateContext::new(fixture, &args, self.mode == GenerateMode::Force)?;
161 for item in context {
162 let item = item?;
163 let is_changed = item.is_changed();
164
165 if is_changed {
166 num_changed += 1;
167 }
168
169 if self.mode == GenerateMode::Check {
170 if is_changed {
171 println!("** {}:\n{}", item.path(), item.diff());
172 }
173
174 continue;
175 }
176
177 if is_changed || self.mode == GenerateMode::Force {
178 item.write_to_path()?;
179 }
180 }
181 }
182
183 if self.mode == GenerateMode::Check && num_changed > 0 {
184 bail!("{} outputs changed", num_changed);
185 }
186
187 println!("{} outputs changed", num_changed);
188
189 Ok(())
190 }
191}