Geschichte deliberately exposes small namespaces rather than one generated API.
| Namespace | Responsibility |
|---|---|
geschichte.repo | repository lifecycle, worktree/index, commits, refs, merge and history |
geschichte.fs | directory-aware byte filesystem over the current worktree |
geschichte.workspace | structurally shared Datahike workspaces and publication |
geschichte.query | portable read views over Datahike database values |
geschichte.git.local | native .git discovery and object/ref import |
geschichte.git.http | injectable smart-HTTP clone/fetch/push/pull |
geschichte.git.transport | JVM HTTP/SSH transport selection |
The JVM host supplies and owns a fresh initialized Datahike repository. The Git
transport writes files and exact Git objects directly into Geschichte; neither a
.git directory nor a native Git process is needed for HTTP import.
(require '[geschichte.repo :as repo]
'[geschichte.git.transport :as transport]
'[geschichte.git.client :as client])
;; `conn` is an exclusively owned, initialized, empty Geschichte repository.
(def url "https://github.com/octocat/Hello-World.git")
(def imported
(transport/clone! {:conn conn :remote "origin" :url url}))
(keys (repo/worktree conn)) ; => ("README")
(String. ^bytes (repo/read conn "README") "UTF-8")
(repo/configuration conn) ; saved origin and branch upstream
;; Fetch changes without publishing them into the current worktree.
(def fetched
(transport/fetch! {:conn conn :remote "origin" :url url
:options {:haves [(:git-oid imported)]}}))
;; Apply separately, after the host has checked its permissions and policy.
(client/apply-pull! conn "origin" fetched {:policy :ff-only})
:haves is an explicit protocol-v2 hint supported by both HTTP and SSH fetch.
Each supplied OID must name a commit whose complete reachable object graph
is still available in the selected object store. A successful full clone's tips
are suitable while retained. A remote-tracking ref alone, or a materialized
logical commit, is not proof of that availability. History materialization can
be bounded while the exact imported Git objects remain complete. Omitting
:haves preserves the full-fetch behavior; providing one branch's tip may still
transfer objects for other branches. Automatic negotiation is not implemented.
Callers own the connection/object-store lifetime and coordinate garbage
collection during these operations.
Fetch imports objects and updates remote-tracking refs; it preserves the local
worktree and index. Applying a pull requires a clean worktree/index and defaults
to fast-forward only. Divergence is refused rather than overwriting local work;
the lower-level API also supports explicit merge preparation. :no-checkout?
clones retain the remote configuration without selecting a branch upstream.
Clone failures can leave an unpublished partial repository; its host owns
cleanup, publication and retries. A clone is not a permission grant or an
instruction to load imported code.
transport/clone! chooses the ordinary JVM HTTP/SSH adapter and saves repository
configuration. For custom authentication or network policy, inject a host-owned
request function into geschichte.git.http/clone! / fetch! instead. These
lower-level transport functions do not configure the origin for the caller.
Keep credentials out of repository URLs/configuration. Embedded sandboxes must
not receive the default host transport implicitly. GitHub shorthand, connection
permissions, recurring synchronization, webhook handling and UI belong to the
embedding application.
(require '[geschichte.fs :as fs])
(fs/mkdir! conn "/src")
(fs/write! conn "/src/demo.clj" (.getBytes "(ns demo)\n" "UTF-8"))
(fs/stat conn "/src/demo.clj")
(fs/list-dir conn "/src")
(fs/rename! conn "/src/demo.clj" "/src/core.clj")
(fs/delete! conn "/src/core.clj")
Directory entities are worktree state. Git/Geschichte commits contain files; empty directories are not committed.
geschichte.content/transact-stream! ingests a borrowed, finite binary
InputStream using content-defined chunks and bounded heap. Supply its exact
nonnegative byte size and a callback returning the metadata transaction data:
(require '[geschichte.content :as content])
(with-open [source (clojure.java.io/input-stream finalized-file)]
(content/transact-stream! conn source expected-size
(fn [id] [{:attachment/id attachment-id
:attachment/content [:geschichte.content/id id]}])
{:expected-content inspected-content-id}))
The optional expected content UUID, complete hash, and actual byte count must agree before the callback runs or metadata is published, even when the content already exists. A source longer than declared consumes at most one extra byte before refusal. The API does not close the caller's source. The caller retains the source's exclusive finalized-file ownership and the database/GC lifetime through the synchronous call. This does not provide an authority gate or a worktree compare-and-swap: include the appropriate guard in the callback's transaction data. Failure can leave unreferenced payloads for ordinary GC. Existing file/byte ingestion APIs retain their representation-selection rules.
The query namespace returns stable maps for common UI/application needs, while ordinary Datahike queries can combine repository facts with application data:
(require '[datahike.api :as d]
'[geschichte.query :as gq])
(gq/repository @conn)
(gq/refs @conn)
(gq/commits @conn)
(gq/worktree @conn)
(d/q '[:find ?path ?size
:where
[?entry :geschichte.work/path ?path]
[?entry :geschichte.work/size ?size]]
@conn)
Payload bytes are intentionally store refs, not indexed inline values. Query
metadata first and load bytes through repo/read, repo/read-entry, or Konserve
blob access only when required.
prepare-commit captures one immutable repository DB after staging. It returns
a short-lived plan for an ordinary commit or a validated no-op; it does not
transact. Amend and pending merges are refused.
Call prepared-commit-tx inside a Datahike transaction function and append
application receipt data to its returned vector. Commit, logical ref, and receipt
then publish together. For idempotent recovery, look up the operation receipt
first: a duplicate must return the winning receipt without revalidating an old
plan. Authorization still belongs to the host application.
The plan binds its store identity and physical workspace branch, not only the logical Git ref: a freshly forked workspace can share the same checkpoint. The first API deliberately requires the exact physical Datahike checkpoint and transaction number to remain current. The latter also distinguishes provisional transactions within a writer batch that still share checkpoint metadata. Any intervening transaction invalidates the plan, including unrelated metadata changes. Finish schema, file writes, staging, and application metadata before preparing. Existing unstaged files are preserved. A no-op returns no commit/ref datoms, but still validates the same basis and can carry a receipt. Plans are not durable queued work or history-retention pins; do not persist one and assume its historical content survives future garbage collection.
JVM calls return direct values. Effectful CLJS calls return partial-CPS awaitable values where Datahike/Konserve are asynchronous; pure query, diff, merge-planning, Git object, and protocol operations remain synchronous.
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |