fix(docs): merge, not overwrite, COMPONENT lines on identity collision
collect_components() used dict.update(), which let conf.d silently overwrite functions/ (or vice versa) when the same bare identity appears in both, e.g. functions/auto-pull.fish and conf.d/auto-pull.fish. The runtime guard can only ever look up the bare status current-function/basename string, so both call sites genuinely share one identity and their raw COMPONENT lines must be concatenated, not replaced.
This commit is contained in:
@@ -23,10 +23,23 @@ OUTPUT = REPO / "conf.d" / "__fish_config_op_registry.fish"
|
||||
|
||||
|
||||
def collect_components() -> dict[str, list[str]]:
|
||||
"""Gather every `# COMPONENT` header across the whole repo."""
|
||||
out = mt.parse_components(REPO / "functions")
|
||||
out.update(mt.parse_components(REPO / "conf.d"))
|
||||
out.update(mt.parse_component_file(REPO / "config.fish"))
|
||||
"""Gather every `# COMPONENT` header across the whole repo.
|
||||
|
||||
Concatenates raw component lines when the same identity appears in
|
||||
more than one source (e.g. functions/auto-pull.fish and
|
||||
conf.d/auto-pull.fish both self-identify as "auto-pull" at runtime,
|
||||
since the guard can only ever look up the bare status
|
||||
current-function/basename string) rather than letting one silently
|
||||
overwrite the other.
|
||||
"""
|
||||
out: dict[str, list[str]] = {}
|
||||
for source in (
|
||||
mt.parse_components(REPO / "functions"),
|
||||
mt.parse_components(REPO / "conf.d"),
|
||||
mt.parse_component_file(REPO / "config.fish"),
|
||||
):
|
||||
for identity, lines in source.items():
|
||||
out.setdefault(identity, []).extend(lines)
|
||||
return out
|
||||
|
||||
|
||||
|
||||
@@ -938,6 +938,42 @@ def test_build_registry_keeps_sites_independent():
|
||||
assert not warnings
|
||||
|
||||
|
||||
def test_collect_components_merges_identity_collisions_across_sources():
|
||||
"""functions/auto-pull.fish and conf.d/auto-pull.fish both self-identify
|
||||
as "auto-pull" at runtime -- the guard only ever has the bare
|
||||
status current-function/basename string to look up with -- so
|
||||
collect_components must concatenate their raw COMPONENT lines
|
||||
rather than letting conf.d's entry silently overwrite functions'."""
|
||||
import generate_component_registry as gcr
|
||||
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
root = Path(d)
|
||||
(root / "functions").mkdir()
|
||||
(root / "conf.d").mkdir()
|
||||
(root / "functions" / "auto-pull.fish").write_text(
|
||||
"# COMPONENT\n"
|
||||
"# autoexec/sync\n"
|
||||
"function auto-pull\n"
|
||||
"end\n"
|
||||
)
|
||||
(root / "conf.d" / "auto-pull.fish").write_text(
|
||||
"# COMPONENT\n"
|
||||
"# autoexec/sync\n"
|
||||
)
|
||||
(root / "config.fish").write_text("")
|
||||
|
||||
orig_repo = gcr.REPO
|
||||
try:
|
||||
gcr.REPO = root
|
||||
got = gcr.collect_components()
|
||||
finally:
|
||||
gcr.REPO = orig_repo
|
||||
|
||||
assert got["auto-pull"] == ["autoexec/sync", "autoexec/sync"], (
|
||||
f"both sources' tags should survive the merge, not overwrite: {got}"
|
||||
)
|
||||
|
||||
|
||||
def test_render_registry_is_valid_fish_and_round_trips():
|
||||
"""Sourcing render()'s output must leave the two arrays in the exact
|
||||
shape __fish_config_op_registry_lookup expects -- checked via the real
|
||||
|
||||
Reference in New Issue
Block a user