show current git branch in tui (#4765)

Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
Aiden Cline
2025-11-25 19:39:20 -08:00
committed by GitHub
parent d95f724303
commit 09bc8d9ca4
7 changed files with 193 additions and 2 deletions

View File

@@ -4,11 +4,11 @@ import { Format } from "../format"
import { LSP } from "../lsp"
import { FileWatcher } from "../file/watcher"
import { File } from "../file"
import { Flag } from "../flag/flag"
import { Project } from "./project"
import { Bus } from "../bus"
import { Command } from "../command"
import { Instance } from "./instance"
import { Vcs } from "./vcs"
import { Log } from "@/util/log"
import { ShareNext } from "@/share/share-next"
@@ -21,6 +21,7 @@ export async function InstanceBootstrap() {
await LSP.init()
FileWatcher.init()
File.init()
Vcs.init()
Bus.subscribe(Command.Event.Executed, async (payload) => {
if (payload.properties.name === Command.Default.INIT) {

View File

@@ -0,0 +1,86 @@
import { $ } from "bun"
import { watch, type FSWatcher } from "fs"
import path from "path"
import z from "zod"
import { Log } from "@/util/log"
import { Bus } from "@/bus"
import { Instance } from "./instance"
const log = Log.create({ service: "vcs" })
export namespace Vcs {
export const Event = {
Changed: Bus.event(
"vcs.changed",
z.object({
branch: z.string().optional(),
}),
),
}
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, watcher: undefined }
}
let current = await currentBranch()
log.info("initialized", { branch: current })
const gitDir = await $`git rev-parse --git-dir`
.quiet()
.nothrow()
.cwd(Instance.worktree)
.text()
.then((x) => x.trim())
.catch(() => undefined)
if (!gitDir) {
log.warn("failed to resolve git directory")
return { branch: async () => current, watcher: undefined }
}
const gitHead = path.join(gitDir, "HEAD")
let watcher: FSWatcher | undefined
// we should probably centralize file watching (see watcher.ts)
// but parcel still marked experimental rn
try {
watcher = watch(gitHead, async () => {
const next = await currentBranch()
if (next !== current) {
log.info("branch changed", { from: current, to: next })
current = next
Bus.publish(Event.Changed, { branch: next })
}
})
log.info("watching", { path: gitHead })
} catch (e) {
log.warn("failed to watch git HEAD", { error: e })
}
return {
branch: async () => current,
watcher,
}
},
async (state) => {
state.watcher?.close()
},
)
export async function init() {
return state()
}
export async function branch() {
return await state().then((s) => s.branch())
}
}