/** * Git introspection (docs/git.md): wire constants, message builders, * record codecs, and the client-side state mirror. * * The server splits repository data along its grain: mutable-and-small * state (HEAD, refs, in-progress operation, upstream tracking, stash, * status) is pushed as whole snapshots the client applies with * {@link GitStateMirror} — replace the map, acknowledge — while * immutable-and-large content (commits, trees, blobs, patches) is pulled * by oid and cacheable forever. * * All integers little-endian, tightly packed, as everywhere in the protocol. */ import type { SessionId } from "./types.js"; import type { ReactiveStore } from "./reactive.js"; /** Open a repo: [0xA0][nonce:2][flags:2][refs_latency_ms:2][status_latency_ms:2][src_pty_id:2][parent_repo_id:2][n_prefixes:2][(len:2, prefix:N)·N][path_len:2][path:N] */ export declare const C2S_GIT_OPEN = 160; /** Close a repo: [0xA1][repo_id:2] */ export declare const C2S_GIT_CLOSE = 161; /** Acknowledge a state snapshot: [0xA2][repo_id:2][state_id:4] */ export declare const C2S_GIT_ACK = 162; /** Walk commits: [0xA7][nonce:2][repo_id:2][flags:1][limit:2][path_len:2][path:N][n_tips:2][tips][n_hides:2][hides] */ export declare const C2S_GIT_LOG = 167; /** List one tree level: [0xAB][nonce:2][repo_id:2][flags:1][oid:32][path_len:2][path:N][after_len:2][after:N] */ export declare const C2S_GIT_TREE = 171; /** Object bytes, windowed: [0xAC][nonce:2][repo_id:2][flags:1][oid:32][path_len:2][path:N][offset:8][max_len:4] */ export declare const C2S_GIT_BLOB = 172; /** File-level diff: [0xAD][nonce:2][repo_id:2][flags:1][rename:1][old_kind:1][old:32][new_kind:1][new:32][path_len:2][path:N][after_len:2][after:N] */ export declare const C2S_GIT_DIFF = 173; /** Patch rows or text: [0xAE][nonce:2][repo_id:2][flags:2][context:1][rename:1][old_kind:1][old:32][new_kind:1][new:32][path_len:2][path:N][max_len:4][after_len:2][after:N][after_pos:8] */ export declare const C2S_GIT_PATCH = 174; /** Enumerate the index: [0xAF][nonce:2][repo_id:2][flags:1][path_len:2][path:N][after_len:2][after:N] */ export declare const C2S_GIT_INDEX = 175; /** Cancel an in-flight request: [0xA3][nonce:2] */ export declare const C2S_GIT_CANCEL = 163; /** Merge base: [0xB0][nonce:2][repo_id:2][n_oids:1][oids:32·N] */ export declare const C2S_GIT_BASE = 176; /** Resolve a revision spec to commit oids: [0xA6][nonce:2][repo_id:2][spec_len:2][spec:N]. * `spec` is any git revision expression — a ref, (short) oid, `HEAD~3`, or * a range `A..B` / `A...B`. The reply gives `tips`/`hides` for {@link msgGitLog}. */ export declare const C2S_GIT_RESOLVE = 166; /** Subscribe to a live log: [0xA8][log_id:2][repo_id:2][flags:1][limit:2][spec_len:2][spec:N]. * The server resolves `spec` and pushes a `GIT_LOG_PAGE`, re-emitting when * the resolved endpoints move. `log_id` is client-assigned (unique per * connection); `flags` are the `GIT_LOG_*` bits. */ export declare const C2S_GIT_LOG_WATCH = 168; /** End a log subscription: [0xA9][log_id:2][repo_id:2] */ export declare const C2S_GIT_LOG_UNWATCH = 169; /** Acknowledge a log page (coalescing pacing): [0xAA][log_id:2][repo_id:2][update_id:4] */ export declare const C2S_GIT_LOG_ACK = 170; /** Open reply: [0xA0][nonce:2][repo_id:2][status:1][oid_format:1][flags:1][workdir_len:2][workdir][gitdir_len:2][gitdir] */ export declare const S2C_GIT_REPO = 160; /** Whole-state snapshot: [0xA4][repo_id:2][state_id:4][flags:1][records:LZ4] */ export declare const S2C_GIT_STATE = 164; /** Repo terminated: [0xA5][repo_id:2][reason:1] */ export declare const S2C_GIT_CLOSED = 165; /** Log page: [0xA7][nonce:2][status:1][flags:1][n_frontier:2][frontier][records:LZ4] */ export declare const S2C_GIT_COMMITS = 167; /** Tree listing: [0xAB][nonce:2][status:1][flags:1][records:LZ4] */ export declare const S2C_GIT_TREE = 171; /** Blob bytes: [0xAC][nonce:2][status:1][size:8][data:LZ4] */ export declare const S2C_GIT_BLOB = 172; /** Diff entries: [0xAD][nonce:2][status:1][flags:1][records:LZ4] */ export declare const S2C_GIT_DIFF = 173; /** Patch rows/text: [0xAE][nonce:2][status:1][flags:1][data:LZ4] */ export declare const S2C_GIT_PATCH = 174; /** Index entries: [0xAF][nonce:2][status:1][flags:1][records:LZ4] */ export declare const S2C_GIT_INDEX = 175; /** Merge bases: [0xB0][nonce:2][status:1][n_bases:1][bases:32·N] */ export declare const S2C_GIT_BASE = 176; /** Resolve reply: [0xA6][nonce:2][status:1][n_tips:2][tips:32·N][n_hides:2][hides:32·N] */ export declare const S2C_GIT_RESOLVE = 166; /** Live log page: [0xA8][log_id:2][update_id:4][status:1][flags:1][n_frontier:2][frontier:32·N][records:LZ4]. * Same records as `GIT_COMMITS`; re-sent (coalesced, acked) when the * subscription's resolved endpoints move. `flags` bit 0 `MORE` marks a * truncated head page — pull older history with `GIT_LOG` from `frontier`. */ export declare const S2C_GIT_LOG_PAGE = 168; /** Enumerate repositories under a path: [0xB1][nonce:2][flags:1][depth:1][path_len:2][path:N][after_len:2][after:N]. * Allocates no repo ids — an enumeration, not an open. */ export declare const C2S_GIT_DISCOVER = 177; /** Line attribution: [0xB2][nonce:2][repo_id:2][flags:1][oid:32][start_line:4][line_count:4][path_len:2][path:N][after_len:2][after:N] */ export declare const C2S_GIT_BLAME = 178; /** Reflog traversal: [0xB3][nonce:2][repo_id:2][flags:1][limit:2][ref_len:2][ref:N][after_len:2][after:N]. `ref` empty = HEAD. */ export declare const C2S_GIT_REFLOG = 179; /** Fetch from a remote: [0xB4][nonce:2][repo_id:2][flags:1][timeout_ms:4][remote_len:2][remote:N][n_refspecs:2][(len:2, refspec:N)·N] */ export declare const C2S_GIT_FETCH = 180; /** List the repository's worktrees: [0xB5][nonce:2][repo_id:2][flags:1][after_pos:8]. * The main worktree plus every linked one, from wherever in the set the * repo was opened. Refetch when {@link GitStateMirror.worktreeGen} moves. */ export declare const C2S_GIT_WORKTREES = 181; /** Discovery reply: [0xB1][nonce:2][status:1][flags:1][records:LZ4] */ export declare const S2C_GIT_DISCOVER = 177; /** Blame reply: [0xB2][nonce:2][status:1][flags:1][records:LZ4] */ export declare const S2C_GIT_BLAME = 178; /** Reflog reply: [0xB3][nonce:2][status:1][flags:1][records:LZ4] */ export declare const S2C_GIT_REFLOG = 179; /** Fetch reply: [0xB4][nonce:2][status:1][flags:1][records:LZ4] */ export declare const S2C_GIT_FETCH = 180; /** Worktree list reply: [0xB5][nonce:2][status:1][flags:1][records:LZ4] */ export declare const S2C_GIT_WORKTREES = 181; /** `S2C_HELLO` feature bit: server supports the `GIT_*` message family. */ export declare const FEATURE_GIT: number; export declare const GIT_STATUS_OK = 0; export declare const GIT_STATUS_UNKNOWN_ID = 1; export declare const GIT_STATUS_NOT_FOUND = 2; export declare const GIT_STATUS_WRONG_TYPE = 3; export declare const GIT_STATUS_PERMISSION = 4; export declare const GIT_STATUS_TOO_LARGE = 5; export declare const GIT_STATUS_BUDGET = 6; export declare const GIT_STATUS_INVALID = 7; export declare const GIT_STATUS_CANCELLED = 8; export declare const GIT_STATUS_OTHER = 9; /** A precondition failed. Shares docs/design/fs-write.md's code. */ export declare const GIT_STATUS_CONFLICT = 11; /** A MERGE_BASE endpoint over histories with no common ancestor: the * request is well-formed, the repository has no such base. */ export declare const GIT_STATUS_NO_MERGE_BASE = 12; export declare const GIT_OPEN_WATCH: number; export declare const GIT_OPEN_STATUS: number; export declare const GIT_OPEN_UNTRACKED: number; export declare const GIT_OPEN_IGNORED: number; export declare const GIT_OPEN_TRACKING: number; /** One `STATE_REMOTE` record per configured remote; implies `WATCH`. */ export declare const GIT_OPEN_REMOTES: number; /** `repo_id` reported by a failed `GIT_REPO`. */ export declare const GIT_REPO_ID_INVALID = 65535; /** `GIT_OPEN.src_pty_id` / `parent_repo_id`: no such context. */ export declare const GIT_OPEN_NO_CONTEXT = 65535; export declare const GIT_OID_FORMAT_SHA1 = 0; export declare const GIT_OID_FORMAT_SHA256 = 1; export declare const GIT_REPO_BARE: number; export declare const GIT_REPO_SHALLOW: number; export declare const GIT_REPO_SPARSE: number; export declare const GIT_REPO_LINKED: number; /** Reserved for a mutation family; clear in this build. */ export declare const GIT_REPO_WRITABLE: number; /** `GIT_FETCH` will be attempted for this repo: fetch is enabled and a * `git` binary was found. Answered per repository, not per connection. */ export declare const GIT_REPO_FETCHABLE: number; export declare const GIT_CLOSED_CLIENT_REQUEST = 0; export declare const GIT_CLOSED_REPO_GONE = 1; export declare const GIT_CLOSED_PERMISSION_LOST = 2; export declare const GIT_CLOSED_BACKEND_FAILED = 3; export declare const GIT_CLOSED_RESOURCE_LIMIT = 4; /** Client-side pseudo-reason: the connection dropped or was re-established. * Repos do not survive reconnects — re-`openRepo`. */ export declare const GIT_CLOSED_CONNECTION_LOST = -1; export declare const GIT_STATE_REFS_TRUNCATED: number; export declare const GIT_STATE_STATUS_TRUNCATED: number; /** More records for this `state_id` follow. {@link GitStateMirror} * accumulates them and installs the map on the chunk with this clear, so a * consumer never observes a half-built snapshot; only the final chunk is * acknowledged. */ export declare const GIT_STATE_PARTIAL: number; export declare const GIT_LOG_FIRST_PARENT: number; export declare const GIT_LOG_TOPO: number; export declare const GIT_LOG_FULL_MESSAGE: number; export declare const GIT_LOG_FOLLOW: number; export declare const GIT_LOG_PATH_OIDS: number; export declare const GIT_COMMITS_MORE: number; /** Deliver the whole object or answer `TOO_LARGE`. Without it a request is * a window: what fits from `offset`, with `size` still the true object * size, so a viewer can render the head of a file too large to ship. */ export declare const GIT_BLOB_WHOLE: number; export declare const GIT_DIFF_RENAMES: number; export declare const GIT_DIFF_UNTRACKED: number; export declare const GIT_DIFF_IGNORED: number; export declare const GIT_DIFF_IGNORE_SPACE_CHANGE: number; export declare const GIT_DIFF_IGNORE_ALL_SPACE: number; /** Compare on-disk bytes as they are: skip the `text`/`eol` normalization * the worktree side gets from the path's gitattributes. */ export declare const GIT_DIFF_RAW: number; export declare const GIT_PATCH_RENAMES: number; export declare const GIT_PATCH_UNTRACKED: number; export declare const GIT_PATCH_IGNORED: number; export declare const GIT_PATCH_IGNORE_SPACE_CHANGE: number; export declare const GIT_PATCH_IGNORE_ALL_SPACE: number; export declare const GIT_PATCH_RAW: number; export declare const GIT_PATCH_TEXT: number; export declare const GIT_PATCH_CHAR_SPANS: number; export declare const GIT_PATCH_NO_SPANS: number; /** With `TEXT`, emit binary content as git's `GIT binary patch` block * instead of the `Binary files … differ` sentence — git's `--binary`, and * asked for as git asks for it: a 40 MiB PNG is not what a review surface * wants by default, but it is the difference between a patch `git apply` * can replay and one it refuses. */ export declare const GIT_PATCH_BINARY: number; /** The similarity threshold a `rename` byte may carry: 0 is the exact-oid * join, 1-100 a percentage, above that `INVALID`. */ export declare const GIT_RENAME_MAX = 100; export declare const GIT_TREE_TRUNCATED: number; export declare const GIT_DIFF_TRUNCATED: number; export declare const GIT_INDEX_TRUNCATED: number; export declare const GIT_PATCH_STRUCTURED: number; export declare const GIT_PATCH_TRUNCATED: number; /** Similarity rename detection was skipped: the candidate set exceeded the * server's limit, so the response fell back to the exact-oid join. */ export declare const GIT_DIFF_RENAME_LIMIT: number; export declare const GIT_DISCOVER_TRUNCATED: number; export declare const GIT_BLAME_TRUNCATED: number; export declare const GIT_REFLOG_TRUNCATED: number; export declare const GIT_WORKTREES_TRUNCATED: number; /** Descend into a repository once one is found (off by default). */ export declare const GIT_DISCOVER_NESTED: number; export declare const GIT_DISCOVER_BARE: number; export declare const GIT_BLAME_FOLLOW_RENAMES: number; export declare const GIT_BLAME_FOLLOW_COPIES: number; /** Oldest entry first; the default is newest-first, like `git reflog`. */ export declare const GIT_REFLOG_OLDEST_FIRST: number; export declare const GIT_FETCH_PRUNE: number; export declare const GIT_FETCH_NO_TAGS: number; /** Anchor each fetched tip under `refs/blit/fetch//` so a * concurrent `gc` cannot prune it before the client diffs it. */ export declare const GIT_FETCH_ANCHOR: number; export declare const GIT_ENDPOINT_EMPTY = 0; export declare const GIT_ENDPOINT_COMMIT = 1; export declare const GIT_ENDPOINT_TREE = 2; export declare const GIT_ENDPOINT_INDEX = 3; export declare const GIT_ENDPOINT_WORKTREE = 4; /** Old side only: the server substitutes `merge-base(oid, new)`, reading * the new side as HEAD when it is {@link GIT_ENDPOINT_INDEX} or * {@link GIT_ENDPOINT_WORKTREE} — so "everything since the fork, * committed or not" is one request. EMPTY and TREE new sides have no * ancestry to fork from and are refused. */ export declare const GIT_ENDPOINT_MERGE_BASE = 5; export declare const GIT_STATE_RECORD_HEAD = 1; export declare const GIT_STATE_RECORD_REF = 2; export declare const GIT_STATE_RECORD_OP = 3; export declare const GIT_STATE_RECORD_STATUS = 4; export declare const GIT_STATE_RECORD_UPSTREAM = 5; export declare const GIT_STATE_RECORD_STASH = 6; export declare const GIT_STATE_RECORD_REMOTE = 7; /** The worktree set's generation: [kind:1][count:4][digest:8]. */ export declare const GIT_STATE_RECORD_WORKTREE_GEN = 8; /** Reserved family-wide in every records payload: where a budget-truncated * response stopped. `TRUNCATED` with no `CURSOR` means unresumable. */ export declare const GIT_RECORD_CURSOR = 127; /** The remote whose HEAD the checked-out branch tracks. */ export declare const GIT_REMOTE_DEFAULT: number; export declare const GIT_HEAD_DETACHED: number; export declare const GIT_HEAD_UNBORN: number; export declare const GIT_REF_PEELED_VALID: number; export declare const GIT_REF_SYMBOLIC: number; export declare const GIT_OP_MERGE = 1; export declare const GIT_OP_REBASE = 2; export declare const GIT_OP_CHERRY_PICK = 3; export declare const GIT_OP_REVERT = 4; export declare const GIT_OP_BISECT = 5; export declare const GIT_STATUS_ENTRY_CONFLICTED: number; export declare const GIT_UPSTREAM_GONE: number; export declare const GIT_UPSTREAM_COUNTS_VALID: number; export declare const GIT_COMMIT_RECORD_COMMIT = 1; export declare const GIT_COMMIT_RECORD_PATH_AT = 2; export declare const GIT_COMMIT_LOSSY_ENCODING: number; export declare const GIT_TREE_RECORD_ENTRY = 2; export declare const GIT_OTYPE_COMMIT = 1; export declare const GIT_OTYPE_TREE = 2; export declare const GIT_OTYPE_BLOB = 3; export declare const GIT_DIFF_RECORD_ENTRY = 3; export declare const GIT_DIFF_RECORD_BASE = 4; export declare const GIT_DIFF_ENTRY_BINARY: number; export declare const GIT_DIFF_ENTRY_SUBMODULE: number; /** The path's gitattributes name a `filter` driver, so the object bytes * and the worktree bytes are not comparable (an LFS pointer against the * asset it stands for). No rows follow: render "filtered file changed" * rather than a wrong whole-file rewrite. */ export declare const GIT_DIFF_ENTRY_FILTERED: number; export declare const GIT_PATCH_RECORD_FILE = 1; export declare const GIT_PATCH_RECORD_ROW = 2; export declare const GIT_PATCH_RECORD_GAP = 3; export declare const GIT_PATCH_RECORD_BASE = 4; export declare const GIT_PATCH_FILE_BINARY: number; /** Filtered file: no rows follow (see {@link GIT_DIFF_ENTRY_FILTERED}). */ export declare const GIT_PATCH_FILE_FILTERED: number; export declare const GIT_INDEX_RECORD_ENTRY = 4; export declare const GIT_INDEX_INTENT_TO_ADD: number; export declare const GIT_INDEX_SKIP_WORKTREE: number; export declare const GIT_DISCOVER_RECORD_REPO = 1; export declare const GIT_BLAME_RECORD_RANGE = 1; export declare const GIT_REFLOG_RECORD_ENTRY = 1; export declare const GIT_FETCH_RECORD_REF = 1; export declare const GIT_WORKTREES_RECORD_TREE = 1; /** The main worktree — exactly one record carries this, including when the * repo was opened through a linked worktree. */ export declare const GIT_WORKTREE_MAIN: number; /** The worktree this repo handle was opened at. Decided server-side by * identity, so a client need not compare paths it may have canonicalized * differently. */ export declare const GIT_WORKTREE_CURRENT: number; /** `git worktree lock`ed; `lockReason` says why, when a reason was given. */ export declare const GIT_WORKTREE_LOCKED: number; /** The checkout is gone from disk — `git worktree prune` would drop the * entry. Reported rather than hidden: a row that cannot be navigated to is * the thing a client most needs to be told about. */ export declare const GIT_WORKTREE_PRUNABLE: number; /** HEAD is detached, so `branch` is empty. */ export declare const GIT_WORKTREE_DETACHED: number; /** Bare: no checkout at all, so `path` is empty. Only ever the main record. */ export declare const GIT_WORKTREE_BARE: number; export declare const GIT_FOUND_BARE: number; export declare const GIT_FOUND_LINKED: number; export declare const GIT_FOUND_SUBMODULE: number; export declare const GIT_FETCH_REF_FORCED: number; export declare const GIT_FETCH_REF_PRUNED: number; export declare const GIT_FETCH_REF_NEW: number; /** An existing tag was moved (git's `t`, distinct from its `+`). */ export declare const GIT_FETCH_REF_TAG_UPDATE: number; /** Always 32 bytes on the wire, zero-padded past the repo's hash width. */ export type GitOid = Uint8Array; export declare const GIT_OID_NONE: GitOid; export declare function gitOidEqual(a: GitOid, b: GitOid): boolean; export declare function gitOidIsZero(oid: GitOid): boolean; /** Lowercase hex of the oid's meaningful width (40 for SHA-1, 64 for SHA-256). */ export declare function gitOidHex(oid: GitOid, oidFormat?: number): string; /** Parse a hex oid of either width into wire form; null on malformation. */ export declare function gitOidFromHex(hex: string): GitOid | null; export interface GitEndpoint { kind: number; oid: GitOid; } /** A `C2S_GIT_OPEN`. Both context ids are plain fields with a * {@link GIT_OPEN_NO_CONTEXT} sentinel rather than flag-gated tails, so * the message has one shape however it is used. */ export interface GitOpenRequest { nonce: number; /** `GIT_OPEN_*` bits (u16). */ flags: number; /** Per-open settle windows; 0 = the server default. */ refsLatencyMs?: number; statusLatencyMs?: number; /** A pty whose live cwd `path` is joined onto before discovery. */ srcPtyId?: number; /** A parent repo: `path` is then a submodule path relative to its * worktree, and the server resolves the submodule's own gitdir. */ parentRepoId?: number; /** Ref prefixes to watch; empty watches every ref. */ refPrefixes?: string[]; path: string; } export declare function msgGitOpen(req: GitOpenRequest): Uint8Array; export declare function msgGitClose(repoId: number): Uint8Array; export declare function msgGitAck(repoId: number, stateId: number): Uint8Array; export interface GitLogRequest { nonce: number; repoId: number; flags: number; /** 0 = server default; clamped to the server maximum. */ limit: number; /** Subtree filter (escaped wire path); "" = everything. */ path: string; tips: GitOid[]; hides: GitOid[]; } export declare function msgGitLog(req: GitLogRequest): Uint8Array; export interface GitTreeRequest { nonce: number; repoId: number; /** Reserved; a set bit is `INVALID`. */ flags?: number; oid: GitOid; path: string; /** "" = from the beginning; else a `CURSOR` record's path. */ after?: string; } export declare function msgGitTree(req: GitTreeRequest): Uint8Array; export interface GitBlobRequest { nonce: number; repoId: number; /** {@link GIT_BLOB_WHOLE} refuses rather than windowing. */ flags?: number; oid: GitOid; path: string; /** First byte to return. Past the end is `INVALID`; exactly the end is * `OK` with no data. */ offset?: number; /** 0 = the server default cap. */ maxLen: number; } export declare function msgGitBlob(req: GitBlobRequest): Uint8Array; export interface GitDiffRequest { nonce: number; repoId: number; flags: number; /** Rename similarity threshold: 0 = the exact-oid join, 1-100 a * percentage (git's own default is 50), above that `INVALID`. */ rename?: number; old: GitEndpoint; new: GitEndpoint; /** Subtree filter (escaped wire path); "" = everything. */ path: string; /** "" = from the beginning; else a `CURSOR` record's path. */ after?: string; } export declare function msgGitDiff(req: GitDiffRequest): Uint8Array; export interface GitPatchRequest extends GitDiffRequest { /** Context lines; 0 = server default (3). */ context: number; /** Response size cap; 0 = server default. */ maxLen: number; /** Rows already delivered for {@link GitDiffRequest.after}, so a file * larger than the byte budget resumes mid-hunk instead of restarting. */ afterPos?: number; } export declare function msgGitPatch(req: GitPatchRequest): Uint8Array; export interface GitIndexRequest { nonce: number; repoId: number; /** Reserved; a set bit is `INVALID`. */ flags?: number; /** Path prefix; "" = every entry. */ path: string; /** "" = from the beginning; else a `CURSOR` record's path. */ after?: string; } export declare function msgGitIndex(req: GitIndexRequest): Uint8Array; export interface GitDiscoverRequest { nonce: number; /** `GIT_DISCOVER_*` bits. */ flags?: number; /** 0 = the server default, clamped to the server maximum. */ depth?: number; /** Plain UTF-8, like {@link GitOpenRequest.path}. */ path: string; after?: string; } export declare function msgGitDiscover(req: GitDiscoverRequest): Uint8Array; export interface GitBlameRequest { nonce: number; repoId: number; /** `GIT_BLAME_*` bits. */ flags?: number; /** The commit to blame from; the zero oid means HEAD. The worktree is * not blameable. */ oid: GitOid; /** 1-based; 0 is treated as 1. Also how a truncated blame resumes: * re-issue with `startLine` one past the `CURSOR`'s `pos`. */ startLine?: number; /** 0 = to end of file, subject to the server's line budget. */ lineCount?: number; path: string; } export declare function msgGitBlame(req: GitBlameRequest): Uint8Array; export interface GitReflogRequest { nonce: number; repoId: number; /** `GIT_REFLOG_*` bits. */ flags?: number; /** 0 = the server default, clamped to the entry budget. */ limit?: number; /** "" = `HEAD`. */ refName?: string; /** Entries already delivered from the end `OLDEST_FIRST` selects, so a * reflog longer than `limit` pages: re-issue with the `CURSOR`'s * `pos`. */ afterPos?: number; } export declare function msgGitReflog(req: GitReflogRequest): Uint8Array; export interface GitWorktreesRequest { nonce: number; repoId: number; /** No flags are defined; a non-zero value is refused (`INVALID`) rather * than ignored, so a future bit cannot be silently dropped. */ flags?: number; /** Worktrees already delivered, so a set larger than the server's budget * pages: re-issue with the `CURSOR`'s `pos`. */ afterPos?: number; } export declare function msgGitWorktrees(req: GitWorktreesRequest): Uint8Array; export interface GitFetchRequest { nonce: number; repoId: number; /** `GIT_FETCH_*` bits. */ flags?: number; /** 0 = the server default, clamped to the server maximum. */ timeoutMs?: number; /** "" = the branch's configured remote, else `origin`. */ remote?: string; /** Empty = the remote's configured refspecs. */ refspecs?: string[]; } export declare function msgGitFetch(req: GitFetchRequest): Uint8Array; export declare function msgGitCancel(nonce: number): Uint8Array; export declare function msgGitBase(nonce: number, repoId: number, oids: GitOid[]): Uint8Array; export declare function msgGitResolve(nonce: number, repoId: number, spec: string): Uint8Array; export declare function msgGitLogWatch(logId: number, repoId: number, flags: number, limit: number, spec: string): Uint8Array; export declare function msgGitLogUnwatch(logId: number, repoId: number): Uint8Array; export declare function msgGitLogAck(logId: number, repoId: number, updateId: number): Uint8Array; export interface GitRepoInfo { nonce: number; repoId: number; status: number; oidFormat: number; flags: number; /** Escaped canonical worktree root; empty for bare. On failure, a * diagnostic message. */ workdir: string; /** Escaped canonical git directory. */ gitdir: string; } export declare function parseGitRepo(msg: Uint8Array): GitRepoInfo | null; /** Parse `S2C_GIT_STATE` into `[repoId, stateId, flags, records]`. */ export declare function parseGitState(msg: Uint8Array): [number, number, number, Uint8Array] | null; export declare function parseGitClosed(msg: Uint8Array): [number, number] | null; export interface GitCommitsPage { nonce: number; status: number; flags: number; /** Pass as `tips` with the same `hides` to continue the walk. */ frontier: GitOid[]; /** Uncompressed records; decode with {@link gitCommitRecords}. */ records: Uint8Array; } export declare function parseGitCommits(msg: Uint8Array): GitCommitsPage | null; export declare function parseGitTreeResp(msg: Uint8Array): [number, number, number, Uint8Array] | null; export declare function parseGitDiffResp(msg: Uint8Array): [number, number, number, Uint8Array] | null; export declare function parseGitDiscoverResp(msg: Uint8Array): [number, number, number, Uint8Array] | null; export declare function parseGitBlameResp(msg: Uint8Array): [number, number, number, Uint8Array] | null; export declare function parseGitWorktreesResp(msg: Uint8Array): [number, number, number, Uint8Array] | null; export declare function parseGitReflogResp(msg: Uint8Array): [number, number, number, Uint8Array] | null; export declare function parseGitFetchResp(msg: Uint8Array): [number, number, number, Uint8Array] | null; export declare function parseGitPatchResp(msg: Uint8Array): [number, number, number, Uint8Array] | null; export declare function parseGitIndexResp(msg: Uint8Array): [number, number, number, Uint8Array] | null; /** Parse `S2C_GIT_BLOB` into `[nonce, status, size, data]`. `size` is the * true object size even when `TOO_LARGE` leaves `data` empty. */ export declare function parseGitBlobResp(msg: Uint8Array): [number, number, number, Uint8Array] | null; export declare function parseGitBaseResp(msg: Uint8Array): [number, number, GitOid[]] | null; export interface GitResolveResult { nonce: number; status: number; /** Feed as `tips` to {@link msgGitLog} (or a live watch). */ tips: GitOid[]; /** Feed as `hides` to {@link msgGitLog}. */ hides: GitOid[]; } export declare function parseGitResolveResp(msg: Uint8Array): GitResolveResult | null; export interface GitLogPage { logId: number; /** Acknowledge with {@link msgGitLogAck} to receive later updates. */ updateId: number; status: number; /** `GIT_COMMITS_*` flags; bit 0 `MORE` marks a truncated head page. */ flags: number; /** Pass as `tips` with the same `hides` to continue the walk statelessly. */ frontier: GitOid[]; /** Uncompressed records; decode with {@link gitCommitRecords}. */ records: Uint8Array; } export declare function parseGitLogPage(msg: Uint8Array): GitLogPage | null; export declare function msgGitState(repoId: number, stateId: number, flags: number, records: Uint8Array): Uint8Array; export declare function msgGitClosed(repoId: number, reason: number): Uint8Array; export declare function msgGitResolveResp(nonce: number, status: number, tips: GitOid[], hides: GitOid[]): Uint8Array; export declare function msgGitLogPage(logId: number, updateId: number, status: number, flags: number, frontier: GitOid[], records: Uint8Array): Uint8Array; export type GitStateRecord = { kind: "head"; flags: number; oid: GitOid; name: string; } | { kind: "ref"; flags: number; oid: GitOid; peeled: GitOid; name: string; /** The symbolic target's ref name with {@link GIT_REF_SYMBOLIC}, * else "". This is what names the default branch instead of * guessing `main` then `master`. */ target: string; } | { kind: "op"; op: number; oid: GitOid; detail: string; } | { kind: "status"; staged: number; unstaged: number; flags: number; /** The worktree content's hash when the status walk read the file, * else zero. A write that leaves the letters alone still moves * this, so the snapshot is not suppressed as a duplicate. */ oid: GitOid; oldPath: string; path: string; } | { kind: "upstream"; flags: number; ahead: number; behind: number; name: string; upstream: string; } | { kind: "stash"; index: number; oid: GitOid; time: bigint; tz: number; msg: string; } | { kind: "remote"; flags: number; name: string; /** As configured, userinfo included. */ fetchUrl: string; /** "" when it equals {@link fetchUrl}. */ pushUrl: string; } | { /** Names the worktree *set* without describing it; see * {@link GitStateMirror.worktreeGen}. One per snapshot, always. */ kind: "worktreeGen"; count: number; digest: bigint; }; /** Where a budget-truncated response stopped; re-issue the same request * with these as `after`/`afterPos`. Reserved family-wide. */ export type GitCursorRecord = { kind: "cursor"; after: string; pos: bigint; }; export type GitCommitRecord = { kind: "commit"; flags: number; oid: GitOid; tree: GitOid; parents: GitOid[]; authorTime: bigint; authorTz: number; committerTime: bigint; committerTz: number; authorName: string; authorEmail: string; committerName: string; committerEmail: string; message: string; } | { kind: "pathAt"; otype: number; mode: number; oid: GitOid; path: string; }; export type GitTreeRecord = { kind: "entry"; otype: number; mode: number; oid: GitOid; name: string; } | GitCursorRecord; export type GitDiffRecord = { kind: "entry"; /** ASCII porcelain letter (A M D R C T U) as a char code. */ st: number; similarity: number; dflags: number; oldMode: number; newMode: number; oldOid: GitOid; newOid: GitOid; oldPath: string; newPath: string; } | GitCursorRecord | { kind: "base"; oid: GitOid; }; export type GitPatchRecord = { kind: "file"; /** ASCII porcelain letter, the {@link GitDiffRecord} alphabet — a * binary or empty added file emits no rows and still says whether * it was added, deleted or modified. */ st: number; similarity: number; flags: number; /** The old path whenever there is an old side, not only renames. */ oldPath: string; newPath: string; } | { kind: "row"; /** 1-based; 0 = side absent (pure addition/deletion). */ oldLine: number; newLine: number; oldText: Uint8Array; newText: Uint8Array; /** Changed byte ranges `[start, len]` within each side's text. */ oldSpans: Array<[number, number]>; newSpans: Array<[number, number]>; } | { kind: "gap"; oldLine: number; newLine: number; } | { kind: "base"; oid: GitOid; } | GitCursorRecord; export type GitIndexRecord = { kind: "entry"; stage: number; iflags: number; mode: number; size: number; mtimeNs: bigint; oid: GitOid; path: string; } | GitCursorRecord; /** One repository found by {@link msgGitDiscover}, deduped by gitdir. */ export type GitDiscoverRecord = { kind: "repo"; flags: number; workdir: string; gitdir: string; } | GitCursorRecord; /** One contiguous attributed range. Author and message are deliberately * absent: resolve the distinct `commit` oids with one `GIT_LOG`, or find * them already in an oid-keyed cache. */ export type GitBlameRecord = { kind: "range"; flags: number; commit: GitOid; startLine: number; lineCount: number; origStart: number; /** "" unless the range came from a different path. */ origPath: string; } | GitCursorRecord; export type GitReflogRecord = { kind: "entry"; flags: number; old: GitOid; new: GitOid; time: bigint; tz: number; msg: string; } | GitCursorRecord; /** What the remote answered for one ref. A remote can refuse one refspec * of several and still exit zero, so `status` per ref is how "did I * actually get these commits" is answered. */ export type GitWorktreeRecord = { kind: "tree"; /** `GIT_WORKTREE_*` bits. */ flags: number; /** The commit that worktree's HEAD resolves to; zero when unborn, or * when it is `PRUNABLE` and its HEAD cannot be read. */ oid: GitOid; /** Escaped worktree root; empty when `BARE`. */ path: string; /** Full ref name HEAD points at; empty when `DETACHED`. */ branch: string; /** Empty unless `LOCKED`, and empty even then when no reason was given. */ lockReason: string; } | GitCursorRecord; export type GitFetchRecord = { kind: "ref"; flags: number; status: number; old: GitOid; new: GitOid; name: string; detail: string; }; export declare function gitStateRecords(data: Uint8Array): Generator; export declare function gitCommitRecords(data: Uint8Array): Generator; export declare function gitTreeRecords(data: Uint8Array): Generator; export declare function gitDiffRecords(data: Uint8Array): Generator; export declare function gitPatchRecords(data: Uint8Array): Generator; export declare function gitIndexRecords(data: Uint8Array): Generator; export declare function gitDiscoverRecords(data: Uint8Array): Generator; export declare function gitBlameRecords(data: Uint8Array): Generator; export declare function gitReflogRecords(data: Uint8Array): Generator; export declare function gitWorktreeRecords(data: Uint8Array): Generator; export declare function gitFetchRecords(data: Uint8Array): Generator; /** Append one record to an uncompressed records buffer (tests and mocks). */ export declare function appendGitStateRecord(buf: number[], record: GitStateRecord): void; /** One repository found by {@link BlitConnection.discoverRepos}. */ export interface GitFoundRepo { /** Worktree root; empty for a bare repository. */ workdir: string; /** Canonical git directory — the identity the server dedupes on, and the * one `GIT_REPO` reports for an open of this repository. */ gitdir: string; bare: boolean; /** A linked worktree (`git worktree add`). */ linked: boolean; submodule: boolean; } export interface GitDiscoverOptions { /** Directory levels to descend; 0 = the server default (4), clamped. */ depth?: number; /** Descend *into* a repository once one is found. Off by default, so a * tree full of vendored checkouts costs nothing. */ nested?: boolean; /** Report bare repositories too. */ bare?: boolean; /** Each page as it lands, for a caller rendering progressively. The * promise still resolves with every repository found. */ onPage?: (repos: GitFoundRepo[]) => void; /** Bound on pages followed (default 64), for a walk over a tree being * written to underneath it. */ maxPages?: number; /** Abort the walk; the promise rejects with a cancelled * {@link GitStatusError}. */ signal?: AbortSignal; } export interface GitOpenOptions { /** Stream `GIT_STATE` snapshots (implied by status/tracking). */ watch?: boolean; /** Include index/worktree status entries in state. */ status?: boolean; /** Status includes untracked files (implies status). */ untracked?: boolean; /** Status includes ignored files (implies untracked). */ ignored?: boolean; /** Include per-branch upstream ahead/behind records. */ tracking?: boolean; /** Include one `STATE_REMOTE` record per configured remote. */ remotes?: boolean; /** Open a submodule of this already-open repo: `path` is then relative * to its worktree and the server resolves the submodule's own gitdir, * so a client never has to guess where `.gitmodules` put it. */ parentRepoId?: number; /** Ref prefixes to watch; empty watches every ref. A UI that renders * branches and never tags stops paying for tags at every settle. */ refPrefixes?: string[]; /** Ref settle window in ms; 0 = server default (50). */ refsLatencyMs?: number; /** Status settle window in ms; 0 = server default (500). */ statusLatencyMs?: number; /** A state snapshot was applied and acknowledged. */ onState?: (mirror: GitStateMirror, stateId: number) => void; /** The repo ended: a `GIT_CLOSED` reason, or * {@link GIT_CLOSED_CONNECTION_LOST} when the connection dropped. */ onClosed?: (reason: number) => void; /** Resolve the repo's discovery path from this session's live cwd, so the * repo follows `cd` (docs/ide.md Decision 3). The session must be on the * same connection. */ fromSessionId?: SessionId; } /** A repository opened by `BlitConnection.openRepo`. */ export interface GitRepoHandle extends ReactiveStore { readonly repoId: number; readonly oidFormat: number; /** `GIT_REPO_*` flags (bare/shallow/sparse/linked). */ readonly repoFlags: number; /** Escaped canonical worktree root; empty for bare. */ readonly workdir: string; /** Escaped canonical git directory. */ readonly gitdir: string; /** Live state; populated when watching. Replaced wholesale per snapshot. */ readonly state: GitStateMirror; /** One page of `hides..tips`; continue with `frontier` as `tips`. */ log(req?: Partial>, opts?: GitRequestOptions): Promise; /** One tree level; oid may be a commit/tag (peeled server-side). * A truncated listing ends with a `cursor` record — pass its `after` * to continue. */ tree(oid: GitOid, path?: string, opts?: GitRequestOptions & { after?: string; }): Promise; /** Object bytes, cached by oid (immutable, cache-forever). * A read is a window: `offset` plus `maxLen`, with the whole object * only when {@link GIT_BLOB_WHOLE} is set in `flags`. */ blob(oid: GitOid, path?: string, maxLen?: number, opts?: GitRequestOptions & { offset?: number; flags?: number; }): Promise; /** File-level diff records between two endpoints. A * {@link GIT_ENDPOINT_MERGE_BASE} old side answers with a `base` record * first, and pairs with a COMMIT, INDEX or WORKTREE new side. */ diff(old: GitEndpoint, newEndpoint: GitEndpoint, opts?: GitRequestOptions & { flags?: number; path?: string; /** Rename similarity threshold; 0 = the exact-oid join. */ rename?: number; after?: string; }): Promise; /** Patch rows (default) or unified text (`GIT_PATCH_TEXT`). */ patch(old: GitEndpoint, newEndpoint: GitEndpoint, opts?: GitRequestOptions & { flags?: number; context?: number; path?: string; maxLen?: number; rename?: number; after?: string; afterPos?: number; }): Promise<{ flags: number; records: GitPatchRecord[]; text: Uint8Array; }>; /** Index entries under a path prefix. */ index(path?: string, opts?: GitRequestOptions & { after?: string; }): Promise; /** Merge base of two or more commits; empty = disjoint histories. */ mergeBase(oids: GitOid[], opts?: GitRequestOptions): Promise; /** Resolve a revision spec (ref, oid, `HEAD~3`, `A..B`, `A...B`) to the * `tips`/`hides` a {@link log} or {@link watchLog} walks between. */ resolve(spec: string, opts?: GitRequestOptions): Promise<{ tips: GitOid[]; hides: GitOid[]; }>; /** Line attribution. Author and message are deliberately absent: resolve * the returned commit oids with one {@link log}, or find them already in * the oid-keyed cache. A blame the line budget cut short ends with a * `cursor` record — continue with `startLine` one past its `pos`. */ blame(path: string, opts?: GitRequestOptions & { oid?: GitOid; startLine?: number; lineCount?: number; flags?: number; }): Promise; /** Reflog entries for a ref ("" = HEAD), newest-first by default. The * only way to name an oid no longer reachable from any ref. A reflog * longer than `limit` ends with a `cursor` record — continue with * `afterPos` set to its `pos`. */ reflog(refName?: string, opts?: GitRequestOptions & { flags?: number; limit?: number; afterPos?: number; }): Promise; /** The repository's worktrees: the main one first (wherever in the set * this handle was opened), then every linked one. `MAIN` and `CURRENT` * say which is which, and a checkout deleted behind git's back comes * back `PRUNABLE` rather than missing. * * A one-shot read, but not a stale one: refetch whenever * {@link GitStateMirror.worktreeGen} moves and the list stays live. A set * larger than the server's budget ends with a `cursor` record — continue * with `afterPos` set to its `pos`. */ worktrees(opts?: GitRequestOptions & { afterPos?: number; }): Promise; /** Fetch from a remote, reporting per-ref what happened — so "did I * actually get these commits" is answerable from the reply rather than * from an exit code that lies. */ fetch(opts?: GitRequestOptions & { remote?: string; refspecs?: string[]; flags?: number; timeoutMs?: number; }): Promise; /** Subscribe to a server-pushed log of `spec`. `onUpdate` fires with the * first page and again whenever the resolved endpoints move (a named ref * changes). Pages are acknowledged automatically. `close()` unsubscribes. */ watchLog(spec: string, opts: GitLogWatchOptions, onUpdate: (page: GitLogPage) => void): GitLogSubscription; /** Close the repo; `onClosed` fires when the server confirms. */ close(): void; } /** Options every git request accepts. */ export interface GitRequestOptions { /** Abort the request. The promise rejects immediately with a * {@link GitStatusError} whose `cancelled` is true, and `GIT_CANCEL` * goes to the server. */ signal?: AbortSignal; } export interface GitLogWatchOptions { /** `GIT_LOG_*` bits (first-parent, topo, full-message, follow, path-oids). */ flags?: number; /** Page size; 0 = server default, clamped to the server maximum. */ limit?: number; } /** A live log subscription created by {@link GitRepoHandle.watchLog}. */ export interface GitLogSubscription { /** Client-assigned subscription id (unique per connection). */ readonly logId: number; /** Unsubscribe; sends `GIT_LOG_UNWATCH` and stops delivering pages. */ close(): void; } /** * Whether a `STATE_REF` name is a gitdir **pseudo-ref** — `MERGE_HEAD`, * `ORIG_HEAD`, `CHERRY_PICK_HEAD`, `REBASE_HEAD`, `REVERT_HEAD`, and the * `MERGE_HEAD#2…` an octopus adds — rather than a real ref. * * They share the ref stream (an in-progress operation is repository state * like any other) but they are not refs: git resolves them from the gitdir, * they disappear when the operation ends, and none of them is something a * client can check out. The distinction is the missing `refs/` prefix, and * it is here so that a consumer inverting `state.refs` into an oid → names * decoration map has one call to make rather than a rule to rediscover — * without it `ORIG_HEAD` renders as though it were a branch. */ export declare function isGitPseudoRef(name: string): boolean; /** Human-readable common-status text. */ export declare function gitStatusText(status: number): string; /** * A rejected git request, carrying the status byte the wire already had. * * Without it the only test available to a consumer is * `error.message.includes("not found")`, and a false positive there turns * a recoverable transport blip into a hard failure — which is why a * consumer that wanted to treat `NOT_FOUND` as "fetch it" and anything * else as a real error wrote that code and then reverted it. * * `message` keeps the human-readable form, so existing string matching * still works; `status` is the supported test. */ export declare class GitStatusError extends Error { /** A `GIT_STATUS_*` code. */ readonly status: number; /** `GIT_REPO`'s diagnostic, else "". */ readonly detail: string; /** Which request failed — "open", "log", "diff", … */ readonly op: string; constructor(op: string, status: number, detail?: string); /** True when the request ended because the caller aborted it, rather * than because it failed — indistinguishable before this class. */ get cancelled(): boolean; } export interface GitHead { flags: number; oid: GitOid; /** Symbolic target; empty when detached. */ name: string; } export interface GitRefState { flags: number; oid: GitOid; peeled: GitOid; /** The symbolic target's ref name with {@link GIT_REF_SYMBOLIC}, else * "". How a client names the default branch instead of guessing. */ target: string; } export interface GitRemoteState { flags: number; /** As configured, userinfo included. */ fetchUrl: string; /** "" when it equals {@link fetchUrl}. */ pushUrl: string; } export interface GitUpstreamState { flags: number; ahead: number; behind: number; upstream: string; } export interface GitStatusEntry { staged: number; unstaged: number; flags: number; /** The worktree content's hash when the status walk read the file, else * zero. A write that leaves the letters alone still moves this, so the * snapshot is not suppressed as a duplicate (indent-com/blit#120). */ oid: GitOid; oldPath: string; path: string; } export interface GitStashEntry { index: number; oid: GitOid; time: bigint; tz: number; message: string; } export interface GitOpState { op: number; oid: GitOid; detail: string; } /** * The complete client obligation for the state stream: apply snapshots * (each replaces the whole state), acknowledge the returned id. */ export declare class GitStateMirror { #private; head: GitHead | null; refs: Map; op: GitOpState | null; status: GitStatusEntry[]; upstreams: Map; stashes: GitStashEntry[]; /** Keyed by remote name; populated with the `REMOTES` open flag. */ remotes: Map; /** * The worktree set's `{count, digest}` — refetch `GIT_WORKTREES` whenever * either moves. * * It lives in the state stream because that is the only thing that can * make a worktree change *arrive*: adding, removing, moving or locking one * leaves every ref and status record byte-identical, so the server's * identical-snapshot suppression would drop the push, and a client * refetching on ref moves would keep showing a worktree that no longer * exists. Only the generation is pushed, not the list: resolving one * worktree's HEAD costs opening its gitdir, which has no business running * on every 50 ms ref settle. * * `{count: 0, digest: 0n}` is a bare repo with no linked worktrees — and * also what a server too old to send the record leaves here, which is why * a first sighting counts as a change. */ worktreeGen: { count: number; digest: bigint; }; flags: number; /** * Apply one `S2C_GIT_STATE` message. * * Returns the `state_id` to acknowledge, or null when the snapshot is * not yet complete (a `PARTIAL` chunk was buffered) or the message was * malformed. In both of those cases there is nothing to acknowledge and * nothing new to render, so one null covers them. */ applyState(msg: Uint8Array): number | null; } //# sourceMappingURL=git.d.ts.map