import { spawnSync } from 'node:child_process'; export interface Revision { sha: string; shortSha: string; author: string; /** ISO 8601, author date. */ date: string; subject: string; } /** * The spawn, injectable — the same seam the LLM providers use for `fetch`. * * Exported because the retry below is otherwise untestable: provoking a real * `EAGAIN` means exhausting the process table, which is not something a test * suite should do to the machine running it. A retry nothing checks is a retry * somebody deletes in a refactor, and mutation testing said exactly that. * * It widens nothing in practice: the CLI has no library entry, so this module * is reachable only from inside this package and from its tests. */ export type SpawnLike = typeof spawnSync; /** * Thrown when git could not be run, as distinct from git having nothing to say. * * A distinct type rather than a message, so a caller cannot accidentally treat * it as an empty result — which is the whole bug. */ export declare class GitUnavailableError extends Error { constructor(detail: string); } /** * Whether `git` can be run at all. * * Separate from `repositoryRoot` because the two failures need different * advice: "install git" and "run this inside a repository" have nothing to do * with each other, and a single "could not read history" would send half the * readers looking in the wrong place. */ export declare function gitAvailable(cwd: string): boolean; /** The repository root containing `cwd`, or `null` if there is not one. */ export declare function repositoryRoot(cwd: string): string | null; /** * The path as git knows it — relative to the repository root, forward slashes — * or `null` when it falls outside the repository. */ export declare function pathInRepository(root: string, target: string): string | null; /** * Runs this same CLI in a child process and returns its stdout. * * The bench's isolation seam, kept in this module so the invariant the * security suite asserts — child_process appears in exactly one file — stays * whole. The same rules as the git spawn, and one more: **every argument is * the caller's own.** The bench passes a script path derived from its own * module URL, workload ids from a const list, and a locale its catalogue * produced; nothing typed by a user reaches this argv. */ export declare function runSelf(scriptPath: string, args: readonly string[]): string; /** * Commits that touched `repoPath`, newest first. * * `--follow` so a renamed prompt keeps its history: a file moved from * `prompt.txt` to `prompts/support.txt` is the same prompt, and a cost history * that restarts at the rename is telling you the growth began the day somebody * tidied the directory. */ export declare function revisionsFor(repoPath: string, options: { cwd: string; max: number; spawn?: SpawnLike; }): Revision[]; /** * The file's content at a commit, or `null` if it did not exist there. * * `--follow` above means the path can differ from the one at that commit, so * this asks git for the name it had rather than assuming today's. */ export declare function contentAt(sha: string, repoPath: string, cwd: string): string | null; /** * The name the file had at each commit, keyed by sha. * * One `git log` rather than one per revision, and it replaces a version that * asked per commit and got nothing back: `git log --follow --max-count=1 * -- ` returns an empty list for every commit before a rename, * because at those commits that name did not exist. The effect was that a * renamed prompt showed "not present" for its entire history before the move — * the data was there, under the old name, and the report said there was none. * * Asking once, without a starting commit, lets `--follow` do the mapping it * exists for: the output pairs each sha with the path it touched. */ export declare function namesByRevision(repoPath: string, cwd: string, max: number): Map; //# sourceMappingURL=git.d.ts.map