import type { DiffFileEntry } from "shared/types/index.js";
/**
 * Validate a string as a safe git ref name.
 * Rejects characters and patterns that are invalid or dangerous in git branch names.
 * Based on git-check-ref-format rules.
 */
export declare function validateGitRef(ref: string): void;
/**
 * Validate that a folder path is an absolute path to an existing directory.
 * Resolves symlinks/traversal to prevent path-based attacks.
 */
export declare function validateFolderPath(folder: string): string;
export interface GitInfo {
    isGitRepo: boolean;
    branch?: string;
}
/**
 * Check if a directory is a git repository and get the current branch
 */
export declare function getGitInfo(directory: string): GitInfo;
export interface WorktreeResolution {
    mainRepoPath: string;
    isWorktree: boolean;
}
/**
 * Detect if a directory is a git worktree and resolve it to the main repository path.
 *
 * A worktree directory has a `.git` **file** (not directory) containing a line like:
 *   gitdir: /path/to/main-repo/.git/worktrees/<name>
 *
 * We parse this to navigate back to the main repo. This avoids spawning any
 * `git` subprocess — it's pure filesystem reads, safe to call per-session.
 *
 * Git submodules also have a `.git` file, but it points to `../.git/modules/<name>`,
 * not `.git/worktrees/<name>`, so they correctly return `isWorktree: false`.
 */
export declare function resolveWorktreeToMainRepo(folder: string): WorktreeResolution;
/**
 * Cached wrapper around resolveWorktreeToMainRepo.
 * Safe to call per-session in hot paths like paginated chat discovery.
 */
export declare function resolveWorktreeToMainRepoCached(folder: string): WorktreeResolution;
/**
 * List local branch names for a git repository.
 * Returns branches sorted alphabetically with the current branch first.
 */
export declare function getGitBranches(directory: string): string[];
export interface WorktreeInfo {
    path: string;
    branch: string | null;
    isMainWorktree: boolean;
    isBare: boolean;
}
export interface BranchMetaInfo {
    branch: string;
    isCurrent: boolean;
    upstream: string | null;
    ahead: number;
    behind: number;
    lastCommit: {
        sha: string;
        shortSha: string;
        author: string;
        subject: string;
        committedAt: string;
    } | null;
}
/**
 * Get rich metadata for every local branch in a repository. Single
 * `git for-each-ref` call to keep this cheap.
 */
export declare function getBranchMeta(directory: string): BranchMetaInfo[];
/**
 * Get the remote URL (origin) for a repo. Returns null if not set or if
 * git fails. Used to map branches to GitHub owner/repo for PR lookups.
 */
export declare function getOriginRemoteUrl(directory: string): string | null;
/**
 * Parse a GitHub URL (https or ssh) into owner/repo. Returns null on any
 * non-GitHub remote or unparseable input.
 *
 * Handles:
 *   https://github.com/owner/repo(.git)?
 *   git@github.com:owner/repo(.git)?
 *   ssh://git@github.com/owner/repo(.git)?
 */
export declare function parseGithubRemote(url: string): {
    owner: string;
    repo: string;
} | null;
/**
 * List all git worktrees for a repository.
 * Parses `git worktree list --porcelain` output.
 */
export declare function getGitWorktrees(directory: string): WorktreeInfo[];
/**
 * Check whether merging `branch` into `base` would produce conflicts, without
 * touching the working tree. Tries `origin/<base>` first, falls back to `<base>`.
 * Returns `null` if detection is unavailable (git pre-2.38, ref missing, error).
 */
export declare function detectMergeConflict(repoDir: string, branch: string, base: string): {
    hasConflict: boolean;
    baseRef: string;
} | null;
/**
 * Collect per-branch working-tree status flags. Both fields are `null` when the
 * information can't be determined (no worktree for uncommitted, no remote ref
 * for unpushed). Designed to be cheap — one `status` call per worktree, one
 * `rev-list --count` per branch.
 */
export declare function getBranchStatusFlags(repoDir: string, branch: string, worktreePath: string | null): {
    hasUncommittedChanges: boolean | null;
    hasUnpushedCommits: boolean | null;
    unpushedCount: number | null;
};
/**
 * Delete a local branch. Refuses to delete the currently-checked-out branch or
 * a branch still checked out in any worktree (safety matches `git branch -d`
 * but returns a clearer error). Uses `-D` when `force` is true.
 */
