Extract shared gitError helper to deduplicate stderr formatting
Also clear activity on failed merge and improve error context for conflicted file reads. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fbb8680376
commit
101651b107
|
|
@ -120,7 +120,9 @@ export async function resolveConflicts(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = await Bun.file(join(cwd, file)).text()
|
const content = await Bun.file(join(cwd, file)).text().catch(() => {
|
||||||
|
throw new Error(`Failed to read conflicted file: ${file}`)
|
||||||
|
})
|
||||||
|
|
||||||
const resolved = await vm.claudePipe(
|
const resolved = await vm.claudePipe(
|
||||||
content,
|
content,
|
||||||
|
|
@ -128,8 +130,7 @@ export async function resolveConflicts(
|
||||||
)
|
)
|
||||||
|
|
||||||
if (resolved.exitCode !== 0 || !resolved.stdout.trim()) {
|
if (resolved.exitCode !== 0 || !resolved.stdout.trim()) {
|
||||||
const stderr = resolved.stderr.trim()
|
throw new Error(`Claude failed to resolve ${file}: ${resolved.stderr.trim() || "(no output)"}`)
|
||||||
throw new Error(`Claude failed to resolve ${file}: ${stderr || "(no output)"}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Bun.write(join(cwd, file), resolved.stdout.trimEnd() + "\n")
|
await Bun.write(join(cwd, file), resolved.stdout.trimEnd() + "\n")
|
||||||
|
|
@ -187,6 +188,7 @@ export async function mergeAndClose(branch: string, opts?: { squash?: boolean; f
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const message = err instanceof Error ? err.message : String(err)
|
const message = err instanceof Error ? err.message : String(err)
|
||||||
spin.fail(message)
|
spin.fail(message)
|
||||||
|
if (session) await vm.clearActivity(session.worktree, branch)
|
||||||
await git.abortMerge(root)
|
await git.abortMerge(root)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
30
src/git.ts
30
src/git.ts
|
|
@ -2,6 +2,12 @@ import { existsSync } from "fs"
|
||||||
import { rm } from "fs/promises"
|
import { rm } from "fs/promises"
|
||||||
import { $ } from "bun"
|
import { $ } from "bun"
|
||||||
|
|
||||||
|
/** Format a git error with a fallback for empty stderr. */
|
||||||
|
function gitError(action: string, stderr: Buffer | string): Error {
|
||||||
|
const msg = stderr.toString().trim()
|
||||||
|
return new Error(`${action}: ${msg || "(no output)"}`)
|
||||||
|
}
|
||||||
|
|
||||||
/** Get the repo root from a working directory. */
|
/** Get the repo root from a working directory. */
|
||||||
export async function repoRoot(cwd?: string): Promise<string> {
|
export async function repoRoot(cwd?: string): Promise<string> {
|
||||||
const result = await $`git rev-parse --show-toplevel`.cwd(cwd ?? ".").nothrow().quiet()
|
const result = await $`git rev-parse --show-toplevel`.cwd(cwd ?? ".").nothrow().quiet()
|
||||||
|
|
@ -72,8 +78,7 @@ export async function createWorktree(branch: string, worktreePath: string, cwd:
|
||||||
}
|
}
|
||||||
if (result.exitCode !== 0) {
|
if (result.exitCode !== 0) {
|
||||||
if (switchedFromBranch) await checkout(branch, cwd).catch(() => {})
|
if (switchedFromBranch) await checkout(branch, cwd).catch(() => {})
|
||||||
const stderr = result.stderr.toString().trim()
|
throw gitError(`Failed to create worktree for "${branch}"`, result.stderr)
|
||||||
throw new Error(`Failed to create worktree for "${branch}": ${stderr || "(no output)"}`)
|
|
||||||
}
|
}
|
||||||
return { branchCreated: exists !== "local" }
|
return { branchCreated: exists !== "local" }
|
||||||
}
|
}
|
||||||
|
|
@ -99,8 +104,7 @@ export async function deleteLocalBranch(branch: string, cwd: string): Promise<vo
|
||||||
export async function checkout(branch: string, cwd: string): Promise<void> {
|
export async function checkout(branch: string, cwd: string): Promise<void> {
|
||||||
const result = await $`git checkout ${branch}`.cwd(cwd).nothrow().quiet()
|
const result = await $`git checkout ${branch}`.cwd(cwd).nothrow().quiet()
|
||||||
if (result.exitCode !== 0) {
|
if (result.exitCode !== 0) {
|
||||||
const stderr = result.stderr.toString().trim()
|
throw gitError(`Failed to checkout branch "${branch}"`, result.stderr)
|
||||||
throw new Error(`Failed to checkout branch "${branch}": ${stderr || "(no output)"}`)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,8 +123,7 @@ export async function merge(branch: string, cwd: string, opts?: { squash?: boole
|
||||||
|
|
||||||
// Not a conflict — some other merge failure
|
// Not a conflict — some other merge failure
|
||||||
const label = opts?.squash ? "squash-merge" : "merge"
|
const label = opts?.squash ? "squash-merge" : "merge"
|
||||||
const stderr = result.stderr.toString().trim()
|
throw gitError(`Failed to ${label} branch "${branch}"`, result.stderr)
|
||||||
throw new Error(`Failed to ${label} branch "${branch}": ${stderr || "(no output)"}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the staged diff as text. */
|
/** Return the staged diff as text. */
|
||||||
|
|
@ -132,8 +135,7 @@ export async function diffStaged(cwd: string): Promise<string> {
|
||||||
export async function commit(message: string, cwd: string): Promise<void> {
|
export async function commit(message: string, cwd: string): Promise<void> {
|
||||||
const result = await $`git commit -m ${message}`.cwd(cwd).nothrow().quiet()
|
const result = await $`git commit -m ${message}`.cwd(cwd).nothrow().quiet()
|
||||||
if (result.exitCode !== 0) {
|
if (result.exitCode !== 0) {
|
||||||
const stderr = result.stderr.toString().trim()
|
throw gitError("Failed to commit", result.stderr)
|
||||||
throw new Error(`Failed to commit: ${stderr || "(no output)"}`)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,8 +143,7 @@ export async function commit(message: string, cwd: string): Promise<void> {
|
||||||
export async function checkoutTheirs(file: string, cwd: string): Promise<void> {
|
export async function checkoutTheirs(file: string, cwd: string): Promise<void> {
|
||||||
const result = await $`git checkout --theirs -- ${file}`.cwd(cwd).nothrow().quiet()
|
const result = await $`git checkout --theirs -- ${file}`.cwd(cwd).nothrow().quiet()
|
||||||
if (result.exitCode !== 0) {
|
if (result.exitCode !== 0) {
|
||||||
const stderr = result.stderr.toString().trim()
|
throw gitError(`Failed to checkout theirs for ${file}`, result.stderr)
|
||||||
throw new Error(`Failed to checkout theirs for ${file}: ${stderr || "(no output)"}`)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,8 +151,7 @@ export async function checkoutTheirs(file: string, cwd: string): Promise<void> {
|
||||||
export async function stageFile(file: string, cwd: string): Promise<void> {
|
export async function stageFile(file: string, cwd: string): Promise<void> {
|
||||||
const result = await $`git add ${file}`.cwd(cwd).nothrow().quiet()
|
const result = await $`git add ${file}`.cwd(cwd).nothrow().quiet()
|
||||||
if (result.exitCode !== 0) {
|
if (result.exitCode !== 0) {
|
||||||
const stderr = result.stderr.toString().trim()
|
throw gitError(`Failed to stage ${file}`, result.stderr)
|
||||||
throw new Error(`Failed to stage ${file}: ${stderr || "(no output)"}`)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,8 +159,7 @@ export async function stageFile(file: string, cwd: string): Promise<void> {
|
||||||
export async function commitMerge(cwd: string): Promise<void> {
|
export async function commitMerge(cwd: string): Promise<void> {
|
||||||
const result = await $`git commit --no-edit`.cwd(cwd).nothrow().quiet()
|
const result = await $`git commit --no-edit`.cwd(cwd).nothrow().quiet()
|
||||||
if (result.exitCode !== 0) {
|
if (result.exitCode !== 0) {
|
||||||
const stderr = result.stderr.toString().trim()
|
throw gitError("Failed to commit merge", result.stderr)
|
||||||
throw new Error(`Failed to commit merge: ${stderr || "(no output)"}`)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,8 +197,7 @@ export async function rebaseContinue(cwd: string): Promise<string[]> {
|
||||||
const files = unmerged.trim().split("\n").filter(Boolean)
|
const files = unmerged.trim().split("\n").filter(Boolean)
|
||||||
if (files.length > 0) return files
|
if (files.length > 0) return files
|
||||||
|
|
||||||
const stderr = result.stderr.toString().trim()
|
throw gitError("Rebase --continue failed", result.stderr)
|
||||||
throw new Error(`Rebase --continue failed: ${stderr || "(no output)"}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Abort an in-progress rebase. */
|
/** Abort an in-progress rebase. */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user