/** * GitCore - Effect service contract for low-level Git operations. * * Wraps core repository primitives used by higher-level orchestration * services and WebSocket routes. * * @module GitCore */ import { Context } from "effect"; import type { Effect } from "effect"; import type { GitCheckoutInput, GitCheckoutResult, GitCreateBranchInput, GitCreateBranchResult, GitCreateWorktreeInput, GitCreateWorktreeResult, GitInitInput, GitListBranchesInput, GitListBranchesResult, GitPullResult, GitRemoveWorktreeInput, GitStatusInput, GitStatusResult, } from "@t3tools/contracts"; import type { GitCommandError } from "@t3tools/contracts"; export interface ExecuteGitInput { readonly operation: string; readonly cwd: string; readonly args: ReadonlyArray; readonly stdin?: string; readonly env?: NodeJS.ProcessEnv; readonly allowNonZeroExit?: boolean; readonly timeoutMs?: number; readonly maxOutputBytes?: number; readonly truncateOutputAtMaxBytes?: boolean; readonly progress?: ExecuteGitProgress; } export interface ExecuteGitResult { readonly code: number; readonly stdout: string; readonly stderr: string; readonly stdoutTruncated: boolean; readonly stderrTruncated: boolean; } export interface GitStatusDetails extends Omit { upstreamRef: string | null; } export interface GitPreparedCommitContext { stagedSummary: string; stagedPatch: string; } export interface ExecuteGitProgress { readonly onStdoutLine?: (line: string) => Effect.Effect; readonly onStderrLine?: (line: string) => Effect.Effect; readonly onHookStarted?: (hookName: string) => Effect.Effect; readonly onHookFinished?: (input: { hookName: string; exitCode: number | null; durationMs: number | null; }) => Effect.Effect; } export interface GitCommitProgress { readonly onOutputLine?: (input: { stream: "stdout" | "stderr"; text: string; }) => Effect.Effect; readonly onHookStarted?: (hookName: string) => Effect.Effect; readonly onHookFinished?: (input: { hookName: string; exitCode: number | null; durationMs: number | null; }) => Effect.Effect; } export interface GitCommitOptions { readonly timeoutMs?: number; readonly progress?: GitCommitProgress; } export interface GitPushResult { status: "pushed" | "skipped_up_to_date"; branch: string; upstreamBranch?: string | undefined; setUpstream?: boolean | undefined; } export interface GitRangeContext { commitSummary: string; diffSummary: string; diffPatch: string; } export interface GitListWorkspaceFilesResult { readonly paths: ReadonlyArray; readonly truncated: boolean; } export interface GitRenameBranchInput { cwd: string; oldBranch: string; newBranch: string; } export interface GitRenameBranchResult { branch: string; } export interface GitFetchPullRequestBranchInput { cwd: string; prNumber: number; branch: string; } export interface GitEnsureRemoteInput { cwd: string; preferredName: string; url: string; } export interface GitFetchRemoteBranchInput { cwd: string; remoteName: string; remoteBranch: string; localBranch: string; } export interface GitSetBranchUpstreamInput { cwd: string; branch: string; remoteName: string; remoteBranch: string; } /** * GitCoreShape - Service API for low-level Git repository interactions. */ export interface GitCoreShape { /** * Execute a raw Git command. */ readonly execute: (input: ExecuteGitInput) => Effect.Effect; /** * Read Git status for a repository. */ readonly status: (input: GitStatusInput) => Effect.Effect; /** * Read detailed working tree / branch status for a repository. */ readonly statusDetails: (cwd: string) => Effect.Effect; /** * Read detailed working tree / branch status without refreshing remote tracking refs. */ readonly statusDetailsLocal: (cwd: string) => Effect.Effect; /** * Build staged change context for commit generation. */ readonly prepareCommitContext: ( cwd: string, filePaths?: readonly string[], ) => Effect.Effect; /** * Create a commit with provided subject/body. */ readonly commit: ( cwd: string, subject: string, body: string, options?: GitCommitOptions, ) => Effect.Effect<{ commitSha: string }, GitCommandError>; /** * Push current branch, setting upstream if needed. */ readonly pushCurrentBranch: ( cwd: string, fallbackBranch: string | null, ) => Effect.Effect; /** * Collect commit/diff context between base branch and current HEAD. */ readonly readRangeContext: ( cwd: string, baseBranch: string, ) => Effect.Effect; /** * Read a Git config value from the local repository. */ readonly readConfigValue: ( cwd: string, key: string, ) => Effect.Effect; /** * Determine whether the provided cwd is inside a git work tree. */ readonly isInsideWorkTree: (cwd: string) => Effect.Effect; /** * List tracked and untracked workspace file paths relative to cwd. */ readonly listWorkspaceFiles: ( cwd: string, ) => Effect.Effect; /** * Remove gitignored paths from a relative path list. */ readonly filterIgnoredPaths: ( cwd: string, relativePaths: ReadonlyArray, ) => Effect.Effect, GitCommandError>; /** * List local + remote branches and branch metadata. */ readonly listBranches: ( input: GitListBranchesInput, ) => Effect.Effect; /** * Pull current branch from upstream using fast-forward only. */ readonly pullCurrentBranch: (cwd: string) => Effect.Effect; /** * Create a worktree and branch from a base branch. */ readonly createWorktree: ( input: GitCreateWorktreeInput, ) => Effect.Effect; /** * Materialize a GitHub pull request head as a local branch without switching checkout. */ readonly fetchPullRequestBranch: ( input: GitFetchPullRequestBranchInput, ) => Effect.Effect; /** * Ensure a named remote exists for the provided URL, returning the reused or created remote name. */ readonly ensureRemote: (input: GitEnsureRemoteInput) => Effect.Effect; /** * Fetch a remote branch into a local branch without checkout. */ readonly fetchRemoteBranch: ( input: GitFetchRemoteBranchInput, ) => Effect.Effect; /** * Set the upstream tracking branch for a local branch. */ readonly setBranchUpstream: ( input: GitSetBranchUpstreamInput, ) => Effect.Effect; /** * Remove an existing worktree. */ readonly removeWorktree: (input: GitRemoveWorktreeInput) => Effect.Effect; /** * Rename an existing local branch. */ readonly renameBranch: ( input: GitRenameBranchInput, ) => Effect.Effect; /** * Create a local branch. */ readonly createBranch: ( input: GitCreateBranchInput, ) => Effect.Effect; /** * Checkout an existing branch and refresh its upstream metadata in background. */ readonly checkoutBranch: ( input: GitCheckoutInput, ) => Effect.Effect; /** * Initialize a repository in the provided directory. */ readonly initRepo: (input: GitInitInput) => Effect.Effect; /** * List local branch names (short format). */ readonly listLocalBranchNames: (cwd: string) => Effect.Effect; } /** * GitCore - Service tag for low-level Git repository operations. */ export class GitCore extends Context.Service()("t3/git/Services/GitCore") {}