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:
125
internal/git/git.go
Normal file
125
internal/git/git.go
Normal 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)
|
||||
}
|
Reference in New Issue
Block a user