feat: initial commit of Git Automation CLI

- Add comprehensive Git workflow automation tools
- Include branch management utilities
- Add commit helpers with conventional commit support
- Implement GitHub integration for PR management
- Add configuration management system
- Include comprehensive test coverage
- Add professional documentation and examples
This commit is contained in:
Dev
2025-09-11 17:02:12 +03:00
commit 15bbfdcda2
27 changed files with 5727 additions and 0 deletions

125
internal/git/git.go Normal file
View File

@@ -0,0 +1,125 @@
package git
import (
"bytes"
"context"
"os/exec"
"strings"
)
func run(ctx context.Context, args ...string) (string, error) {
cmd := exec.CommandContext(ctx, "git", args...)
var out bytes.Buffer
var errb bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &errb
if err := cmd.Run(); err != nil {
if errb.Len() > 0 {
return "", fmtError(errb.String())
}
return "", err
}
return strings.TrimSpace(out.String()), nil
}
// Run is a public version of run for use in other packages
func Run(ctx context.Context, args ...string) (string, error) {
return run(ctx, args...)
}
func Fetch(ctx context.Context) error {
_, err := run(ctx, "fetch", "--prune")
return err
}
func RebaseOntoTracking(ctx context.Context) error {
branch, err := CurrentBranch(ctx)
if err != nil {
return err
}
up, err := UpstreamFor(ctx, branch)
if err != nil {
return err
}
_, err = run(ctx, "rebase", up)
return err
}
func PushCurrent(ctx context.Context, forceWithLease bool) error {
args := []string{"push"}
if forceWithLease {
args = append(args, "--force-with-lease")
}
args = append(args, "--set-upstream", "origin", "HEAD")
_, err := run(ctx, args...)
return err
}
func LocalBranches(ctx context.Context) ([]string, error) {
out, err := run(ctx, "branch", "--format=%(refname:short)")
if err != nil {
return nil, err
}
if out == "" {
return nil, nil
}
return strings.Split(out, "\n"), nil
}
func DeleteBranch(ctx context.Context, name string) error {
_, err := run(ctx, "branch", "-D", name)
return err
}
func CurrentBranch(ctx context.Context) (string, error) {
return run(ctx, "rev-parse", "--abbrev-ref", "HEAD")
}
func UpstreamFor(ctx context.Context, branch string) (string, error) {
return run(ctx, "rev-parse", "--abbrev-ref", branch+"@{upstream}")
}
func CreateBranch(ctx context.Context, name string) error {
_, err := run(ctx, "checkout", "-b", name)
return err
}
func SwitchBranch(ctx context.Context, name string) error {
_, err := run(ctx, "checkout", name)
return err
}
func IsCleanWorkingDir(ctx context.Context) (bool, error) {
out, err := run(ctx, "status", "--porcelain")
if err != nil {
return false, err
}
return out == "", nil
}
func AddAll(ctx context.Context) error {
_, err := run(ctx, "add", "-A")
return err
}
func Commit(ctx context.Context, message string) error {
_, err := run(ctx, "commit", "-m", message)
return err
}
func fmtError(s string) error {
return &gitError{msg: strings.TrimSpace(s)}
}
type gitError struct {
msg string
}
func (e *gitError) Error() string {
return e.msg
}
// GetRemoteURL returns the URL of the specified remote
func GetRemoteURL(ctx context.Context, remote string) (string, error) {
return run(ctx, "remote", "get-url", remote)
}