@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
167 lines • 8.41 kB
TypeScript
import type { PathSpec } from '../../../../types.ts';
import type { HeadRef, Refspec, SymbolicEnd } from './types.ts';
import type { Files } from '../../../../workspace/files.ts';
export declare const HEAD_FILE = "HEAD";
export declare const MAX_SYMREF_DEPTH = 5;
export declare const SYMREF_PREFIX = "ref: ";
export declare const BRANCH_PREFIX = "refs/heads/";
export declare const REMOTE_PREFIX = "refs/remotes/";
/**
* Resolve `.git/HEAD` to a branch name or a detached commit.
*
* HEAD holds either a symbolic ref (`ref: refs/heads/main`) or a raw object id
* when the checkout is detached. A ref outside `refs/heads` keeps its full name,
* which is what git shows for a checked-out tag or remote-tracking ref.
*/
export declare function readHead(vfs: Files, gitdir: PathSpec): Promise<HeadRef>;
/**
* Point one ref at an object id, as a loose ref file.
*
* Always written loose, never into `packed-refs`: git does the same for any ref
* it updates, and a loose file takes precedence over the packed copy, so a
* branch that was packed is correctly overridden rather than duplicated.
*
* Refs live in the common directory, so a branch made from a linked worktree is
* visible to the repository it was cut from, which is what makes `git worktree`
* share branches at all.
*
* A name whose path would leave the ref tree is refused here as git's ref
* transaction refuses it, whatever the caller checked: the name is joined onto
* the git directory, so `refs/heads/../../config` would land on the
* repository's own configuration. Every verb checks its name before it gets
* here, so this is the last guard, not the refusal a user sees.
*
* @throws BadRefNameUpdateError a name `safeRefName` refuses
*/
export declare function writeRef(vfs: Files, commondir: PathSpec, ref: string, sha: string): Promise<void>;
/**
* `packed-refs` with one ref's lines removed, null if it held none.
*
* A packed ref is two lines rather than one when it is an annotated tag: the tag
* object's own id, then a `^` line holding the commit it peels to. The peeled
* line belongs to the ref above it, so dropping a ref drops the `^` line that
* follows it and nothing else.
*/
export declare function withoutPacked(text: string, ref: string): string | null;
/**
* Remove a ref, loose copy and packed copy alike.
*
* Both are removed because either alone can be what holds the ref, and removing
* only the loose one would report a deletion the next read undoes: after
* `git pack-refs` a ref exists nowhere else, and a force-updated one exists in
* both, where dropping the loose file would resurrect the older packed value.
*/
export declare function deleteRef(vfs: Files, commondir: PathSpec, ref: string): Promise<void>;
/** Point HEAD at a branch, symbolically. */
export declare function setHead(vfs: Files, gitdir: PathSpec, ref: string): Promise<void>;
/** Point HEAD straight at a commit, detaching it from any branch. */
export declare function detachHead(vfs: Files, gitdir: PathSpec, sha: string): Promise<void>;
/**
* Read every ref a repository publishes, packed and loose.
*
* Both sources are needed and neither is optional: a freshly cloned repository
* keeps `refs/remotes/origin/main` only in `packed-refs`, while a branch
* committed to since the last pack exists only as a loose file. Loose wins on a
* collision, which is git's own precedence.
*
* Refs come from two directories when the two differ. A linked worktree shares
* its branches with the repository it was cut from and keeps only its own HEAD
* and per-checkout refs (`refs/bisect`, `refs/worktree`), so the shared table is
* read first and the worktree's own overrides it, then HEAD last of all.
*
* @param vfs the session's files
* @param gitdir this checkout's git directory, which owns HEAD
* @param commondir the shared git directory, which owns the branches; null means
* it is the same directory, which is every ordinary checkout
*/
export declare function loadRefs(vfs: Files, gitdir: PathSpec, commondir?: PathSpec | null): Promise<Map<string, string>>;
export declare const TAG_PREFIX = "refs/tags/";
/**
* The existing ref that stops a new one from being written.
*
* A ref is a path, so two of them cannot coexist when one spells a directory
* the other spells a file: with `refs/tags/foo` already there,
* `refs/tags/foo/bar` has no directory to live in, and with `refs/tags/foo/bar`
* there, `refs/tags/foo` has a directory standing on its name. git refuses both
* and names the ref already written; a repository can only ever hold one of the
* two shapes, so the two searches cannot both answer.
*
* Nothing below git's own storage can be relied on to say so. A disk mount
* raises whatever its host filesystem raises, which reaches the user as neither
* git's wording nor git's exit code, and a prefix store takes both keys happily
* and leaves a ref the loose-ref walk cannot find.
*
* @param known every ref the repository holds
* @param ref the full ref name about to be written
*/
export declare function blockingRef(known: ReadonlySet<string>, ref: string): string | null;
/**
* Whether a name passes git's ref rules (`git check-ref-format`).
*
* The rules, in git's own order: no component may start with `.` or end with
* `.lock`; `..` may not appear; no control character, space or shell
* metacharacter; no leading, trailing or doubled `/`; no trailing `.`; and no
* `@{`. Empty is refused too. A bare `@` is refused only as a whole ref, and a
* name here always sits below `refs/`, so it passes. Pinned against git 2.50.1.
*
* @param name the name below `refs/heads/` or `refs/tags/`
*/
export declare function validRefName(name: string): boolean;
/**
* Whether git takes a name for a new branch: git's ref rules, and two more
* that hold for a branch only: no leading `-`, which would read as an option,
* and not `HEAD`, which `refs/heads/HEAD` would make ambiguous with HEAD
* itself. Pinned against git 2.47.3.
*
* @param name the name below `refs/heads/`
*/
export declare function validBranchName(name: string): boolean;
/**
* Whether git's ref rules take a whole ref name, one level allowed, as
* `git check-ref-format --allow-onelevel` judges it: a bare `@` is the one name
* they refuse whole that they take below `refs/`.
*
* @param name the full ref name
*/
export declare function wholeRefName(name: string): boolean;
/**
* A ref's raw value, an object id or `ref: <target>`, null when there is none.
*
* Read from the ref table, or for a one-level name outside it (`ORIG_HEAD` and
* its kin) from the checkout's git directory, which is where git keeps them.
*
* @param vfs the session's files
* @param gitdir this checkout's git directory
* @param table every ref, as loadRefs reads them
* @param name the full ref name
*/
export declare function rawRef(vfs: Files, gitdir: PathSpec, table: ReadonlyMap<string, string>, name: string): Promise<string | null>;
/**
* Follow a symbolic ref the way git resolves one, without reading the object
* it lands on.
*
* One hop when `recurse` is off, otherwise to the end of the chain, which may
* name a ref that does not exist yet (an unborn branch). Null where git finds
* no such ref: a name its rules refuse, or a chain more than five deep. Pinned
* against git 2.47.3.
*
* @param vfs the session's files
* @param gitdir this checkout's git directory
* @param table every ref, as loadRefs reads them
* @param name the full ref name to start from
* @param recurse follow every hop rather than the first
*/
export declare function resolveSymbolic(vfs: Files, gitdir: PathSpec, table: ReadonlyMap<string, string>, name: string, recurse: boolean): Promise<SymbolicEnd | null>;
/**
* Whether git lets a ref update write a name it has no object for: below
* `refs/`, a path with no empty, `.` or `..` component; anywhere else, capitals
* and underscores only, which is HEAD and its kin. Pinned against git 2.47.3.
*
* @param name the full ref name about to be written
*/
export declare function safeRefName(name: string): boolean;
/** Split a refspec into its source, destination and force flag. */
export declare function parseRefspec(text: string): Refspec;
/** The local ref a refspec maps a remote ref to, null when unmatched. */
export declare function mapped(spec: Refspec, name: string): string | null;
//# sourceMappingURL=refs.d.ts.map