78 """Return a compact working-tree summary, or ``"(not a git repo)"`` on any error.
80 Format: ``"<N> modified, <M> untracked, <K> staged"`` (+ ``", <P> ahead/<Q>
81 behind origin"`` when the branch tracks a remote), or ``"clean"`` when there
82 are no changes. Computed fresh every call — never cached by ``HEAD`` (the
83 dirty summary changes while ``HEAD`` does not). Never raises.
85 func =
"git_status_summary"
87 proc = subprocess.run(
88 [
"git",
"status",
"--porcelain=v1",
"-b"],
89 capture_output=
True, text=
True, timeout=_GIT_TIMEOUT_S, check=
False,
91 except (OSError, subprocess.SubprocessError)
as exc:
92 _dbg(
"OC_CHAT.MAIN", func, f
"git status failed/timeout: {type(exc).__name__}", 3)
94 if proc.returncode != 0:
96 modified = untracked = staged = 0
98 for line
in proc.stdout.splitlines():
99 if line.startswith(
"## "):
100 if "[" in line
and "]" in line:
101 tail = line[line.index(
"[") + 1: line.index(
"]")]
102 for part
in tail.split(
","):
104 if part.startswith(
"ahead "):
105 ahead = int(part[6:]
or 0)
106 elif part.startswith(
"behind "):
107 behind = int(part[7:]
or 0)
111 x, y = (line[0]
if line
else " "), (line[1]
if len(line) > 1
else " ")
115 if x
not in (
" ",
"?"):
119 if not (modified
or untracked
or staged
or ahead
or behind):
121 summary = f
"{modified} modified, {untracked} untracked, {staged} staged"
123 summary += f
", {ahead} ahead/{behind} behind origin"