vcs.ts 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import { BusEvent } from "@/bus/bus-event"
  2. import { Bus } from "@/bus"
  3. import { $ } from "bun"
  4. import path from "path"
  5. import z from "zod"
  6. import { Log } from "@/util/log"
  7. import { Instance } from "./instance"
  8. import { FileWatcher } from "@/file/watcher"
  9. const log = Log.create({ service: "vcs" })
  10. export namespace Vcs {
  11. export const Event = {
  12. BranchUpdated: BusEvent.define(
  13. "vcs.branch.updated",
  14. z.object({
  15. branch: z.string().optional(),
  16. }),
  17. ),
  18. }
  19. export const Info = z
  20. .object({
  21. branch: z.string(),
  22. })
  23. .meta({
  24. ref: "VcsInfo",
  25. })
  26. export type Info = z.infer<typeof Info>
  27. async function currentBranch() {
  28. return $`git rev-parse --abbrev-ref HEAD`
  29. .quiet()
  30. .nothrow()
  31. .cwd(Instance.worktree)
  32. .text()
  33. .then((x) => x.trim())
  34. .catch(() => undefined)
  35. }
  36. const state = Instance.state(
  37. async () => {
  38. if (Instance.project.vcs !== "git") {
  39. return { branch: async () => undefined, unsubscribe: undefined }
  40. }
  41. let current = await currentBranch()
  42. log.info("initialized", { branch: current })
  43. const unsubscribe = Bus.subscribe(FileWatcher.Event.Updated, async (evt) => {
  44. if (evt.properties.file.endsWith("HEAD")) return
  45. const next = await currentBranch()
  46. if (next !== current) {
  47. log.info("branch changed", { from: current, to: next })
  48. current = next
  49. Bus.publish(Event.BranchUpdated, { branch: next })
  50. }
  51. })
  52. return {
  53. branch: async () => current,
  54. unsubscribe,
  55. }
  56. },
  57. async (state) => {
  58. state.unsubscribe?.()
  59. },
  60. )
  61. export async function init() {
  62. return state()
  63. }
  64. export async function branch() {
  65. return await state().then((s) => s.branch())
  66. }
  67. }