Skip to content

Commit f972fbe

Browse files
committed
Merge remote-tracking branch 'origin/main'
# Conflicts: # src/main.rs # src/render.rs
2 parents 4baf410 + aecbab0 commit f972fbe

5 files changed

Lines changed: 716 additions & 240 deletions

File tree

src/diagnostics.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//! Structured diagnostics gathered during planning and optionally exposed to operators.
2+
//!
3+
//! Planner anomalies (unparsable XML, empty metadata, orphan child laws) flow into
4+
//! [`Diagnostics`], which feeds both the `--validate` JSON report and the post-build
5+
//! `--manifest` payload.
6+
7+
use std::path::Path;
8+
9+
use anyhow::{Context, Result};
10+
use serde::Serialize;
11+
12+
use rustc_hash::FxHashMap as HashMap;
13+
14+
/// Record for one cached XML file that failed the planning pass.
15+
#[derive(Serialize, Debug, Clone)]
16+
pub struct UnparsableRecord {
17+
/// Source file name (basename) of the offending XML document.
18+
pub file: String,
19+
/// Human-readable parser error message.
20+
pub error: String,
21+
}
22+
23+
/// Record for one planned child entry whose parent 법률 is missing from the cache.
24+
#[derive(Serialize, Debug, Clone)]
25+
pub struct OrphanRecord {
26+
/// Original law name reported by the child entry.
27+
pub law_name: String,
28+
/// Law-type label of the orphan child (e.g. 대통령령).
29+
pub law_type: String,
30+
/// Normalized parent group name that was expected but not found.
31+
pub parent_group: String,
32+
}
33+
34+
/// Accumulated planning diagnostics shared by validate and build paths.
35+
#[derive(Serialize, Debug, Default)]
36+
pub struct Diagnostics {
37+
/// Cache files whose XML failed to parse.
38+
pub unparsable: Vec<UnparsableRecord>,
39+
/// Cache file names whose basic metadata block was empty.
40+
pub empty_metadata: Vec<String>,
41+
/// Planned child entries whose parent 법률 could not be located.
42+
pub orphan_children: Vec<OrphanRecord>,
43+
/// Count of planned entries keyed by law_type.
44+
pub by_type: HashMap<String, usize>,
45+
/// Total XML files observed in the detail cache directory.
46+
pub total_xml: usize,
47+
}
48+
49+
impl Diagnostics {
50+
/// Returns true when no anomalies were collected.
51+
pub fn is_clean(&self) -> bool {
52+
self.unparsable.is_empty()
53+
&& self.empty_metadata.is_empty()
54+
&& self.orphan_children.is_empty()
55+
}
56+
}
57+
58+
/// Pre-flight validation report emitted via stdout when `--validate` is set.
59+
#[derive(Serialize, Debug)]
60+
pub struct ValidationReport<'a> {
61+
/// Total XML files observed in the detail cache directory.
62+
pub total_xml: usize,
63+
/// Cache files whose XML failed to parse.
64+
pub unparsable: &'a [UnparsableRecord],
65+
/// Cache file names whose basic metadata block was empty.
66+
pub empty_metadata: &'a [String],
67+
/// Planned child entries whose parent 법률 could not be located.
68+
pub orphan_children: &'a [OrphanRecord],
69+
/// Planned entry counts keyed by law_type.
70+
pub by_type: &'a HashMap<String, usize>,
71+
/// Operator-supplied expected law total (via `--expect-laws`), if any.
72+
pub expected_laws: Option<usize>,
73+
/// Actual planned entry count after pass 1.
74+
pub actual_laws: usize,
75+
}
76+
77+
/// Build manifest JSON written to disk after a successful build.
78+
#[derive(Serialize, Debug)]
79+
pub struct BuildManifest<'a> {
80+
/// Manifest schema version.
81+
pub schema_version: u32,
82+
/// HEAD commit SHA of the finished bare repository (lowercase hex, 40 chars).
83+
pub head_commit_sha: String,
84+
/// Total number of planned entries committed into the output repository.
85+
pub entries_total: usize,
86+
/// Cache files whose XML failed to parse.
87+
pub unparsable: &'a [UnparsableRecord],
88+
/// Cache file names whose basic metadata block was empty.
89+
pub empty_metadata: &'a [String],
90+
/// Planned child entries whose parent 법률 could not be located.
91+
pub orphan_children: &'a [OrphanRecord],
92+
/// Planned entry counts keyed by law_type.
93+
pub by_type: &'a HashMap<String, usize>,
94+
}
95+
96+
/// Writes a pretty-printed manifest JSON payload to the given path.
97+
pub fn write_manifest(path: &Path, manifest: &BuildManifest) -> Result<()> {
98+
let json = serde_json::to_string_pretty(manifest)
99+
.context("failed to serialize build manifest as JSON")?;
100+
std::fs::write(path, json)
101+
.with_context(|| format!("failed to write manifest to {}", path.display()))?;
102+
Ok(())
103+
}

src/git_repo.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,10 @@ impl BareRepoWriter {
432432
}
433433

434434
/// Finalizes the pack, writes `main` as loose refs, and moves the temporary repo into place.
435-
pub fn finish(mut self) -> Result<()> {
435+
///
436+
/// Returns the HEAD commit SHA of the finished repository, or `[0u8; 20]` when no commits
437+
/// were ever appended.
438+
pub fn finish(mut self) -> Result<[u8; 20]> {
436439
self.writer.finish()?;
437440

438441
if let Some(parent_commit) = self.parent_commit {
@@ -462,7 +465,7 @@ impl BareRepoWriter {
462465
self.final_output.display()
463466
)
464467
})?;
465-
Ok(())
468+
Ok(self.parent_commit.unwrap_or([0u8; 20]))
466469
}
467470

468471
/// Commits one file change after updating blob and tree state.
@@ -1524,7 +1527,7 @@ fn hex_buf(sha: &[u8; 20]) -> [u8; 40] {
15241527
}
15251528

15261529
/// Hex-encodes one object id for refs, logging, and non-hot-path usage.
1527-
fn hex(sha: &[u8; 20]) -> String {
1530+
pub(crate) fn hex(sha: &[u8; 20]) -> String {
15281531
let buf = hex_buf(sha);
15291532
String::from_utf8(buf.to_vec()).expect("hex digits are valid UTF-8")
15301533
}

0 commit comments

Comments
 (0)