diff --git a/index.ts b/index.ts index d13cfd4..4d962d1 100644 --- a/index.ts +++ b/index.ts @@ -645,15 +645,6 @@ async function handleCommit( autoMode: boolean, dryRun: boolean, ): Promise<"done" | "back"> { - const config = await loadConfig(); - - if (!config.apiKey) { - console.error( - ` ${RED}Error: API key not set. Run ${BOLD}gai config${RESET}${RED} to configure.${RESET}`, - ); - process.exit(1); - } - if (!(await isGitRepo())) { console.error(` ${RED}Error: Not a git repository.${RESET}`); process.exit(1); @@ -663,12 +654,7 @@ async function handleCommit( const unstagedFiles = await getUnstagedFiles(); if (stagedFiles.length === 0 && unstagedFiles.length === 0) { - const choice = await selectOne({ - title: "Nothing to commit", - subtitle: "No staged or unstaged changes.", - items: [{ label: "Back", value: "back" as const }], - }); - if (choice === null) process.exit(0); + console.log(` ${DIM}Nothing to commit. No staged or unstaged changes.${RESET}`); return "done"; } @@ -692,15 +678,19 @@ async function handleCommit( const diff = await getStagedDiff(); if (!diff) { - const choice = await selectOne({ - title: "Nothing to commit", - subtitle: "No staged changes to commit.", - items: [{ label: "Back", value: "back" as const }], - }); - if (choice === null) process.exit(0); + console.log(` ${DIM}Nothing to commit. No staged changes to commit.${RESET}`); return "done"; } + const config = await loadConfig(); + + if (!config.apiKey) { + console.error( + ` ${RED}Error: API key not set. Run ${BOLD}gai config${RESET}${RED} to configure.${RESET}`, + ); + process.exit(1); + } + const MAX_DIFF_SIZE = 15000; const truncatedDiff = diff.length > MAX_DIFF_SIZE diff --git a/test/commit.test.ts b/test/commit.test.ts new file mode 100644 index 0000000..c748b13 --- /dev/null +++ b/test/commit.test.ts @@ -0,0 +1,50 @@ +import { mkdtempSync } from "node:fs"; +import { join } from "node:path"; +import { tmpdir } from "node:os"; +import { test, expect, describe } from "bun:test"; + +async function run(command: string[], cwd: string, env: Record = {}) { + const proc = Bun.spawn(command, { + cwd, + stdout: "pipe", + stderr: "pipe", + env: { + PATH: process.env.PATH ?? "", + HOME: env.HOME ?? process.env.HOME ?? "", + ...env, + }, + }); + + const [exitCode, stdout, stderr] = await Promise.all([ + proc.exited, + new Response(proc.stdout).text(), + new Response(proc.stderr).text(), + ]); + + return { exitCode, stdout, stderr }; +} + +describe("commit command", () => { + test("clean repository exits without requiring API key", async () => { + const repo = mkdtempSync(join(tmpdir(), "gai-clean-repo-")); + const home = mkdtempSync(join(tmpdir(), "gai-empty-home-")); + + const init = await run(["git", "init"], repo, { HOME: home }); + expect(init.exitCode).toBe(0); + + const result = await run( + ["bun", "run", join(import.meta.dir, "..", "index.ts"), "commit"], + repo, + { + HOME: home, + GAI_API_KEY: "", + }, + ); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toContain("Nothing to commit"); + expect(result.stdout).toContain("No staged or unstaged changes"); + expect(result.stderr).not.toContain("API key not set"); + expect(result.stderr).not.toContain("requires a TTY"); + }); +});