Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions daemon/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package daemon

import (
"context"
"os"
"os/exec"
"strings"
"time"
Expand All @@ -16,6 +17,16 @@ type GitInfo struct {
IsRepo bool
}

// gitCmd creates a git command that won't acquire optional locks.
// This prevents conflicts with user-initiated git operations when the daemon
// polls git status in the background. Uses GIT_OPTIONAL_LOCKS=0 which is
// equivalent to passing --no-optional-locks to every git command.
func gitCmd(ctx context.Context, args ...string) *exec.Cmd {
cmd := exec.CommandContext(ctx, "git", args...)
cmd.Env = append(os.Environ(), "GIT_OPTIONAL_LOCKS=0")
return cmd
}

// GetGitInfo returns git branch and dirty status for a directory.
// It uses the native git CLI which is significantly faster and more memory-efficient
// than the pure-Go go-git implementation, especially on large repositories.
Expand All @@ -28,19 +39,19 @@ func GetGitInfo(workingDir string) GitInfo {
defer cancel()

// Check if this is a git repo
if err := exec.CommandContext(ctx, "git", "-C", workingDir, "rev-parse", "--git-dir").Run(); err != nil {
if err := gitCmd(ctx, "-C", workingDir, "rev-parse", "--git-dir").Run(); err != nil {
return GitInfo{}
}

info := GitInfo{IsRepo: true}

// Get branch name from HEAD
if out, err := exec.CommandContext(ctx, "git", "-C", workingDir, "rev-parse", "--abbrev-ref", "HEAD").Output(); err == nil {
if out, err := gitCmd(ctx, "-C", workingDir, "rev-parse", "--abbrev-ref", "HEAD").Output(); err == nil {
info.Branch = strings.TrimSpace(string(out))
}

// Check dirty status via porcelain output (empty = clean)
if out, err := exec.CommandContext(ctx, "git", "-C", workingDir, "status", "--porcelain").Output(); err == nil {
if out, err := gitCmd(ctx, "-C", workingDir, "status", "--porcelain").Output(); err == nil {
info.Dirty = len(strings.TrimSpace(string(out))) > 0
}

Expand Down