| 246 |
246 |
|
/// one decision, and drift between them is a real defect, because a build that
|
| 247 |
247 |
|
/// bypasses the TUI has to get the stack the TUI would have asked for.
|
| 248 |
248 |
|
///
|
| 249 |
|
- |
/// Asserted against `image.rs` as text rather than by importing it: the crate is
|
|
249 |
+ |
/// Asserted against `image/choices.rs` as text rather than by importing it: the crate is
|
| 250 |
250 |
|
/// a binary, the test is a text check over the Containerfile in the spirit of
|
| 251 |
251 |
|
/// the rest of this file, and the point is that the two spellings agree.
|
| 252 |
252 |
|
///
|
| 262 |
262 |
|
.find_map(|line| line.strip_prefix("ARG LANGS="))
|
| 263 |
263 |
|
.expect("no ARG LANGS in the Containerfile");
|
| 264 |
264 |
|
|
| 265 |
|
- |
let source =
|
| 266 |
|
- |
std::fs::read_to_string(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/image.rs"))
|
| 267 |
|
- |
.expect("cannot read image.rs");
|
|
265 |
+ |
let source = std::fs::read_to_string(
|
|
266 |
+ |
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/image/choices.rs"),
|
|
267 |
+ |
)
|
|
268 |
+ |
.expect("cannot read image/choices.rs");
|
| 268 |
269 |
|
// The derive is the default while there is no hand-written one, and a
|
| 269 |
270 |
|
// derived `BTreeSet` is empty. Scoped to `impl Default for Choices` rather
|
| 270 |
271 |
|
// than any `langs: BTreeSet::` line, because the tests below `Choices`
|
| 300 |
301 |
|
|
| 301 |
302 |
|
assert_eq!(
|
| 302 |
303 |
|
from_arg, from_builder,
|
| 303 |
|
- |
"ARG LANGS={arg:?} and image.rs's default disagree; they are one decision",
|
|
304 |
+ |
"ARG LANGS={arg:?} and the builder's default disagree; they are one decision",
|
| 304 |
305 |
|
);
|
| 305 |
306 |
|
}
|
| 306 |
307 |
|
|
| 335 |
336 |
|
.expect("no ARG DB in the Containerfile")
|
| 336 |
337 |
|
.trim();
|
| 337 |
338 |
|
|
| 338 |
|
- |
let source =
|
| 339 |
|
- |
std::fs::read_to_string(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/image.rs"))
|
| 340 |
|
- |
.expect("cannot read image.rs");
|
|
339 |
+ |
let source = std::fs::read_to_string(
|
|
340 |
+ |
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/image/choices.rs"),
|
|
341 |
+ |
)
|
|
342 |
+ |
.expect("cannot read image/choices.rs");
|
| 341 |
343 |
|
assert!(
|
| 342 |
344 |
|
source.contains("db: Db::default()") || derives_default(&source),
|
| 343 |
345 |
|
"the builder does not default its db field"
|
| 350 |
352 |
|
.split_once("pub(crate) enum Db {")
|
| 351 |
353 |
|
.and_then(|(_, rest)| rest.split_once('}'))
|
| 352 |
354 |
|
.map(|(body, _)| body)
|
| 353 |
|
- |
.expect("no Db enum in image.rs");
|
|
355 |
+ |
.expect("no Db enum in image/choices.rs");
|
| 354 |
356 |
|
let variant = body
|
| 355 |
357 |
|
.split_once("#[default]")
|
| 356 |
358 |
|
.and_then(|(_, rest)| rest.split(',').next())
|
| 391 |
393 |
|
/// The language whitelist lives in three files, and nothing bound them.
|
| 392 |
394 |
|
///
|
| 393 |
395 |
|
/// The Containerfile validates `LANGS` against a `case` arm, `Lang::ALL` in
|
| 394 |
|
- |
/// image.rs is what the builder TUI offers, and build/preflight.py refuses a
|
|
396 |
+ |
/// `image/choices.rs` is what the builder TUI offers, and build/preflight.py refuses a
|
| 395 |
397 |
|
/// recipe naming anything else. Adding `c` on 2026-09-07 touched the first two
|
| 396 |
398 |
|
/// and missed the third, and the gate caught it at mint time, after the recipe
|
| 397 |
399 |
|
/// was already written and a build had been asked for.
|
| 416 |
418 |
|
})
|
| 417 |
419 |
|
.expect("no LANGS case arm in the Containerfile");
|
| 418 |
420 |
|
|
| 419 |
|
- |
let image =
|
| 420 |
|
- |
std::fs::read_to_string(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/image.rs"))
|
| 421 |
|
- |
.expect("cannot read image.rs");
|
|
421 |
+ |
let image = std::fs::read_to_string(
|
|
422 |
+ |
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("src/image/choices.rs"),
|
|
423 |
+ |
)
|
|
424 |
+ |
.expect("cannot read image/choices.rs");
|
| 422 |
425 |
|
let from_enum: Vec<String> = image
|
| 423 |
426 |
|
.split_once("const ALL: [Lang;")
|
| 424 |
427 |
|
.and_then(|(_, rest)| rest.split_once('['))
|
| 428 |
431 |
|
.filter_map(|e| e.trim().strip_prefix("Lang::").map(str::to_lowercase))
|
| 429 |
432 |
|
.collect()
|
| 430 |
433 |
|
})
|
| 431 |
|
- |
.expect("no Lang::ALL in image.rs");
|
|
434 |
+ |
.expect("no Lang::ALL in image/choices.rs");
|
| 432 |
435 |
|
|
| 433 |
436 |
|
let preflight = std::fs::read_to_string(
|
| 434 |
437 |
|
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../build/preflight.py"),
|