mirror of
https://github.com/sst/opencode.git
synced 2025-12-23 10:11:41 +00:00
77 lines
1.8 KiB
TypeScript
77 lines
1.8 KiB
TypeScript
import { $ } from "bun"
|
|
import path from "path"
|
|
import z from "zod"
|
|
import { Log } from "@/util/log"
|
|
import { Bus } from "@/bus"
|
|
import { Instance } from "./instance"
|
|
import { FileWatcher } from "@/file/watcher"
|
|
|
|
const log = Log.create({ service: "vcs" })
|
|
|
|
export namespace Vcs {
|
|
export const Event = {
|
|
BranchUpdated: Bus.event(
|
|
"vcs.branch.updated",
|
|
z.object({
|
|
branch: z.string().optional(),
|
|
}),
|
|
),
|
|
}
|
|
|
|
export const Info = z
|
|
.object({
|
|
branch: z.string(),
|
|
})
|
|
.meta({
|
|
ref: "VcsInfo",
|
|
})
|
|
export type Info = z.infer<typeof Info>
|
|
|
|
async function currentBranch() {
|
|
return $`git rev-parse --abbrev-ref HEAD`
|
|
.quiet()
|
|
.nothrow()
|
|
.cwd(Instance.worktree)
|
|
.text()
|
|
.then((x) => x.trim())
|
|
.catch(() => undefined)
|
|
}
|
|
|
|
const state = Instance.state(
|
|
async () => {
|
|
const vcsDir = Instance.project.vcsDir
|
|
if (Instance.project.vcs !== "git" || !vcsDir) {
|
|
return { branch: async () => undefined, unsubscribe: undefined }
|
|
}
|
|
let current = await currentBranch()
|
|
log.info("initialized", { branch: current })
|
|
|
|
const head = path.join(vcsDir, "HEAD")
|
|
const unsubscribe = Bus.subscribe(FileWatcher.Event.Updated, async (evt) => {
|
|
if (evt.properties.file !== head) return
|
|
const next = await currentBranch()
|
|
if (next !== current) {
|
|
log.info("branch changed", { from: current, to: next })
|
|
current = next
|
|
Bus.publish(Event.BranchUpdated, { branch: next })
|
|
}
|
|
})
|
|
|
|
return {
|
|
branch: async () => current,
|
|
unsubscribe,
|
|
}
|
|
},
|
|
async (state) => {
|
|
state.unsubscribe?.()
|
|
},
|
|
)
|
|
|
|
export async function init() {
|
|
return state()
|
|
}
|
|
|
|
export async function branch() {
|
|
return await state().then((s) => s.branch())
|
|
}
|
|
}
|