export declare function deleteLocalBranch(repoDir: string, branch: string, force?: boolean): void;
/**
 * Remove a git worktree and prune stale references.
 * Refuses to remove the main worktree.
 *
 * @param repoDir - The main repository directory
 * @param worktreePath - Absolute path of the worktree to remove
 * @param force - If true, forces removal even with uncommitted changes
 */
export declare function removeWorktree(repoDir: string, worktreePath: string, force?: boolean): void;
/**
 * Create or reuse a git worktree as a sibling directory of the repo.
 * Worktree path: [repo-parent]/[repo-name].[sanitized-branch]
 *
 * If the worktree already exists at the expected path, returns the path without creating.
 *
 * @param repoDir - The original repository directory
 * @param branch - Branch name to checkout in the worktree
 * @param createBranch - If true and branch doesn't exist, create it from baseBranch
 * @param baseBranch - Base branch for new branch creation
 * @returns The absolute path to the worktree directory
 */
export declare function ensureWorktree(repoDir: string, branch: string, createBranch: boolean, baseBranch?: string): string;
/**
 * Switch to a branch in the given directory (non-worktree mode).
 * If createNew is true, creates the branch from baseBranch first.
 *
 * Before checking out, inspects the worktree list. If the target branch is
 * already checked out in a different worktree, returns that worktree's path
 * instead of attempting (and failing) the checkout.
 *
 * @returns The worktree path if the branch lives in a different worktree, or
 *          `null` if the checkout happened in-place in `directory`.
 */
export declare function switchBranch(directory: string, branch: string, createNew: boolean, baseBranch?: string): string | null;
/**
 * Check whether the working directory has any uncommitted changes.
 * Uses `git status --porcelain` which is fast and catches:
 *   - staged changes
 *   - unstaged modifications
 *   - untracked files
 *
 * Returns true if there are ANY changes; false if the working tree is clean.
 */
export declare function hasUncommittedChanges(directory: string): boolean;
export interface ResolveBranchOptions {
    /** Absolute path to the working directory / repo root */
    folder: string;
    /** Branch to switch to (or base for newBranch) */
    baseBranch?: string;
    /** New branch name to create (from baseBranch or current HEAD) */
    newBranch?: string;
    /** Create a git worktree instead of switching branches in-place */
    useWorktree?: boolean;
    /** Skip uncommitted-changes guard (default: false) */
    forceBranchChange?: boolean;
}
export type ResolveBranchResult = {
    ok: true;
    folder: string;
} | {
    ok: false;
    error: "uncommitted_changes";
    message: string;
    currentBranch: string;
    targetBranch: string;
};
/**
 * Resolve a branch configuration to an effective working directory.
 *
 * Handles worktree creation, new-branch creation, and branch switching
 * with a dirty-state guard. Returns the (possibly new) folder path on
 * success, or a structured error when uncommitted changes block an
 * in-place branch switch.
 *
 * Worktrees are inherently isolated and bypass the dirty-state guard.
 */
export declare function resolveBranch(opts: ResolveBranchOptions): ResolveBranchResult;
/**
 * Get the git diff (unstaged + staged) for a repository.
 * Returns the raw unified diff string.
 */
export declare function getGitDiff(directory: string): string;
/**
 * Validate a filename to prevent path traversal attacks.
 * Allows legitimate patterns like Next.js catch-all routes: [[...slug]], [...params]
 */
export declare function validateFilename(filename: string): void;
/**
 * Get structured git diff with file metadata, untracked files, and large file gating.
 */
export declare function getGitDiffStructured(directory: string): DiffFileEntry[];
/**
 * Get the diff for a single file on demand (for large files loaded after user clicks "show anyway").
 */
export declare function getGitFileDiff(directory: string, filename: string): {
    diff: string;
    additions: number;
    deletions: number;
};
/**
 * Read a raw file from a repository for media previews.
 */
export declare function readRepoFile(directory: string, filename: string): {
    buffer: Buffer;
    contentType: string;
};
//# sourceMappingURL=git.d.ts.map