Trees, history & diff
Tree primitives
Section titled “Tree primitives”upsertTreeupsertTree(repo: Repo, treeOid: string | undefined, entries: Map<string, string>): Promise<string>| Parameter | Type | Description |
|---|---|---|
treeOid | string | undefined | The existing root tree, or undefined to start empty. |
entries | Map<string, string> | relativePath → blobOid. |
Returns: Promise<string>
Builds/updates a tree by overlaying blobs onto an existing one, returning the new root tree oid. Handles nested paths — intermediate subtrees are created or updated as needed. Sibling subdirectories are built in parallel.
deleteFromTreedeleteFromTree(repo: Repo, treeOid: string, filePath: string): Promise<string>Returns: Promise<string>
Removes one path from a tree, returning the new root tree oid.
findTreeEntryfindTreeEntry(repo: Repo, rootTreeOid: string, treePath: string): Promise<TreeEntry | null>Returns: Promise<TreeEntry | null>
Resolves a path inside a tree to its entry ({ path, mode, type, oid }),
or null if it doesn’t exist. An empty treePath returns the root tree
itself.
listTreeEntrieslistTreeEntries(repo: Repo, treeOid: string, prefix?: string): Promise<TreeEntry[]>Returns: Promise<TreeEntry[]>
A tree’s direct children, with path prefixed by prefix if given —
used to build result entries whose keys are already the full path a
caller expects.
getTreeFromRefgetTreeFromRef(repo: Repo, options?: { ref?, treePath? }, hooks?: OpsHooks): Promise<TreeEntry[]>| Parameter | Type | Description |
|---|---|---|
options.ref? | string | Defaults to "main". |
options.treePath? | string | Defaults to the repo root. |
Returns: Promise<TreeEntry[]>
A directory listing at a ref’s tip — resolves the ref to a commit, then
treePath inside that commit’s tree. Results are memoized per resolved
head sha, same pattern as getCommitLog below.
History: getCommitLog
Section titled “History: getCommitLog”getCommitLoggetCommitLog(repo: Repo, options?: CommitLogOptions, hooks?: OpsHooks): Promise<CommitInfo[]>| Parameter | Type | Description |
|---|---|---|
options.ref? | string | Defaults to "main". |
options.depth? | number | Defaults to 50. |
options.knownHeadSha? | string | Pass this when the caller already resolved ref — skips a redundant resolveRef. |
Returns: Promise<CommitInfo[]>
The commit chain from a ref, newest first. ref not resolving (empty
repo, unborn branch) returns []; a commit the walk needs but can’t read
after ref already resolved throws instead — see
empty repo vs. missing data.
getCommitHistory: pagination on top of the log cache
Section titled “getCommitHistory: pagination on top of the log cache”getCommitHistorygetCommitHistory(repo: Repo, options: { ref, limit?, skip? }, hooks?: OpsHooks): Promise<CommitInfo[]>Returns: Promise<CommitInfo[]>
A page of commit history (limit/skip), built directly on top of
getCommitLog’s own cache for the underlying chain — a paginated commit
list view doesn’t re-walk anything getCommitLog already walked for a
different page size.
File history & last-commits-per-directory
Section titled “File history & last-commits-per-directory”getFileHistorygetFileHistory(repo: Repo, options: { ref, filePath, limit?, maxDepth? }, hooks?: OpsHooks): Promise<FileHistoryResult>Returns: Promise<FileHistoryResult>
All commits (newest first) that changed one file’s blob oid, walking the
first-parent chain. { entries, truncated } — truncated: true means
the walk hit its depth budget (or the requested limit) before
exhausting the branch’s full commit chain; there may be older commits
touching this file a deeper walk would surface.
getLastCommitsForTreegetLastCommitsForTree(repo: Repo, options: { ref, treePath?, depth? }, hooks?: OpsHooks): Promise<Record<string, LastCommitInfo>>Returns: Promise<Record<string, LastCommitInfo>>
For each direct child of treePath, the most recent commit that changed
it — the tree-view “last commit” column GitHub-style UIs show next to
every file and folder.
Both walk history in fixed-size windows, prefetching each window’s tree reads in parallel before processing that window sequentially — the walk itself must advance commit-by-commit for correctness (each step needs to know what’s still unresolved from the step before), but the tree-object reads backing it don’t depend on each other, since every commit’s tree oid is already known upfront from the commit log. Preserve this two-phase structure if you ever need to touch this algorithm — collapsing it back to one-commit-at-a-time turns a batched-round-trip walk back into a round-trip-per-commit one, which is the single largest contributor to slow directory listings on large repos.
getCommitDiffgetCommitDiff(repo: Repo, commitSha: string): Promise<DiffResult>Returns: Promise<DiffResult>
The diff a single commit introduced, against its first parent. For a root
commit (no parent), every file in the tree is reported as added — the
whole tree is walked recursively, not just its top level.
getDiffBetweenRefsgetDiffBetweenRefs(repo: Repo, baseRef: string, compareRef: string): Promise<DiffResult>Returns: Promise<DiffResult>
The diff between two refs (branch names or commit shas — both are
accepted). DiffResult is { files: DiffFile[], totalAdditions, totalDeletions, totalFiles }; each DiffFile carries a git-style
unified patch (diff --git a/... b/... header, no leaking diff
package internals like an Index:/=== block) plus binary detection
(isBinary, base64 oldContent/newContent for binary files instead of
a text patch).