A commit row pulled from git log for the Recent Commits sidebar block.
Mirrors lazygit’s columnar layout (hash + author + subject) so the
renderer can lay out one commit per visual line. Hashes are parsed
into binary OIDs once, then formatted on display to a fixed length (the
COMMIT_HASH_DISPLAY_LEN constant in src/tui/ui.rs, currently 8
chars, matching lazygit’s Gui.CommitHashLength default). Not
user-configurable today — change the constant to retune.
parents.len() >= 2 flags a merge commit, which the renderer marks
with ◎ instead of ○.
Insertion / deletion line counts of a branch versus its base trunk
(issue #287). Populated from git diff --shortstat <base>...HEAD — the
three-dot merge-base form, so the figures reflect only what the branch
itself contributed (the GitHub-PR view), not divergence that landed on
the trunk after the fork.
One prunable worktree entry as surfaced by gwm prune --dry-run
(issue #31). The reason field is a human-readable rationale that
is currently hard-coded to “working dir missing” — that is the only
case is_prunable(None) flags today (working tree removed out from
under the admin entry). Kept as a String rather than a literal
in the CLI so future libgit2 versions can surface richer reasons
(locked worktrees, broken HEAD, …) without breaking the CLI
rendering contract.
One row of git stash list (issue #34). Surfaced by the sidebar
in stashes mode. Kept deliberately minimal — ref_name so the user
can copy stash@{N} to the status bar, subject so they can tell
which stash is which. Per-file diff numbers (+/-) live in a
follow-up — the v1 contract is just “name + subject”.
Hard cap on the number of NUL-terminated git status -z records read
before the scan is abandoned (issue #300). --untracked-files=all makes
git recurse into unignored generated/vendor directories; streaming the
output and stopping here bounds both git’s directory walk (the child
is killed once the cap is hit) and our own parse / allocation, so a
pathological worktree can’t stall the TUI. Set well above any realistic
change set; the file tree itself renders at most
crate::tui::wt_tree::WT_TREE_MAX_FILES.
Create a new worktree off of HEAD, attaching it either to a freshly
created branch (the default) or — when reuse_branch is true — to a
pre-existing local branch of the same name.
Time elapsed since the oldest commit on branch that’s not also on a
known trunk (main / master / dev). Returns None when no such commit
exists — i.e. the branch is the trunk itself, has no divergence yet,
or branch cannot be resolved. The “oldest commit” rule mirrors the
lazygit branch-age semantics (pkg/utils/date.go::UnixToTimeAgo on the
branch’s founding commit) and is more meaningful for a worktree-manager
than git log -1: it answers “how long has this branch been alive?”
rather than “when did someone last touch it?”.
Render a Duration as a lazygit-style compact relative label
(2d, 3w, 1M, 5y). Mirrors pkg/utils/date.go::formatSecondsAgo
from lazygit: single-character suffix, no plural, capital M to
disambiguate from minutes. Bounded at 4 chars for two-digit values in
each unit, which is enough for any realistic branch age.
Shell out to git diff --stat <base>..<head> inside path. The
output is truncated to max_lines lines so a sprawling diff stat
doesn’t blow up the PR body (issue #84: 30-line cap by convention).
Committed diff size of the worktree’s current branch versus its base
trunk (issue #287), via git diff --shortstat <base>...HEAD. Returns
Ok(None) when the path is not a readable repo, when HEAD is itself a
trunk (no meaningful base to diff against — see is_trunk_branch), or
when no base trunk resolves locally. trunks is the configured
trunk-priority list (config.doctor.trunks) so the figure matches the
base gwm pr would target — resolve_trunk walks it before falling
back to the common defaults.
Shell out to git log --pretty=- %s <base>..<head> inside path
and return raw stdout. Used by gwm pr to fill the {commits}
placeholder in PR templates (issue #84) — each commit becomes a
Markdown bullet so a list of commit subjects drops straight into a
PR body without extra formatting.
Return recent commits for the sidebar using libgit2. This is the uncached
compatibility entry point; the TUI should call recent_commits_cached
so repeated sidebar rebuilds for the same branch tip are a hash lookup.
Stream git status --porcelain -z --untracked-files=all inside path
and return raw stdout, capped at STATUS_SCAN_CAP records. Used by the
TUI sidebar to preview the working-tree state.
Cap-injectable core of git_status_short. Spawns git with a piped
stdout, reads NUL-terminated records until cap is reached (then kills
the child so git stops walking the tree), and returns (bytes, truncated)
— the raw stdout gathered so far plus whether the cap was hit (so the
caller reports a lower bound rather than an exact total). Exposed so
integration tests can exercise truncation with a small cap instead of
creating thousands of files.
True when the worktree at repo carries staged, unstaged, or
untracked changes (ignored files excluded). Shares its
StatusOptions shape with [compute_status] so the status column
and gwm sync’s dirty-tree refusal (issue #24) agree on what
“dirty” means.
True when branch is itself a trunk — present in the configured trunk
list or in the [COMMON_TRUNKS] defaults. Used to suppress the Status
pane’s diff row on trunk worktrees regardless of which trunk
resolve_trunk would pick as the base (issue #287).
Parse a git diff --shortstat summary line into a DiffLineStat
(issue #287). The line looks like
3 files changed, 12 insertions(+), 4 deletions(-), but either the
insertions or the deletions clause can be absent — an all-additions or
all-deletions diff omits the empty side, and an empty diff yields an
empty string. Any clause that’s missing counts as zero; the singular
1 insertion(+) / 1 deletion(-) forms are handled too.
Compute (without mutating) the list of worktree admin entries that
gwm prune would drop. Used by gwm prune --dry-run (issue #31)
and consumed by prune so the dry-run preview and the destructive
pass can never drift on what “prunable” means. Output is sorted by
name for deterministic stdout — scripted callers diff across runs.
Prune stale worktree admin entries (gwq cleanup equivalent).
Consumes prunable_worktrees so what --dry-run shows is exactly
what this destructive pass acts on — the two surfaces share the
scanner, by construction.
Return recent commits for one worktree, memoised by branch-tip OID and
limit. WorktreeInfo.head is populated by list, so normal TUI sidebar
refreshes can hit the cache without reopening the repo. Fixtures and older
callers with head = None fall back to opening the worktree once.
Read-only check that name resolves to a removable worktree —
the libgit2 half of gwm remove --dry-run (issue #31). Errors on
the same “worktree not found” path as remove so the dry-run
surface and the destructive surface share an error contract;
returns Ok(()) when the worktree exists. The caller (the CLI)
is responsible for rendering the plan; this function intentionally
touches no filesystem state and emits no output.
Pick a base ref for gwm pr by walking the configured trunks list
first, then the common defaults (main, master, dev, develop,
trunk) so a repo whose local trunk is master and which hasn’t
customised [doctor] doesn’t fall back to a non-existent "main".
Returns None only if none of the candidates resolve to a local
branch — the caller then uses "main" as a last resort so the
downstream gh pr create --base main produces a clean error message
instead of a panic.
Run git -C <dir> <args>, returning stdout verbatim on success or a
GwmError::CommandFailed carrying the verb and git’s stderr on a
non-zero exit (or the spawn error if git could not be launched).
Like run_git but records the call on the process-global command log so
it surfaces in the Command Logs modal (#290). Used for gwm sync’s
mutating steps (fetch / rebase / merge / --abort), which are
user-triggered operations the user expects to find in the transcript —
unlike the read-only previews that go through run_git.