Liking cljdoc? Tell your friends :D

com.blockether.vis.ext.channel-tui.magit

Magit-style PORCELAIN layer for the TUI — the pure, testable half of the C-x g status buffer. Everything runs over the native git CLI via internal.git/run-git; nothing here touches a terminal.

Three surfaces:

  • status-model — one snapshot of the repo: head/upstream facts plus the magit sections (untracked / unstaged / staged / unmerged / stashes / unpushed / unpulled / recent commits).
  • actions — stage-file!, unstage-file!, discard-file!, commit!, push!, pull!, fetch!, branch and stash verbs. Each returns {:ok? bool :msg str} so the dialog can echo success/failure verbatim.
  • status-rows — PURE projection of a model (+ the expanded-diff set) into renderable row maps; the dialog only paints and moves a cursor over what this returns.

Keeping the model/actions/rows split pure means the whole magit feature is exercisable in tests against a throw-away repo, with zero lanterna.

Magit-style PORCELAIN layer for the TUI — the pure, testable half of the
C-x g status buffer. Everything runs over the native `git` CLI via
`internal.git/run-git`; nothing here touches a terminal.

Three surfaces:

- `status-model`   — one snapshot of the repo: head/upstream facts plus the
                     magit sections (untracked / unstaged / staged /
                     unmerged / stashes / unpushed / unpulled / recent
                     commits).
- actions          — `stage-file!`, `unstage-file!`, `discard-file!`,
                     `commit!`, `push!`, `pull!`, `fetch!`, branch and
                     stash verbs. Each returns `{:ok? bool :msg str}` so
                     the dialog can echo success/failure verbatim.
- `status-rows`    — PURE projection of a model (+ the expanded-diff set)
                     into renderable row maps; the dialog only paints and
                     moves a cursor over what this returns.

Keeping the model/actions/rows split pure means the whole magit feature is
exercisable in tests against a throw-away repo, with zero lanterna.
raw docstring

checkout-branch!clj

(checkout-branch! root branch)
source

commit!clj

(commit! root message {:keys [amend?]})

Refuses an empty message and — like magit's Nothing staged guard — a non-amend commit over a clean index (a bare git commit failure would echo a whole status dump). The index guard only applies when HEAD resolves: diff --cached --quiet reports clean on an unborn branch even with staged files.

Refuses an empty message and — like magit's `Nothing staged` guard — a
non-amend commit over a clean index (a bare `git commit` failure would echo
a whole status dump). The index guard only applies when HEAD resolves:
`diff --cached --quiet` reports clean on an unborn branch even with staged
files.
sourceraw docstring

commit-diff-linesclj

(commit-diff-lines root {:keys [sha]})

Diff body for one commit row, as plain lines (for the TAB fold): the patch git show produces for sha, kept from the first diff --git header down so every file the commit touched is named.

Diff body for one commit row, as plain lines (for the TAB fold): the patch
`git show` produces for `sha`, kept from the first `diff --git` header down so
every file the commit touched is named.
sourceraw docstring

create-branch!clj

(create-branch! root name)

