1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//! Merging named files across a stack of roots — the sibling of
//! [`crate::frontmatter`], and for the same reason: two conventions
//! ([`crate::templates`] and [`crate::memory`]) load a set of markdown files,
//! strongest root first, into one name-keyed list, and this module lives here
//! once so the two cannot drift on what a duplicate name means.
//!
//! Two rules, and both are about what a *name* means, not what a *file* is:
//!
//! - **Within one root, a repeated name is the mistake it looks like.** Two
//! files claiming one name in the same directory is not a decision anyone
//! made on purpose, so [`load_root`] refuses rather than picking one
//! silently — and refuses in file order sorted first, so which file gets
//! blamed is stable across filesystems rather than whatever a directory
//! listing happened to return.
//! - **Across roots, a repeated name is intent — an override.** A workspace
//! template shadowing a global one of the same name, or a workspace memory
//! shadowing a personal one, is the whole point of having more than one
//! root; [`merge_roots`] keeps the strongest root's writer and drops the
//! rest silently, the way `HashMap::entry(..).or_insert(..)` always has.
//!
//! What is deliberately **not** shared: how a root's candidate files are
//! found (templates recurse for namespacing — `git/commit.md` is
//! `git:commit`; memory does not, because a memory names itself in
//! frontmatter and nesting would add nothing a name does not already say) and
//! how one file becomes one record (a template's name comes from its path, a
//! memory's from its own frontmatter). Both stay each caller's own, passed in
//! as the `parse_one` closure.
use ;
/// Parses every file in `paths` into one name-keyed map, sorting first so a
/// duplicate is always blamed on the same pair of files regardless of
/// directory-listing order.
///
/// `parse_one` reads and interprets one file, named by the same path this
/// function passes it, into `(name, value)`. `duplicate` builds the caller's
/// own error type when a second file in this same batch claims a name the
/// first already has — this function never decides *how* that is reported,
/// only *that* it is.
pub
/// Folds one convention's already-loaded roots into its final list,
/// strongest first: the first root to name something keeps it, every later
/// root's claim on the same name is silently dropped.
///
/// Takes the roots as an iterator of already-`Result`ed maps — each built by
/// [`load_root`] — rather than the raw sources, so a caller keeps its own
/// per-source loop (it is the one that knows how to turn one source into a
/// root) and this only ever does the folding.
pub