feat: init commit with main func
This commit is contained in:
80
git.go
Normal file
80
git.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// gitRun executes a git command in repoPath, returning a descriptive error
|
||||
// that includes the combined stdout+stderr on failure.
|
||||
func gitRun(repoPath string, args ...string) error {
|
||||
cmd := exec.Command("git", append([]string{"-C", repoPath}, args...)...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("git %s: %w\n%s",
|
||||
strings.Join(args, " "), err, bytes.TrimSpace(out))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// gitOutput executes a git command and returns its stdout as a string.
|
||||
func gitOutput(repoPath string, args ...string) (string, error) {
|
||||
cmd := exec.Command("git", append([]string{"-C", repoPath}, args...)...)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
var stderr []byte
|
||||
if ee, ok := err.(*exec.ExitError); ok {
|
||||
stderr = ee.Stderr
|
||||
}
|
||||
return "", fmt.Errorf("git %s: %w\n%s",
|
||||
strings.Join(args, " "), err, bytes.TrimSpace(stderr))
|
||||
}
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
// GitPull fetches from the remote and rebases the local branch.
|
||||
// Using --autostash ensures any uncommitted changes are preserved across the rebase
|
||||
// (should not normally happen but guards against manual edits).
|
||||
func GitPull(cfg *Config) error {
|
||||
if err := gitRun(cfg.RepoPath, "fetch", "--prune", cfg.RepoRemote); err != nil {
|
||||
return fmt.Errorf("git fetch: %w", err)
|
||||
}
|
||||
if err := gitRun(cfg.RepoPath,
|
||||
"pull", "--rebase", "--autostash",
|
||||
cfg.RepoRemote, cfg.RepoBranch,
|
||||
); err != nil {
|
||||
return fmt.Errorf("git pull --rebase: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GitStatusChanged reports true when the working tree has uncommitted changes.
|
||||
func GitStatusChanged(cfg *Config) (bool, error) {
|
||||
out, err := gitOutput(cfg.RepoPath, "status", "--porcelain")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return strings.TrimSpace(out) != "", nil
|
||||
}
|
||||
|
||||
// GitCommitAndPush stages the dynamic directory, commits with the given message,
|
||||
// and pushes to the configured remote branch.
|
||||
// Author identity is passed via git -c flags to avoid requiring global git config.
|
||||
func GitCommitAndPush(cfg *Config, message string) error {
|
||||
if err := gitRun(cfg.RepoPath, "add", cfg.DynamicDir); err != nil {
|
||||
return fmt.Errorf("git add: %w", err)
|
||||
}
|
||||
if err := gitRun(cfg.RepoPath,
|
||||
"-c", "user.name="+cfg.AuthorName,
|
||||
"-c", "user.email="+cfg.AuthorEmail,
|
||||
"commit", "-m", message,
|
||||
); err != nil {
|
||||
return fmt.Errorf("git commit: %w", err)
|
||||
}
|
||||
if err := gitRun(cfg.RepoPath, "push", cfg.RepoRemote, cfg.RepoBranch); err != nil {
|
||||
return fmt.Errorf("git push: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user