Add forced full-site rendering

This commit is contained in:
2026-07-23 10:23:02 +02:00
parent d87e80f96b
commit 2844ed5a47
21 changed files with 611 additions and 122 deletions

View File

@@ -6,7 +6,8 @@ use bds_core::db::queries::template::insert_template;
use bds_core::engine::generation::{
GenerationSection, PublishedPostSource, apply_validation_section_with_progress,
apply_validation_sections, build_site_search_index, generate_starter_site,
load_published_post_source, render_site_section_with_progress, sections_from_validation_report,
generate_starter_site_forced, load_published_post_source, render_site_section_with_progress,
sections_from_validation_report,
};
use bds_core::engine::meta::write_category_meta_json;
use bds_core::engine::validate_site::validate_site;
@@ -742,6 +743,61 @@ fn generation_engine_skips_unchanged_outputs_on_second_run() {
);
}
#[test]
fn forced_generation_rewrites_unchanged_outputs_without_erasing_unrelated_cache_records() {
let (db, dir) = setup();
let metadata = make_metadata();
let posts = vec![PublishedPostSource {
post: make_post("hello", 1_710_000_000_000),
body_markdown: "Hello **world**".into(),
}];
generate_starter_site(db.conn(), dir.path(), "p1", &metadata, &posts, "en").unwrap();
let unchanged =
generate_starter_site(db.conn(), dir.path(), "p1", &metadata, &posts, "en").unwrap();
assert!(unchanged.skipped_paths.contains(&"index.html".to_string()));
std::fs::write(dir.path().join("index.html"), "tampered").unwrap();
let normal_after_drift =
generate_starter_site(db.conn(), dir.path(), "p1", &metadata, &posts, "en").unwrap();
assert!(
normal_after_drift
.skipped_paths
.contains(&"index.html".to_string())
);
assert_eq!(
std::fs::read_to_string(dir.path().join("index.html")).unwrap(),
"tampered"
);
bds_core::db::queries::generated_file_hash::upsert_generated_file_hash(
db.conn(),
&bds_core::model::GeneratedFileHash {
project_id: "p1".into(),
relative_path: "legacy-output.txt".into(),
content_hash: "legacy".into(),
updated_at: 42,
},
)
.unwrap();
let forced =
generate_starter_site_forced(db.conn(), dir.path(), "p1", &metadata, &posts, "en").unwrap();
assert!(forced.written_paths.contains(&"index.html".to_string()));
assert!(forced.skipped_paths.is_empty());
assert_ne!(
std::fs::read_to_string(dir.path().join("index.html")).unwrap(),
"tampered"
);
assert!(
bds_core::db::queries::generated_file_hash::get_generated_file_hash(
db.conn(),
"p1",
"legacy-output.txt",
)
.is_ok()
);
}
#[test]
fn site_validation_matches_bds2_index_route_comparison() {
let (db, dir) = setup();

View File

@@ -6,6 +6,7 @@ use bds_core::db::queries::project::insert_project;
use bds_core::model::{Post, PostStatus, Project};
use bds_core::render::{
GeneratedWriteOutcome, build_calendar_json, build_core_generation_paths, write_generated_file,
write_generated_file_forced,
};
use tempfile::TempDir;
@@ -95,7 +96,7 @@ fn generated_write_rewrites_missing_file_even_when_hash_matches() {
}
#[test]
fn generated_write_rewrites_stale_file_even_when_db_hash_matches() {
fn generated_write_trusts_the_cached_hash_like_bds2() {
let (db, dir) = setup();
let first = write_generated_file(db.conn(), dir.path(), "p1", "index.html", "hello").unwrap();
@@ -103,7 +104,23 @@ fn generated_write_rewrites_stale_file_even_when_db_hash_matches() {
let second = write_generated_file(db.conn(), dir.path(), "p1", "index.html", "hello").unwrap();
assert_eq!(first, GeneratedWriteOutcome::Written);
assert_eq!(second, GeneratedWriteOutcome::Written);
assert_eq!(second, GeneratedWriteOutcome::SkippedUnchanged);
assert_eq!(
fs::read_to_string(dir.path().join("index.html")).unwrap(),
"tampered"
);
}
#[test]
fn forced_generated_write_ignores_the_cached_hash() {
let (db, dir) = setup();
write_generated_file(db.conn(), dir.path(), "p1", "index.html", "hello").unwrap();
fs::write(dir.path().join("index.html"), "tampered").unwrap();
let forced =
write_generated_file_forced(db.conn(), dir.path(), "p1", "index.html", "hello").unwrap();
assert_eq!(forced, GeneratedWriteOutcome::Written);
assert_eq!(
fs::read_to_string(dir.path().join("index.html")).unwrap(),
"hello"