Merge branch 'master' into feat/issue-610-live-remote-parity
This commit is contained in:
@@ -320,3 +320,128 @@ def format_parity(assessment: dict) -> str:
|
||||
if not assessment.get("determinable"):
|
||||
return "parity indeterminate (baseline or current HEAD unknown)"
|
||||
return f"in parity at {_short(assessment.get('current_head'))}"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Target-repository parity (#739 F3)
|
||||
#
|
||||
# Everything above measures ONE dimension: the Gitea-Tools server's own
|
||||
# implementation commit, comparing the SHA this process was loaded from against
|
||||
# the SHA now on disk at PROJECT_ROOT. That is deliberate and is left untouched
|
||||
# — it is what proves the in-memory capability gates are current.
|
||||
#
|
||||
# It is not, however, a statement about the repository a cross-repository
|
||||
# namespace actually mutates. The assessment below is a separate, separately
|
||||
# labelled dimension for the configured canonical target repository. It never
|
||||
# feeds the mutation gate and never changes startup_head/current_head.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
DEFAULT_TARGET_TRACKING_REF = "refs/remotes/origin/master"
|
||||
|
||||
|
||||
def _git_capture(root: str, *args: str) -> str | None:
|
||||
"""Run a read-only git command in *root*; ``None`` on any failure.
|
||||
|
||||
Deliberately does not honour ``GITEA_TEST_CURRENT_HEAD``: that override
|
||||
exists to pin the *server's* HEAD, and applying it here would make a target
|
||||
repository silently report the server's forced SHA.
|
||||
"""
|
||||
if not root:
|
||||
return None
|
||||
try:
|
||||
res = subprocess.run(
|
||||
["git", "-C", root, *args],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
except Exception:
|
||||
return None
|
||||
if res.returncode != 0:
|
||||
return None
|
||||
return (res.stdout or "").strip() or None
|
||||
|
||||
|
||||
def assess_target_repository_parity(
|
||||
*,
|
||||
canonical_root: str | None,
|
||||
source: str | None,
|
||||
tracking_ref: str = DEFAULT_TARGET_TRACKING_REF,
|
||||
) -> dict:
|
||||
"""Assess the configured cross-repository target checkout.
|
||||
|
||||
Reports the target's canonical root, repository identity, checked-out
|
||||
commit, and last-known remote master commit, plus whether the checkout is
|
||||
behind that ref. No network call is made: the remote side is read from the
|
||||
existing remote-tracking ref, so a target that has never been fetched is
|
||||
reported as indeterminate rather than guessed at.
|
||||
|
||||
An unconfigured namespace is ``configured=False`` and never ``stale`` — the
|
||||
single-repository default has no second dimension to be stale about. A
|
||||
configured root that cannot be read is ``determinable=False`` with reasons.
|
||||
"""
|
||||
result = {
|
||||
"configured": bool(canonical_root),
|
||||
"canonical_repository_root": None,
|
||||
"source": source,
|
||||
"repository_slug": None,
|
||||
"checkout_head": None,
|
||||
"tracking_ref": tracking_ref,
|
||||
"remote_tracking_head": None,
|
||||
"determinable": False,
|
||||
"stale": False,
|
||||
"reasons": [],
|
||||
}
|
||||
if not canonical_root:
|
||||
result["determinable"] = True
|
||||
return result
|
||||
|
||||
result["canonical_repository_root"] = canonical_root
|
||||
if not os.path.isdir(canonical_root):
|
||||
result["reasons"].append(
|
||||
f"configured canonical repository root '{canonical_root}' "
|
||||
f"does not exist or is not a directory"
|
||||
)
|
||||
return result
|
||||
|
||||
toplevel = _git_capture(canonical_root, "rev-parse", "--show-toplevel")
|
||||
if not toplevel:
|
||||
result["reasons"].append(
|
||||
f"configured canonical repository root '{canonical_root}' "
|
||||
f"is not a git checkout"
|
||||
)
|
||||
return result
|
||||
|
||||
head = _git_capture(canonical_root, "rev-parse", "HEAD")
|
||||
if not head:
|
||||
result["reasons"].append(
|
||||
f"target repository HEAD could not be read at '{canonical_root}'"
|
||||
)
|
||||
return result
|
||||
result["checkout_head"] = head
|
||||
result["determinable"] = True
|
||||
|
||||
remote_url = _git_capture(canonical_root, "remote", "get-url", "origin")
|
||||
if remote_url:
|
||||
# Local import keeps this module dependency-light for its startup role.
|
||||
import remote_repo_guard
|
||||
|
||||
parsed = remote_repo_guard.parse_org_repo_from_remote_url(remote_url)
|
||||
if parsed:
|
||||
result["repository_slug"] = f"{parsed[0]}/{parsed[1]}"
|
||||
if not result["repository_slug"]:
|
||||
result["reasons"].append(
|
||||
"target repository identity could not be derived from its git remote"
|
||||
)
|
||||
|
||||
tracking_head = _git_capture(canonical_root, "rev-parse", tracking_ref)
|
||||
if not tracking_head:
|
||||
result["reasons"].append(
|
||||
f"remote-tracking ref '{tracking_ref}' is unknown in the target "
|
||||
f"checkout; target staleness is indeterminate (no fetch is "
|
||||
f"performed by this assessment)"
|
||||
)
|
||||
return result
|
||||
result["remote_tracking_head"] = tracking_head
|
||||
result["stale"] = tracking_head != head
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user