# Git Interface for Go

A comprehensive Go interface for Git operations that provides a clean, type-safe API for interacting with Git repositories.

## Features

- **Complete Git Operations**: Supports all major Git operations including repository management, commits, branches, remotes, tags, and more
- **Type-Safe API**: Strongly typed interfaces and structs for better code safety
- **Context Support**: All operations support context for cancellation and timeouts
- **Error Handling**: Comprehensive error handling with detailed error messages
- **Flexible Configuration**: Configurable timeouts and environment variables
- **Easy to Use**: Simple and intuitive API design

## Installation

The Git interface is part of the `github.com/iomodo/staff` module. No additional dependencies are required beyond the standard library.

## Quick Start

```go
package main

import (
    "context"
    "fmt"
    "log"
    
    "github.com/iomodo/staff/git"
)

func main() {
    ctx := context.Background()
    
    // Create a Git instance
    git := git.DefaultGit("/path/to/your/repo")
    
    // Open an existing repository
    if err := git.Open(ctx, "/path/to/your/repo"); err != nil {
        log.Fatalf("Failed to open repository: %v", err)
    }
    
    // Get repository status
    status, err := git.Status(ctx)
    if err != nil {
        log.Fatalf("Failed to get status: %v", err)
    }
    
    fmt.Printf("Current branch: %s\n", status.Branch)
    fmt.Printf("Repository is clean: %t\n", status.IsClean)
}
```

## Core Interface

### GitInterface

The main interface that defines all Git operations:

```go
type GitInterface interface {
    // Repository operations
    Init(ctx context.Context, path string) error
    Clone(ctx context.Context, url, path string) error
    IsRepository(ctx context.Context, path string) (bool, error)
    
    // Status and information
    Status(ctx context.Context) (*Status, error)
    Log(ctx context.Context, options LogOptions) ([]Commit, error)
    Show(ctx context.Context, ref string) (*Commit, error)
    
    // Branch operations
    ListBranches(ctx context.Context) ([]Branch, error)
    CreateBranch(ctx context.Context, name string, startPoint string) error
    Checkout(ctx context.Context, ref string) error
    DeleteBranch(ctx context.Context, name string, force bool) error
    GetCurrentBranch(ctx context.Context) (string, error)
    
    // Commit operations
    Add(ctx context.Context, paths []string) error
    AddAll(ctx context.Context) error
    Commit(ctx context.Context, message string, options CommitOptions) error
    
    // Remote operations
    ListRemotes(ctx context.Context) ([]Remote, error)
    AddRemote(ctx context.Context, name, url string) error
    RemoveRemote(ctx context.Context, name string) error
    Fetch(ctx context.Context, remote string, options FetchOptions) error
    Pull(ctx context.Context, remote, branch string) error
    Push(ctx context.Context, remote, branch string, options PushOptions) error
    
    // Merge operations
    Merge(ctx context.Context, ref string, options MergeOptions) error
    MergeBase(ctx context.Context, ref1, ref2 string) (string, error)
    
    // Configuration
    GetConfig(ctx context.Context, key string) (string, error)
    SetConfig(ctx context.Context, key, value string) error
    GetUserConfig(ctx context.Context) (*UserConfig, error)
    SetUserConfig(ctx context.Context, config UserConfig) error
}
```

## Data Structures

### Status

Represents the current state of the repository:

```go
type Status struct {
    Branch     string
    IsClean    bool
    Staged     []FileStatus
    Unstaged   []FileStatus
    Untracked  []string
    Conflicts  []string
}
```

### Commit

Represents a Git commit:

```go
type Commit struct {
    Hash      string
    Author    Author
    Committer Author
    Message   string
    Parents   []string
    Timestamp time.Time
    Files     []CommitFile
}
```

### Branch

Represents a Git branch:

```go
type Branch struct {
    Name      string
    IsCurrent bool
    IsRemote  bool
    Commit    string
    Message   string
}
```

## Usage Examples

### Repository Management

