3 Commits

Author SHA1 Message Date
Mplan d0506381f5 refactor(cli): remove interactive prompts for empty states and add clean repo test
Build / bun-build (push) Successful in 29s
Build / bun-build (pull_request) Successful in 37s
2026-06-12 00:42:49 +08:00
Mplan 14df49b110 refactor(cli): replace process.exit prompts with interactive selection for empty states 2026-06-12 00:36:01 +08:00
Mplan 962b76d20f refactor(cli): show empty state prompt in current page
Empty commit/PR states no longer auto-return to the menu. Instead, the
user is shown an in-page prompt with a Back option, mirroring the rest
of the CLI: pressing Enter on Back (or ←/backspace) closes the prompt
and returns control to the previous step.
2026-06-12 00:35:23 +08:00
2 changed files with 68 additions and 15 deletions
+18 -15
View File
@@ -645,15 +645,6 @@ async function handleCommit(
autoMode: boolean, autoMode: boolean,
dryRun: boolean, dryRun: boolean,
): Promise<"done" | "back"> { ): 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())) { if (!(await isGitRepo())) {
console.error(` ${RED}Error: Not a git repository.${RESET}`); console.error(` ${RED}Error: Not a git repository.${RESET}`);
process.exit(1); process.exit(1);
@@ -663,7 +654,7 @@ async function handleCommit(
const unstagedFiles = await getUnstagedFiles(); const unstagedFiles = await getUnstagedFiles();
if (stagedFiles.length === 0 && unstagedFiles.length === 0) { if (stagedFiles.length === 0 && unstagedFiles.length === 0) {
console.log(" Nothing to commit."); console.log(` ${DIM}Nothing to commit. No staged or unstaged changes.${RESET}`);
return "done"; return "done";
} }
@@ -687,10 +678,19 @@ async function handleCommit(
const diff = await getStagedDiff(); const diff = await getStagedDiff();
if (!diff) { if (!diff) {
console.log(" No staged changes to commit."); console.log(` ${DIM}Nothing to commit. No staged changes to commit.${RESET}`);
return "done"; 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 MAX_DIFF_SIZE = 15000;
const truncatedDiff = const truncatedDiff =
diff.length > MAX_DIFF_SIZE diff.length > MAX_DIFF_SIZE
@@ -816,10 +816,13 @@ async function handlePR(draft: boolean): Promise<"done" | "back"> {
const commits = await getBranchCommits(baseBranch); const commits = await getBranchCommits(baseBranch);
if (commits.length === 0) { if (commits.length === 0) {
console.error( const choice = await selectOne({
` ${RED}Error: No commits on ${branchName} compared to ${baseBranch}. Commit something first.${RESET}`, title: "No commits to compare",
); subtitle: `No commits on ${branchName} compared to ${baseBranch}. Commit something first.`,
process.exit(1); items: [{ label: "Back", value: "back" as const }],
});
if (choice === null) process.exit(0);
return "done";
} }
console.log( console.log(
+50
View File
@@ -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<string, string> = {}) {
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");
});
});