Use go-git for native git operations

Replace exec-based git calls with go-git/v6 library for ~5.6x
speedup over shell version. Only pgrep remains as external call.
This commit is contained in:
2025-12-18 05:11:34 +01:00
parent 135bbf68f1
commit f1ca1ccaa0
4 changed files with 383 additions and 43 deletions

77
main.go
View File

@ -10,6 +10,7 @@ import (
"regexp"
"strings"
"github.com/go-git/go-git/v6"
"golang.org/x/sys/unix"
)
@ -94,10 +95,7 @@ func main() {
termWidth := getTerminalWidth() - statuslineWidthOffset
// Calculate padding
padding := termWidth - len(leftVisible) - len(rightVisible)
if padding < 1 {
padding = 1
}
padding := max(termWidth-len(leftVisible)-len(rightVisible), 1)
// Output with padding
fmt.Printf("%s%s%s", left, strings.Repeat(" ", padding), right)
@ -129,64 +127,59 @@ func getGiteaStatus() string {
}
func getGitInfo(cwd string) string {
// Change to the directory
oldDir, _ := os.Getwd()
if err := os.Chdir(cwd); err != nil {
// Open the repository (searches up from cwd)
repo, err := git.PlainOpenWithOptions(cwd, &git.PlainOpenOptions{
DetectDotGit: true,
})
if err != nil {
return ""
}
defer os.Chdir(oldDir)
// Check if we're in a git repo
cmd := exec.Command("git", "rev-parse", "--git-dir")
cmd.Stderr = nil
if err := cmd.Run(); err != nil {
// Get HEAD reference
head, err := repo.Head()
if err != nil {
return ""
}
// Get branch name
branch := ""
cmd = exec.Command("git", "symbolic-ref", "--short", "HEAD")
cmd.Stderr = nil
if out, err := cmd.Output(); err == nil {
branch = strings.TrimSpace(string(out))
var branch string
if head.Name().IsBranch() {
branch = head.Name().Short()
} else {
// Fallback to short SHA
cmd = exec.Command("git", "rev-parse", "--short", "HEAD")
cmd.Stderr = nil
if out, err := cmd.Output(); err == nil {
branch = strings.TrimSpace(string(out))
}
}
if branch == "" {
return ""
// Detached HEAD - use short hash
branch = head.Hash().String()[:7]
}
// Check if working tree is dirty
isDirty := false
// Check unstaged changes
cmd = exec.Command("git", "diff", "--no-ext-diff", "--quiet", "--exit-code", "--no-optional-locks")
cmd.Stderr = nil
if err := cmd.Run(); err != nil {
isDirty = true
worktree, err := repo.Worktree()
if err != nil {
return fmt.Sprintf(" git:(%s)", branch)
}
// Check staged changes
if !isDirty {
cmd = exec.Command("git", "diff-index", "--cached", "--quiet", "HEAD", "--no-optional-locks")
cmd.Stderr = nil
if err := cmd.Run(); err != nil {
isDirty = true
}
status, err := worktree.Status()
if err != nil {
return fmt.Sprintf(" git:(%s)", branch)
}
if isDirty {
if !status.IsClean() {
return fmt.Sprintf(" git:(%s) ✗", branch)
}
return fmt.Sprintf(" git:(%s)", branch)
}
func findGitRoot(path string) string {
for {
if _, err := os.Stat(filepath.Join(path, ".git")); err == nil {
return path
}
parent := filepath.Dir(path)
if parent == path {
return ""
}
path = parent
}
}
func getTerminalWidth() int {
ws, err := unix.IoctlGetWinsize(int(os.Stdout.Fd()), unix.TIOCGWINSZ)
if err != nil {