diff --git a/packages/opencode/src/file/watcher.ts b/packages/opencode/src/file/watcher.ts index c4a4747777..12445735f8 100644 --- a/packages/opencode/src/file/watcher.ts +++ b/packages/opencode/src/file/watcher.ts @@ -11,7 +11,7 @@ import { createWrapper } from "@parcel/watcher/wrapper" import { lazy } from "@/util/lazy" import { withTimeout } from "@/util/timeout" import type ParcelWatcher from "@parcel/watcher" -import { $ } from "bun" +import { gitText } from "../util/git" import { Flag } from "@/flag/flag" import { readdir } from "fs/promises" @@ -88,11 +88,7 @@ export namespace FileWatcher { if (sub) subs.push(sub) } - const vcsDir = await $`git rev-parse --git-dir` - .quiet() - .nothrow() - .cwd(Instance.worktree) - .text() + const vcsDir = await gitText(["rev-parse", "--git-dir"], Instance.worktree) .then((x) => path.resolve(Instance.worktree, x.trim())) .catch(() => undefined) if (vcsDir && !cfgIgnores.includes(".git") && !cfgIgnores.includes(vcsDir)) { diff --git a/packages/opencode/src/project/project.ts b/packages/opencode/src/project/project.ts index f6902de4e1..6032652241 100644 --- a/packages/opencode/src/project/project.ts +++ b/packages/opencode/src/project/project.ts @@ -2,7 +2,7 @@ import z from "zod" import fs from "fs/promises" import { Filesystem } from "../util/filesystem" import path from "path" -import { $ } from "bun" +import { gitText } from "../util/git" import { Storage } from "../storage/storage" import { Log } from "../util/log" import { Flag } from "@/flag/flag" @@ -55,15 +55,15 @@ export namespace Project { const { id, sandbox, worktree, vcs } = await iife(async () => { const matches = Filesystem.up({ targets: [".git"], start: directory }) - const git = await matches.next().then((x) => x.value) + const gitdir = await matches.next().then((x) => x.value) await matches.return() - if (git) { - let sandbox = path.dirname(git) + if (gitdir) { + let sandbox = path.dirname(gitdir) const gitBinary = Bun.which("git") // cached id calculation - let id = await Bun.file(path.join(git, "opencode")) + let id = await Bun.file(path.join(gitdir, "opencode")) .text() .then((x) => x.trim()) .catch(() => undefined) @@ -79,11 +79,7 @@ export namespace Project { // generate id from root commit if (!id) { - const roots = await $`git rev-list --max-parents=0 --all` - .quiet() - .nothrow() - .cwd(sandbox) - .text() + const roots = await gitText(["rev-list", "--max-parents=0", "--all"], sandbox) .then((x) => x .split("\n") @@ -104,7 +100,7 @@ export namespace Project { id = roots[0] if (id) { - void Bun.file(path.join(git, "opencode")) + void Bun.file(path.join(gitdir, "opencode")) .write(id) .catch(() => undefined) } @@ -119,11 +115,7 @@ export namespace Project { } } - const top = await $`git rev-parse --show-toplevel` - .quiet() - .nothrow() - .cwd(sandbox) - .text() + const top = await gitText(["rev-parse", "--show-toplevel"], sandbox) .then((x) => path.resolve(sandbox, x.trim())) .catch(() => undefined) @@ -138,11 +130,7 @@ export namespace Project { sandbox = top - const worktree = await $`git rev-parse --git-common-dir` - .quiet() - .nothrow() - .cwd(sandbox) - .text() + const worktree = await gitText(["rev-parse", "--git-common-dir"], sandbox) .then((x) => { const dirname = path.dirname(x.trim()) if (dirname === ".") return sandbox diff --git a/packages/opencode/src/project/vcs.ts b/packages/opencode/src/project/vcs.ts index e434b5f8c3..34e2b60a9c 100644 --- a/packages/opencode/src/project/vcs.ts +++ b/packages/opencode/src/project/vcs.ts @@ -1,7 +1,6 @@ import { BusEvent } from "@/bus/bus-event" import { Bus } from "@/bus" -import { $ } from "bun" -import path from "path" +import { gitText } from "../util/git" import z from "zod" import { Log } from "@/util/log" import { Instance } from "./instance" @@ -29,11 +28,7 @@ export namespace Vcs { export type Info = z.infer async function currentBranch() { - return $`git rev-parse --abbrev-ref HEAD` - .quiet() - .nothrow() - .cwd(Instance.worktree) - .text() + return gitText(["rev-parse", "--abbrev-ref", "HEAD"], Instance.worktree) .then((x) => x.trim()) .catch(() => undefined) } diff --git a/packages/opencode/src/storage/storage.ts b/packages/opencode/src/storage/storage.ts index 18f2d67e7a..e6565f1653 100644 --- a/packages/opencode/src/storage/storage.ts +++ b/packages/opencode/src/storage/storage.ts @@ -5,7 +5,7 @@ import { Global } from "../global" import { Filesystem } from "../util/filesystem" import { lazy } from "../util/lazy" import { Lock } from "../util/lock" -import { $ } from "bun" +import { gitText } from "../util/git" import { NamedError } from "@opencode-ai/util/error" import z from "zod" @@ -45,18 +45,18 @@ export namespace Storage { } if (!worktree) continue if (!(await Filesystem.isDir(worktree))) continue - const [id] = await $`git rev-list --max-parents=0 --all` - .quiet() - .nothrow() - .cwd(worktree) - .text() + const roots = await gitText(["rev-list", "--max-parents=0", "--all"], worktree) .then((x) => x - .split("\n") - .filter(Boolean) - .map((x) => x.trim()) - .toSorted(), + ? x + .split("\n") + .filter(Boolean) + .map((x) => x.trim()) + .toSorted() + : undefined, ) + .catch(() => undefined) + const id = roots?.[0] if (!id) continue projectID = id diff --git a/packages/opencode/src/util/git.ts b/packages/opencode/src/util/git.ts new file mode 100644 index 0000000000..d5e4929333 --- /dev/null +++ b/packages/opencode/src/util/git.ts @@ -0,0 +1,16 @@ +import { $ } from "bun" + +function env() { + return { + ...process.env, + GIT_TERMINAL_PROMPT: "0", + GIT_ASKPASS: "echo", + GIT_PAGER: "cat", + PAGER: "", + } +} + +export async function gitText(args: string[], cwd: string): Promise { + const input = new Response("") + return $`git ${args} < ${input}`.env(env()).cwd(cwd).quiet().nothrow().text() +}