Create AND check out name (magit's b c).

Create AND check out `name` (magit's `b c`).
sourceraw docstring

current-branchclj

(current-branch root)

Short name of the current branch (main), or nil on a detached/unborn HEAD.

Short name of the current branch (`main`), or nil on a detached/unborn HEAD.
sourceraw docstring

delete-branch!clj

(delete-branch! root name {:keys [force?]})
source

discard-file!clj

(discard-file! root {:keys [path area]})

Magit's k: throw the change away.

  • untracked file → delete it (git clean -f)
  • UNSTAGED change → restore the INDEX version in the worktree only (git checkout -- path) — the staged half of the same file survives, exactly like magit
  • staged change in HEAD → restore the HEAD version in index AND worktree
  • added, not in HEAD → unstage only (the file survives as untracked — never silently delete content git has never stored).
Magit's `k`: throw the change away.
- untracked file        → delete it (`git clean -f`)
- UNSTAGED change       → restore the INDEX version in the worktree only
                          (`git checkout -- path`) — the staged half of the
                          same file survives, exactly like magit
- staged change in HEAD → restore the HEAD version in index AND worktree
- added, not in HEAD    → unstage only (the file survives as untracked —
  never silently delete content git has never stored).
sourceraw docstring

fetch!clj

(fetch! root)
source

file-diff-linesclj

(file-diff-lines root {:keys [path area]})

Diff body for one file row, as plain lines (for the TAB fold). area picks the side: :staged → diff --cached, :unstaged/:unmerged → diff, :untracked → the file's own content rendered as additions.

Diff body for one file row, as plain lines (for the TAB fold).
`area` picks the side: :staged → `diff --cached`, :unstaged/:unmerged →
`diff`, :untracked → the file's own content rendered as additions.
sourceraw docstring

first-selectableclj

(first-selectable rows idx)

Index of the first selectable row at-or-after idx (wrapping search both directions handled by the caller); nil when nothing is selectable.

Index of the first selectable row at-or-after `idx` (wrapping search both
directions handled by the caller); nil when nothing is selectable.
sourceraw docstring

gerrit-push!clj

(gerrit-push! root {:keys [remote branch topic dry-run? no-verify?]})

Push HEAD to Gerrit for review (refs/for/<branch>) — a regular push, just carrying an optional Gerrit topic. opts: :remote :branch :topic :dry-run? :no-verify?. remote/branch default to the detected Gerrit remote and upstream branch.

Push HEAD to Gerrit for review (`refs/for/<branch>`) — a regular push, just
carrying an optional Gerrit topic. `opts`: :remote :branch :topic :dry-run?
:no-verify?. `remote`/`branch` default to the detected Gerrit remote and
upstream branch.
sourceraw docstring

gerrit-remoteclj

(gerrit-remote root)

Name of the remote that talks to a Gerrit server, or nil. Prefers an explicit gerrit remote, then any remote whose URL smells like Gerrit, then falls back to the first remote when a .gitreview file is present.

Name of the remote that talks to a Gerrit server, or nil. Prefers an explicit
`gerrit` remote, then any remote whose URL smells like Gerrit, then falls back
to the first remote when a `.gitreview` file is present.
sourceraw docstring

gerrit-target-branchclj

(gerrit-target-branch root)

Branch a Gerrit review targets: the upstream branch (minus its remote), else the current branch, else master.

Branch a Gerrit review targets: the upstream branch (minus its remote), else
the current branch, else `master`.
sourceraw docstring

gerrit?clj

(gerrit? root)

True when this repo appears to target a Gerrit server.

True when this repo appears to target a Gerrit server.
sourceraw docstring

head-rowsclj

(head-rows {:keys [branch detached? head head-subject upstream? upstream ahead
                   behind]})

The Head: / Merge: preamble of the status buffer.

The `Head:` / `Merge:` preamble of the status buffer.
sourceraw docstring

head-subjectclj

(head-subject root)

Subject line of HEAD's commit, or nil on an unborn branch.

Subject line of HEAD's commit, or nil on an unborn branch.
sourceraw docstring

last-commit-messageclj

(last-commit-message root)

Full message of HEAD's commit (for amend pre-fill), or nil.

Full message of HEAD's commit (for amend pre-fill), or nil.
sourceraw docstring

load-reposclj

(load-repos repo-entries)

Attach a fresh :model snapshot to every repo entry — one status-model read per root. The refresh path of a multi-root buffer.

Attach a fresh `:model` snapshot to every repo entry — one `status-model`
read per root. The refresh path of a multi-root buffer.
sourceraw docstring

local-branchesclj

(local-branches root)

Local branches as [{:name :current?}], current first.

Local branches as `[{:name :current?}]`, current first.
sourceraw docstring

log-graph-linesclj

(log-graph-lines root)
(log-graph-lines root {:keys [all? max] :or {max 250}})

Pretty git log --graph for the fullscreen log viewer, as ANSI-colored lines (git's own --color=always graph). opts:

  • :all? include every ref, not just HEAD's history (default false)
  • :max commit cap (default 250). Returns a vec of lines; a one-line notice when the repo has no commits.
Pretty `git log --graph` for the fullscreen log viewer, as ANSI-colored
lines (git's own `--color=always` graph). `opts`:
- `:all?` include every ref, not just HEAD's history (default false)
- `:max`  commit cap (default 250).
Returns a vec of lines; a one-line notice when the repo has no commits.
sourceraw docstring

multi-status-rowsclj

(multi-status-rows repos expanded diff-fn)

Rows for one OR many repos. repos is [{:root :label :draft? :model}] (:model a status-model, nil outside a git repo). ONE repo renders exactly like status-rows — the single-root buffer looks unchanged — while several repos each get a :repo header row. EVERY row is tagged with its :root so the dialog's verbs route to the right repo.

expanded is a set of [root area path] triples; diff-fn receives the root-tagged file row.

Rows for one OR many repos. `repos` is `[{:root :label :draft? :model}]`
(`:model` a `status-model`, nil outside a git repo). ONE repo renders
exactly like `status-rows` — the single-root buffer looks unchanged —
while several repos each get a `:repo` header row. EVERY row is tagged
with its `:root` so the dialog's verbs route to the right repo.

`expanded` is a set of `[root area path]` triples; `diff-fn` receives the
root-tagged file row.
sourceraw docstring

next-sectionclj

(next-section rows idx dir)

Index of the nearest :section/:repo header from idx moving by dir (+1/-1); idx unchanged when there is none that way. Magit's n/p section-to-section jump.

Index of the nearest `:section`/`:repo` header from `idx` moving by `dir`
(+1/-1); `idx` unchanged when there is none that way. Magit's `n`/`p`
section-to-section jump.
sourceraw docstring

next-selectableclj

(next-selectable rows idx dir)

Index of the nearest selectable row moving from idx by dir (+1/-1); returns idx unchanged when there is none further that way.

Index of the nearest selectable row moving from `idx` by `dir` (+1/-1);
returns `idx` unchanged when there is none further that way.
sourceraw docstring

pull!clj

(pull! root)
source

push!clj

(push! root {:keys [set-upstream? force? remote dry-run? no-verify?]})

opts: :remote (default "origin"), :set-upstream? adds -u <remote> <branch>, :force? uses --force-with-lease (never bare --force), :dry-run? adds --dry-run, :no-verify? adds --no-verify to skip pre-push hooks.

`opts`: :remote (default "origin"), :set-upstream? adds `-u <remote> <branch>`,
:force? uses `--force-with-lease` (never bare --force), :dry-run? adds
`--dry-run`, :no-verify? adds `--no-verify` to skip pre-push hooks.
sourceraw docstring

range-commitsclj

(range-commits root range-spec)

Commits in range-spec (e.g. "@{upstream}..HEAD") as [{:sha :subject}], newest first. Empty when the range is empty or unresolvable.

Commits in `range-spec` (e.g. "@{upstream}..HEAD") as `[{:sha :subject}]`,
newest first. Empty when the range is empty or unresolvable.
sourceraw docstring

recent-commitsclj

(recent-commits root n)

Latest n commits as [{:sha :subject}], newest first.

Latest `n` commits as `[{:sha :subject}]`, newest first.
sourceraw docstring

refs-for-specclj

(refs-for-spec branch topic)

PURE: the Gerrit push refspec HEAD:refs/for/<branch>, with an optional %topic=<topic> appended when topic is non-blank.

PURE: the Gerrit push refspec `HEAD:refs/for/<branch>`, with an optional
`%topic=<topic>` appended when `topic` is non-blank.
sourceraw docstring

remotesclj

(remotes root)

Configured remotes as [{:name :url}] (the PUSH url), in git's own order. Deduplicated so a remote with distinct fetch/push urls shows once.

Configured remotes as `[{:name :url}]` (the PUSH url), in git's own order.
Deduplicated so a remote with distinct fetch/push urls shows once.
sourceraw docstring

repo-rowclj

(repo-row {:keys [label root draft?]})

The repo header row a multi-root buffer shows above each repo's sections.

The repo header row a multi-root buffer shows above each repo's sections.
sourceraw docstring

section-ofclj

(section-of rows section-idx)

The [area path]-bearing rows covered by a :section header row — used for section-wide stage/unstage (s/u on the header). Stops at the next :section OR :repo header and only matches rows of the SAME repo (:root), so a multi-root buffer never bleeds one repo's files into another's section.

The `[area path]`-bearing rows covered by a `:section` header row —
used for section-wide stage/unstage (`s`/`u` on the header). Stops at the
next `:section` OR `:repo` header and only matches rows of the SAME repo
(`:root`), so a multi-root buffer never bleeds one repo's files into
another's section.
sourceraw docstring

section-open?clj

(section-open? expanded area)

Is area's section currently expanded? expanded carries [:section area] toggle keys that FLIP a section from its default — a default-collapsed section (stash list, commit log) opens when its key is present; a default-open working-tree section closes when its key is present.

Is `area`'s section currently expanded? `expanded` carries `[:section area]`
toggle keys that FLIP a section from its default — a default-collapsed
section (stash list, commit log) opens when its key is present; a
default-open working-tree section closes when its key is present.
sourceraw docstring

selectable?clj

(selectable? {:keys [kind stageable?]})

Rows the dialog cursor can land on. A :diff row is landable only when it is :stageable? (a hunk of a staged/unstaged file), so plain diff peeks stay scroll-only.

Rows the dialog cursor can land on. A `:diff` row is landable only when it is
`:stageable?` (a hunk of a staged/unstaged file), so plain diff peeks stay
scroll-only.
sourceraw docstring

split-diff-hunksclj

(split-diff-hunks lines)

PURE: split a unified diff (as lines, WITH its diff --git/index/---/ +++ preamble) into {:header [lines] :hunks [[lines] ...]} — the preamble shared by every hunk, then one line-vector per @@ hunk. A valid one-hunk patch for hunk N is therefore (into header (nth hunks N)), which git apply accepts. Header is everything before the first @@; each hunk runs from its @@ line up to (not including) the next one.

PURE: split a unified diff (as `lines`, WITH its `diff --git`/`index`/`--- `/
`+++ ` preamble) into `{:header [lines] :hunks [[lines] ...]}` — the preamble
shared by every hunk, then one line-vector per `@@` hunk. A valid one-hunk
patch for hunk N is therefore `(into header (nth hunks N))`, which `git apply`
accepts. Header is everything before the first `@@`; each hunk runs from its
`@@` line up to (not including) the next one.
sourceraw docstring

stage-all!clj

(stage-all! root)
source

stage-file!clj

(stage-file! root path)
source

stage-hunk!clj

(stage-hunk! root {:keys [path hunk]})

Magit's s on a diff HUNK: stage just hunk hunk (0-based, in @@ order) of path's UNSTAGED diff — reconstruct that one hunk into a patch and git apply --cached it, leaving the file's other hunks unstaged.

Magit's `s` on a diff HUNK: stage just hunk `hunk` (0-based, in `@@` order) of
`path`'s UNSTAGED diff — reconstruct that one hunk into a patch and
`git apply --cached` it, leaving the file's other hunks unstaged.
sourceraw docstring

stash-apply!clj

(stash-apply! root ref)
source

stash-diff-linesclj

(stash-diff-lines root {:keys [ref]})

Diff body for one stash row, as plain lines (for the TAB fold): the patch git stash show -p produces for ref, from the first diff --git header down so every file the stash touched is named.

Diff body for one stash row, as plain lines (for the TAB fold): the patch
`git stash show -p` produces for `ref`, from the first `diff --git` header
down so every file the stash touched is named.
sourceraw docstring

stash-drop!clj

(stash-drop! root ref)
source

stash-pop!clj

(stash-pop! root ref)
source

stash-push!clj

(stash-push! root message)

Stash the working tree INCLUDING untracked files (the least surprising default for a status-buffer 'stash everything' verb). Git exits 0 with 'No local changes to save' when there is nothing to stash — surface that as a failure so the dialog doesn't claim success.

Stash the working tree INCLUDING untracked files (the least surprising
default for a status-buffer 'stash everything' verb). Git exits 0 with
'No local changes to save' when there is nothing to stash — surface that
as a failure so the dialog doesn't claim success.
sourceraw docstring

stashesclj

(stashes root)

Stash list as [{:ref "stash@{0}" :message}], newest first.

Stash list as `[{:ref "stash@{0}" :message}]`, newest first.
sourceraw docstring

status-modelclj

(status-model root)

One full magit snapshot of the repo at root, or nil outside a repo.

{:branch :detached? :head :upstream? :upstream :ahead :behind :head-subject :untracked [path …] :unstaged [{:path :code} …] ;; worktree side (porcelain Y) :staged [{:path :code} …] ;; index side (porcelain X) :unmerged [{:path :code} …] :stashes [{:ref :message} …] :unpushed [{:sha :subject} …] ;; @{upstream}..HEAD — magit's Unmerged into :unpulled [{:sha :subject} …] ;; HEAD..@{upstream} — magit's Unpulled from :commits [{:sha :subject} …]}

One full magit snapshot of the repo at `root`, or nil outside a repo.

{:branch :detached? :head :upstream? :upstream :ahead :behind
 :head-subject
 :untracked [path …]
 :unstaged  [{:path :code} …]     ;; worktree side (porcelain Y)
 :staged    [{:path :code} …]     ;; index side   (porcelain X)
 :unmerged  [{:path :code} …]
 :stashes   [{:ref :message} …]
 :unpushed  [{:sha :subject} …]   ;; @{upstream}..HEAD — magit's `Unmerged into`
 :unpulled  [{:sha :subject} …]   ;; HEAD..@{upstream} — magit's `Unpulled from`
 :commits   [{:sha :subject} …]}
sourceraw docstring

status-rowsclj

(status-rows model expanded)
(status-rows {:keys [untracked unstaged staged unmerged stashes commits upstream
                     unpushed unpulled]
              :as model}
             expanded
             diff-fn)

PURE projection: model (+ expanded set of [area path], + optional diff-fn row→lines) → renderable rows. Every row is {:kind :info|:section|:file|:diff|:stash|:commit|:blank :text …}. Section order mirrors magit: unpushed commits render as Unmerged into <upstream> and Recent commits appears ONLY when nothing is unpushed (magit's unpushed-to-upstream-or-recent); Unpulled from <upstream> closes the buffer when the branch is behind.

PURE projection: model (+ `expanded` set of `[area path]`, + optional
`diff-fn` row→lines) → renderable rows. Every row is
`{:kind :info|:section|:file|:diff|:stash|:commit|:blank :text …}`.
Section order mirrors magit: unpushed commits render as
`Unmerged into <upstream>` and `Recent commits` appears ONLY when nothing
is unpushed (magit's `unpushed-to-upstream-or-recent`); `Unpulled from
<upstream>` closes the buffer when the branch is behind.
sourceraw docstring

unstage-all!clj

(unstage-all! root)
source

unstage-file!clj

(unstage-file! root path)

Magit's u: git reset -q -- path. Unlike restore --staged this also works on an unborn HEAD (before the first commit), exactly like magit.

Magit's `u`: `git reset -q -- path`. Unlike `restore --staged` this also
works on an unborn HEAD (before the first commit), exactly like magit.
sourceraw docstring

unstage-hunk!clj

(unstage-hunk! root {:keys [path hunk]})

Magit's u on a staged diff HUNK: unstage just hunk hunk (0-based) of path's STAGED diff — reverse-apply that one hunk to the index.

Magit's `u` on a staged diff HUNK: unstage just hunk `hunk` (0-based) of
`path`'s STAGED diff — reverse-apply that one hunk to the index.
sourceraw docstring

upstream-nameclj

(upstream-name root)

Short name of the current branch's upstream (origin/main), or nil.

Short name of the current branch's upstream (`origin/main`), or nil.
sourceraw docstring

visit-file-linesclj

(visit-file-lines root path)

Working-tree content of path (relative to root) as plain lines for the fullscreen RET-visit viewer, or nil when it isn't a readable regular file (a deleted/renamed entry has no working-tree body — the caller falls back to the diff).

Working-tree content of `path` (relative to `root`) as plain lines for the
fullscreen `RET`-visit viewer, or nil when it isn't a readable regular file
(a deleted/renamed entry has no working-tree body — the caller falls back to
the diff).
sourceraw docstring

workspace-rootsclj

(workspace-roots ws fallback-root)

Ordered repo entries the magit buffer shows for one SESSION: the primary workspace root first, then every extra filesystem root (/fs, the dir picker). Accepts the gateway session-workspace-info map in EITHER key shape (in-process kebab or canonical snake wire); ws nil → one entry for fallback-root.

DRAFT semantics: each entry's :root is the path the session actually EDITS — for a draft that's the CLONE (primary :root, extras' :clone), never the trunk — with :trunk carrying the real dir it was forked from and :draft? set. Deduped by :root, order preserved.

Entry: {:root abs-path :trunk abs-path :label basename :draft? bool}.

Ordered repo entries the magit buffer shows for one SESSION: the primary
workspace root first, then every extra filesystem root (`/fs`, the dir
picker). Accepts the gateway `session-workspace-info` map in EITHER key
shape (in-process kebab or canonical snake wire); `ws` nil → one entry for
`fallback-root`.

DRAFT semantics: each entry's `:root` is the path the session actually
EDITS — for a draft that's the CLONE (primary `:root`, extras' `:clone`),
never the trunk — with `:trunk` carrying the real dir it was forked from
and `:draft?` set. Deduped by `:root`, order preserved.

Entry: `{:root abs-path :trunk abs-path :label basename :draft? bool}`.
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close