Files
troupe-standup/wizard-work/beam/tree_root.py
T
ledger 232c8af304 volt: Q90 -- tree_root.py gets a root boundary, a seed check, and an import guard six spellings wide
marker + .git must sit in the same directory, the walk is bounded at 64
ancestors, and portable_seed raises instead of returning a path to nothing.
Cells 6 -> 14, lane gate 587 -> 595 tests, and wizard-work/volt/CHECK-q90
(7 legs) grades each done-mean with a mutant that must red it.
2026-10-30 23:42:26 +00:00

80 lines
3.1 KiB
Python

"""tree_root.py - derive a repo root from __file__ instead of a host-absolute path.
Boundary rule (Q90, 2026-10-30). A marker file alone is not a repository: a
stray ``WORK-QUEUE.md`` in a parent directory -- a download, an unpacked
tarball, a second checkout, a vendor drop -- satisfies the marker test and
wins the walk, so the root a caller resolves can be a directory this tree
does not own, and every path derived from it lands in the wrong tree. A
candidate therefore counts only when the marker *and* a ``.git`` entry sit in
the same directory: the pair a real checkout carries and a decoy does not.
The walk is also bounded -- 64 ancestors by default, or ``max_depth`` -- so a
pathological tree cannot walk to ``/`` and adopt a foreign marker there.
Callers that genuinely grade a marker-only tree (a fixture, an export with no
VCS) pass ``require_git=False``; that is an explicit weakening, not the
default, and the caller owns it.
"""
from __future__ import annotations
import os
DEFAULT_MARKER = "WORK-QUEUE.md"
DEFAULT_MAX_DEPTH = 64
def find_tree_root(start, marker=DEFAULT_MARKER, require_git=True,
max_depth=DEFAULT_MAX_DEPTH):
"""Return the repository root at or above ``start``.
A candidate directory must contain ``marker`` and, when ``require_git`` is
true (the default), a ``.git`` entry as well. At most ``max_depth``
ancestors are examined. Raises ``FileNotFoundError`` when no candidate
qualifies -- never falls back to the topmost directory it happened to see.
"""
cur = os.path.realpath(start)
if os.path.isfile(cur):
cur = os.path.dirname(cur)
want = "marker %r%s" % (marker, " and .git" if require_git else "")
depth = 0
while True:
if os.path.isfile(os.path.join(cur, marker)):
if not require_git or os.path.exists(os.path.join(cur, ".git")):
return cur
parent = os.path.dirname(cur)
depth += 1
if parent == cur or depth > max_depth:
raise FileNotFoundError(
"%s not found in %d ancestor(s) of %s" % (want, max_depth, start)
)
cur = parent
def assert_inside_tree(path, root):
rp = os.path.realpath(path)
rr = os.path.realpath(root)
if rp == rr or rp.startswith(rr + os.sep):
return rp
raise ValueError("path %s escapes tree root %s" % (rp, rr))
def portable_seed(root, rel="inbox/seed-2026-09-26.json"):
"""Return the absolute seed path inside ``root``, or raise.
Raises ``FileNotFoundError`` when the seed does not exist: returning a
path to a file that is not there is the failure this function exists to
prevent, and a caller that trusts the return value would read it later,
far from the root that never had it. Raises ``ValueError`` (via
``assert_inside_tree``) when ``rel`` escapes ``root``.
"""
p = assert_inside_tree(os.path.join(root, rel), root)
if not os.path.isfile(p):
raise FileNotFoundError("seed not found inside tree root %s: %s" % (root, p))
return p
if __name__ == "__main__":
r = find_tree_root(__file__)
p = portable_seed(r)
print("root=", r)
print("seed=", p)