```go
// Initialize a new repository
git := git.DefaultGit("/path/to/new/repo")
if err := git.Init(ctx, "/path/to/new/repo"); err != nil {
    log.Fatal(err)
}

// Clone a repository
if err := git.Clone(ctx, "https://github.com/user/repo.git", "/path/to/clone"); err != nil {
    log.Fatal(err)
}
```

### Basic Git Workflow

```go
// Stage files
if err := git.Add(ctx, []string{"file1.txt", "file2.txt"}); err != nil {
    log.Fatal(err)
}

// Or stage all changes
if err := git.AddAll(ctx); err != nil {
    log.Fatal(err)
}

// Commit changes
commitOptions := git.CommitOptions{
    AllowEmpty: false,
}
if err := git.Commit(ctx, "Add new feature", commitOptions); err != nil {
    log.Fatal(err)
}
```

### Branch Operations

```go
// List all branches
branches, err := git.ListBranches(ctx)
if err != nil {
    log.Fatal(err)
}

for _, branch := range branches {
    fmt.Printf("Branch: %s (current: %t)\n", branch.Name, branch.IsCurrent)
}

// Create a new branch
if err := git.CreateBranch(ctx, "feature/new-feature", ""); err != nil {
    log.Fatal(err)
}

// Switch to a branch
if err := git.Checkout(ctx, "feature/new-feature"); err != nil {
    log.Fatal(err)
}

// Get current branch
currentBranch, err := git.GetCurrentBranch(ctx)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Current branch: %s\n", currentBranch)
```

### Remote Operations

```go
// Add a remote
if err := git.AddRemote(ctx, "origin", "https://github.com/user/repo.git"); err != nil {
    log.Fatal(err)
}

// List remotes
remotes, err := git.ListRemotes(ctx)
if err != nil {
    log.Fatal(err)
}

for _, remote := range remotes {
    fmt.Printf("Remote: %s -> %s\n", remote.Name, remote.URL)
}

// Fetch from remote
fetchOptions := git.FetchOptions{
    All:  true,
    Tags: true,
}
if err := git.Fetch(ctx, "", fetchOptions); err != nil {
    log.Fatal(err)
}

// Push to remote
pushOptions := git.PushOptions{
    SetUpstream: true,
}
if err := git.Push(ctx, "origin", "main", pushOptions); err != nil {
    log.Fatal(err)
}
```

### Configuration

```go
// Get user configuration
userConfig, err := git.GetUserConfig(ctx)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("User: %s <%s>\n", userConfig.Name, userConfig.Email)

// Set user configuration
newConfig := git.UserConfig{
    Name:  "John Doe",
    Email: "john@example.com",
}
if err := git.SetUserConfig(ctx, newConfig); err != nil {
    log.Fatal(err)
}

// Get/set custom config
value, err := git.GetConfig(ctx, "core.editor")
if err != nil {
    log.Fatal(err)
}

if err := git.SetConfig(ctx, "core.editor", "vim"); err != nil {
    log.Fatal(err)
}
```

## Error Handling

The Git interface provides detailed error information through the `GitError` type:

```go
if err := git.Commit(ctx, "Invalid commit", git.CommitOptions{}); err != nil {
    if gitErr, ok := err.(*git.GitError); ok {
        fmt.Printf("Git command '%s' failed: %v\n", gitErr.Command, gitErr.Err)
        fmt.Printf("Output: %s\n", gitErr.Output)
    }
}
```

## Configuration

You can customize the Git instance with specific configuration:

```go
config := git.GitConfig{
    Timeout: 60 * time.Second,
    Env: map[string]string{
        "GIT_AUTHOR_NAME":  "Custom Author",
        "GIT_AUTHOR_EMAIL": "author@example.com",
    },
}

git := git.NewGit("/path/to/repo", config)
```

## Thread Safety

The Git interface is not thread-safe. If you need to use it from multiple goroutines, you should either:

1. Use separate Git instances for each goroutine
2. Use a mutex to synchronize access
3. Use channels to serialize operations

## Requirements

- Go 1.24.4 or later
- Git installed and available in PATH
- Appropriate permissions to access the repository

## License

This code is part of the `github.com/iomodo/staff` project and follows the same license terms. 