- Smalltalk 100%
| images | ||
| src | ||
| .gitignore | ||
| .project | ||
| .properties | ||
| .smalltalk.ston | ||
| LICENSE | ||
| README.md | ||
GitRiver
GitRiver reads a Git history through the Pharo libgit2 bindings, assigns
commits and edges to stable lanes, and renders the result as a Unicode river.
It targets Pharo 14 and does not invoke the git executable.
The core deliberately has no GTK or Pulsar dependency. It provides both an eager pipeline for text rendering and a lazy, paginated model that a Spec presenter can consume directly.
Loading from a local checkout
Metacello new
baseline: 'GitRiver';
repository: 'tonel:///absolute/path/to/pharo-git-river/src';
load: 'development'.
The baseline loads the Pharo14 branch of
pharo-vcs/libgit2-pharo-bindings.
The native libgit2 library must also be available to Pharo, as required by
those bindings.
Usage
Render the history reachable from HEAD, with roots at the top:
GitRiver render: '/path/to/repository'.
Include every local branch, remote branch and tag:
GitRiver renderAll: '/path/to/repository'.
Start at any Git commit-ish. Branches, tags, commit hashes and revparse expressions are accepted:
GitRiver render: '/path/to/repository' startingAt: 'feature/login'.
GitRiver render: '/path/to/repository' startingAt: 'refs/remotes/origin/main'.
GitRiver render: '/path/to/repository' startingAt: '4f9a6e2'.
GitRiver render: '/path/to/repository' startingAt: 'HEAD~20'.
An explicit starting revision is the only traversal root. All branch and tag references are still collected and shown as decorations on reachable commits.
Use the individual stages directly:
history := (GitRiverHistoryReader on: '/path/to/repository')
includeAllReferences;
read.
layout := GitRiverLaneLayout new layout: history.
renderer := GitRiverTextRenderer new
tipsFirst;
hashLength: 10;
messageLength: 60;
yourself.
output := renderer render: layout.
Build a lazy model for a SpListPresenter or SpTablePresenter:
model := GitRiver
historyListModelOn: '/path/to/repository'
includeAllReferences: true
pageSize: 500.
list model: model.
For a branch or commit selected in Pulsar, pass its Iceberg commit id. This is more reliable than reconstructing a local or remote reference name:
revision := lastBranchSelected branch commit id.
model := GitRiver
historyListModelOn: self model location
startingAt: revision
pageSize: 500.
listPresenter model: model.
The first page is materialized immediately. Accessing rows near its end prefetches another page and announces the size change to Spec. Close the model when its presenter is no longer needed so a partially consumed native revwalk is released immediately:
model close.
The lazy stages can also be composed explicitly:
commits := (GitRiverHistoryReader on: '/path/to/repository') commitGenerator.
rows := GitRiverLaneLayout new rowGeneratorFrom: commits.
model := GitRiverHistoryListModel on: rows pageSize: 500.
GitRiverHistoryReader converts all native LGit* objects into ordinary
Pharo snapshots before yielding them. Commits, the revwalk and the repository
are released as the generator advances, finishes or is closed.
GitRiverLaneLayout therefore has no FFI dependency and can be tested or
reused independently.
Packages
GitRiver-Core: snapshots,libgit2reader, lane layout and renderer.GitRiver-Spec: a lightweight presenter for displaying one layout row as a graph column cell.GitRiver-Tests: synthetic graph tests; no repository orgitprocess is required.
Spec graph column
Use GitRiverLayoutRowPresenter as the cell presenter of the graph column in
an easy column view:
listPresenter addColumn: (SpEasyColumnViewColumn new
title: '';
width: 100;
cellPresenterClass: GitRiverLayoutRowPresenter;
beNotExpandable;
yourself).
Give every logical branch a stable color by configuring each graph cell with the same palette. Colors wrap around when the graph contains more simultaneous branches than entries in the palette:
palette := {
Color red.
Color blue.
Color green.
Color orange }.
graphColumn := SpEasyColumnViewColumn new
title: '';
width: 100;
cellPresenterClass: GitRiverLayoutRowPresenter;
whenCellPresenterInstantiatedDo: [ :presenter |
presenter branchPalette: palette ];
beNotExpandable;
yourself.
listPresenter addColumn: graphColumn.
The layout stores only stable integer branch identities. Color objects stay
in the Spec presenter, so the same rows can be rendered with another palette
without recomputing repository history or lane layout.
Each list item must be a GitRiverLayoutRow. The presenter renders only that
row's Unicode graph fragment; other columns can read commit data through
layoutRow commit.
Scope
Implemented:
- topological/date-ordered traversal;
HEAD-only and all-reference histories;- local branches, remote branches, tags and detached
HEADlabels; - linear histories, multiple tips, forks, joins and octopus merges;
- roots-first and tips-first Unicode rendering;
- configurable hash and message lengths;
- incremental revwalk, lane layout and paginated Spec list model.
Deferred to the Pulsar/GTK stage:
- graphical drawing and interaction;
- background loading;
- worktree status badges;
- custom themes and colored terminal output.
Design note
The lane allocator is an independent implementation based on Git's commit
graph semantics. It does not translate or reuse the GPL-licensed layout code
from git-rivera.