Skip to content

Trees, history & diff

functionupsertTree
upsertTree(repo: Repo, treeOid: string | undefined, entries: Map<string, string>): Promise<string>
ParameterTypeDescription
treeOidstring | undefinedThe existing root tree, or undefined to start empty.
entriesMap<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.

deleteFromTree(repo: Repo, treeOid: string, filePath: string): Promise<string>

Returns: Promise<string>

Removes one path from a tree, returning the new root tree oid.

findTreeEntry(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.

listTreeEntries(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.

getTreeFromRef(repo: Repo, options?: { ref?, treePath? }, hooks?: OpsHooks): Promise<TreeEntry[]>
ParameterTypeDescription
options.ref?stringDefaults to "main".
options.treePath?stringDefaults 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.

functiongetCommitLog
getCommitLog(repo: Repo, options?: CommitLogOptions, hooks?: OpsHooks): Promise<CommitInfo[]>
ParameterTypeDescription
options.ref?stringDefaults to "main".
options.depth?numberDefaults to 50.
options.knownHeadSha?stringPass 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”
getCommitHistory(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.

getFileHistory(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.

getLastCommitsForTree(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.

getCommitDiff(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.

getDiffBetweenRefs(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).