package daemonrunner import ( "context" "fmt" "os/exec" "strings" "time" ) // isGitRepo checks if we're in a git repository func isGitRepo() bool { cmd := exec.Command("git", "rev-parse", "--git-dir") return cmd.Run() == nil } // gitHasUpstream checks if the current branch has an upstream configured func gitHasUpstream() bool { cmd := exec.Command("git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}") return cmd.Run() == nil } // gitHasChanges checks if the specified file has uncommitted changes func gitHasChanges(ctx context.Context, filePath string) (bool, error) { cmd := exec.CommandContext(ctx, "git", "status", "--porcelain", filePath) output, err := cmd.Output() if err != nil { return false, fmt.Errorf("git status failed: %w", err) } return len(strings.TrimSpace(string(output))) > 0, nil } // gitCommit commits the specified file func gitCommit(ctx context.Context, filePath string, message string) error { // Stage the file addCmd := exec.CommandContext(ctx, "git", "add", filePath) if err := addCmd.Run(); err != nil { return fmt.Errorf("git add failed: %w", err) } // Generate message if not provided if message == "" { message = fmt.Sprintf("bd sync: %s", time.Now().Format("2006-01-02 15:04:05")) } // Commit commitCmd := exec.CommandContext(ctx, "git", "commit", "-m", message) output, err := commitCmd.CombinedOutput() if err != nil { return fmt.Errorf("git commit failed: %w\n%s", err, output) } return nil } // gitPull pulls from the current branch's upstream func gitPull(ctx context.Context) error { // Get current branch name branchCmd := exec.CommandContext(ctx, "git", "rev-parse", "--abbrev-ref", "HEAD") branchOutput, err := branchCmd.Output() if err != nil { return fmt.Errorf("failed to get current branch: %w", err) } branch := strings.TrimSpace(string(branchOutput)) // Get remote name for current branch (usually "origin") remoteCmd := exec.CommandContext(ctx, "git", "config", "--get", fmt.Sprintf("branch.%s.remote", branch)) remoteOutput, err := remoteCmd.Output() if err != nil { // If no remote configured, default to "origin" remoteOutput = []byte("origin\n") } remote := strings.TrimSpace(string(remoteOutput)) // Pull with explicit remote and branch cmd := exec.CommandContext(ctx, "git", "pull", remote, branch) output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("git pull failed: %w\n%s", err, output) } return nil } // gitPush pushes to the current branch's upstream func gitPush(ctx context.Context) error { cmd := exec.CommandContext(ctx, "git", "push") output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("git push failed: %w\n%s", err, output) } return nil }