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