- Fix module reloading bug in task capability router (F-1) - Harden journal persistence and pending creations crash window (F-3) - Implement dirty worktree and author commit recovery preservation (F-4) - Fail closed on missing identity, profile, or session parameters (F-5) - Fix branches root path traversal and symlink validation (F-6) - Enforce O_NOFOLLOW and symlink checking on transition locks (F-7) - Support common ancestor merge-base verification for base SHA (F-8) - Release transition lock on compensating recovery (F-10) - Thread journal_dir through recovery and fix guidance strings (F-11, F-12) - Fix unittest mock import in bootstrap test suite (F-13)
This commit is contained in:
+46
-45
@@ -41,24 +41,14 @@ def _normalize_path(path: str) -> str:
|
||||
|
||||
|
||||
def get_canonical_branches_root(project_root: str | None = None) -> str:
|
||||
"""Resolve the exact canonical branches root directory for the repository."""
|
||||
if project_root:
|
||||
root = os.path.realpath(project_root)
|
||||
else:
|
||||
root = os.path.realpath(os.getcwd())
|
||||
|
||||
norm = root.replace("\\", "/")
|
||||
if "/branches/" in norm:
|
||||
base_part = norm.split("/branches/")[0]
|
||||
return os.path.realpath(os.path.join(base_part, "branches"))
|
||||
elif norm.endswith("/branches"):
|
||||
return os.path.realpath(norm)
|
||||
|
||||
return os.path.realpath(os.path.join(root, "branches"))
|
||||
"""Return the absolute path of the canonical branches directory for *project_root*."""
|
||||
root = os.path.realpath(project_root) if project_root else os.path.realpath(os.getcwd())
|
||||
canonical_repo_root = resolve_canonical_repo_root(root, root)
|
||||
return os.path.realpath(os.path.join(canonical_repo_root, "branches"))
|
||||
|
||||
|
||||
def is_path_under_branches(path: str, project_root: str | None = None) -> bool:
|
||||
"""True when *path* resolves inside ``<canonical_repo_root>/branches/``."""
|
||||
"""True when *path* resolves inside a canonical ``branches/`` directory."""
|
||||
if not path or not str(path).strip():
|
||||
return False
|
||||
try:
|
||||
@@ -66,16 +56,50 @@ def is_path_under_branches(path: str, project_root: str | None = None) -> bool:
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
branches_root = get_canonical_branches_root(project_root)
|
||||
branches_root = get_canonical_branches_root(project_root or real_path)
|
||||
try:
|
||||
common = os.path.commonpath([branches_root, real_path])
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
if real_path == branches_root:
|
||||
return True
|
||||
if common != branches_root:
|
||||
return False
|
||||
|
||||
prefix = branches_root + os.sep
|
||||
if real_path.startswith(prefix):
|
||||
return True
|
||||
rel = os.path.relpath(real_path, branches_root)
|
||||
return rel != "." and not rel.startswith("..")
|
||||
|
||||
return False
|
||||
|
||||
def resolve_canonical_repo_root(workspace_path: str, fallback_project_root: str) -> str:
|
||||
"""Return the stable repository root for *workspace_path* via git metadata (#460)."""
|
||||
p = (workspace_path or "").strip()
|
||||
if p:
|
||||
try:
|
||||
res = subprocess.run(
|
||||
["git", "-C", p, "rev-parse", "--git-common-dir"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
common = _realpath_git_common_dir(p, res.stdout)
|
||||
if common.endswith(f"{os.sep}.git") or os.path.basename(common) == ".git":
|
||||
candidate_root = os.path.dirname(common)
|
||||
real_p = os.path.realpath(p)
|
||||
try:
|
||||
if os.path.commonpath([candidate_root, real_p]) == candidate_root:
|
||||
return candidate_root
|
||||
except Exception:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
fallback = os.path.realpath(fallback_project_root or workspace_path or ".")
|
||||
norm = fallback.replace("\\", "/")
|
||||
if "/branches/" in norm:
|
||||
return os.path.realpath(norm.split("/branches/")[0])
|
||||
elif norm.endswith("/branches"):
|
||||
return os.path.realpath(os.path.dirname(fallback))
|
||||
|
||||
return fallback
|
||||
|
||||
|
||||
def resolve_mutation_workspace(
|
||||
@@ -107,29 +131,6 @@ def _realpath_git_common_dir(workspace_path: str, common_dir: str) -> str:
|
||||
return os.path.realpath(os.path.join(workspace_path, raw))
|
||||
|
||||
|
||||
def resolve_canonical_repo_root(workspace_path: str, fallback_project_root: str) -> str:
|
||||
"""Return the stable repository root for *workspace_path* via git metadata (#460)."""
|
||||
path = (workspace_path or "").strip()
|
||||
fallback = os.path.realpath(fallback_project_root)
|
||||
if not path:
|
||||
return fallback
|
||||
try:
|
||||
res = subprocess.run(
|
||||
["git", "-C", path, "rev-parse", "--git-common-dir"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
common = _realpath_git_common_dir(path, res.stdout)
|
||||
except Exception:
|
||||
return fallback
|
||||
if common.endswith(f"{os.sep}.git"):
|
||||
return os.path.dirname(common)
|
||||
if os.path.basename(common) == ".git":
|
||||
return os.path.dirname(common)
|
||||
return fallback
|
||||
|
||||
|
||||
def resolve_author_mutation_context(
|
||||
worktree_path: str | None,
|
||||
process_project_root: str,
|
||||
|
||||
Reference in New Issue
Block a user