| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- import { BusEvent } from "@/bus/bus-event"
- import { Bus } from "@/bus"
- import { $ } from "bun"
- import path from "path"
- import z from "zod"
- import { Log } from "@/util/log"
- import { Instance } from "./instance"
- import { FileWatcher } from "@/file/watcher"
- const log = Log.create({ service: "vcs" })
- export namespace Vcs {
- export const Event = {
- BranchUpdated: BusEvent.define(
- "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 () => {
- if (Instance.project.vcs !== "git") {
- return { branch: async () => undefined, unsubscribe: undefined }
- }
- let current = await currentBranch()
- log.info("initialized", { branch: current })
- const unsubscribe = Bus.subscribe(FileWatcher.Event.Updated, async (evt) => {
- if (evt.properties.file.endsWith("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())
- }
- }
|