aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/wflib/config.py
diff options
context:
space:
mode:
Diffstat (limited to 'wflib/config.py')
-rw-r--r--wflib/config.py24
1 files changed, 22 insertions, 2 deletions
diff --git a/wflib/config.py b/wflib/config.py
index 8f75c89..5339313 100644
--- a/wflib/config.py
+++ b/wflib/config.py
@@ -8,10 +8,11 @@ from pathlib import Path
from . import lanes as lanes_mod
NAME = "workflow.toml"
+WF_HOME = ".wf-home"
FORMAT = 1
KEYS = {"format", "tasks", "archive", "docs", "verify", "done", "ledgers", "anchors", "ctx_hint", "worktree_setup", "quick_gate",
"slice_above", "lanes", "areas", "code_root", "area_stale_commits", "area_ignore",
- "cloud", "cloud_include", "cloud_note"}
+ "cloud", "cloud_include", "cloud_note", "push"}
AREA_IGNORE = ("tests", "test", "docs", "doc")
ANCHOR_KEYS = {"index", "index_section", "specs"}
@@ -46,12 +47,18 @@ class Config:
cloud: bool = False # cloud lane opt-in (wf cloud send)
cloud_include: list[str] = field(default_factory=list) # git-ignored paths force-added to the snapshot
cloud_note: str | None = None # appended to the cloud prompt
+ push: list[str] = field(default_factory=list) # wf finish/merge/push: run in root after a merge (else push home)
@property
def areas_file(self) -> Path:
return self.areas or (self.local or self.root) / "CLAUDE.md"
@property
+ def split(self) -> bool:
+ """code_root is another git repo than root: private home repo + code repo (split project)."""
+ return bool(self.code_root) and git_top(self.code_root) not in (None, git_top(self.root))
+
+ @property
def code(self) -> Path:
return self.code_root or self.root
@@ -104,8 +111,15 @@ def linked_worktree(folder: Path) -> tuple[Path, Path, Path] | None:
def find_root(start: Path) -> Path:
"""Folder with workflow.toml at or above start; in a linked git worktree the main tree's
- same folder, when it is a project too (one TASKS.md for all worktrees)."""
+ same folder, when it is a project too (one TASKS.md for all worktrees). A code worktree of a
+ split project: its .wf-home."""
start = start.resolve()
+ top = git_top(start)
+ if top and (top / WF_HOME).is_file():
+ home = Path((top / WF_HOME).read_text().strip())
+ if not (home / NAME).is_file():
+ raise ConfigError(f"{WF_HOME} points to {home}: no {NAME} there (fix or delete {top / WF_HOME})")
+ return home
for folder in (start, *start.parents):
if (folder / NAME).is_file():
wt = linked_worktree(folder)
@@ -117,6 +131,11 @@ def find_root(start: Path) -> Path:
raise ConfigError(f"no {NAME} in {start} or above: not a wf project (wf init makes one)")
+def code_main(cfg: "Config") -> Path | None:
+ """Main tree top of the code repo of a split project, else None."""
+ return git_top(cfg.code_root) if cfg.split else None
+
+
def find_local(start: Path) -> Path | None:
"""In a linked worktree whose project root is the main tree's (find_root): the worktree's own copy
of that folder when it has a workflow.toml, else None."""
@@ -222,4 +241,5 @@ def load(root: Path, local: Path | None = None) -> Config:
local=local,
cloud=data.get("cloud", False), cloud_include=_strings(data, "cloud_include"),
cloud_note=_string(data, "cloud_note"),
+ push=_strings(data, "push"),
)