No One Can Stop Me Now
This commit is contained in:
144
services/setec-manager/internal/deploy/git.go
Normal file
144
services/setec-manager/internal/deploy/git.go
Normal file
@@ -0,0 +1,144 @@
|
||||
package deploy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// CommitInfo holds metadata for a single git commit.
|
||||
type CommitInfo struct {
|
||||
Hash string
|
||||
Author string
|
||||
Date string
|
||||
Message string
|
||||
}
|
||||
|
||||
// Clone clones a git repository into dest, checking out the given branch.
|
||||
func Clone(repo, branch, dest string) (string, error) {
|
||||
git, err := exec.LookPath("git")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("git not found: %w", err)
|
||||
}
|
||||
|
||||
args := []string{"clone", "--branch", branch, "--progress", repo, dest}
|
||||
out, err := exec.Command(git, args...).CombinedOutput()
|
||||
if err != nil {
|
||||
return string(out), fmt.Errorf("git clone: %s: %w", strings.TrimSpace(string(out)), err)
|
||||
}
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
// Pull performs a fast-forward-only pull in the given directory.
|
||||
func Pull(dir string) (string, error) {
|
||||
git, err := exec.LookPath("git")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("git not found: %w", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(git, "pull", "--ff-only")
|
||||
cmd.Dir = dir
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return string(out), fmt.Errorf("git pull: %s: %w", strings.TrimSpace(string(out)), err)
|
||||
}
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
// CurrentCommit returns the hash and message of the latest commit in dir.
|
||||
func CurrentCommit(dir string) (hash string, message string, err error) {
|
||||
git, err := exec.LookPath("git")
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("git not found: %w", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(git, "log", "--oneline", "-1")
|
||||
cmd.Dir = dir
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("git log: %w", err)
|
||||
}
|
||||
|
||||
line := strings.TrimSpace(string(out))
|
||||
if line == "" {
|
||||
return "", "", fmt.Errorf("git log: no commits found")
|
||||
}
|
||||
|
||||
parts := strings.SplitN(line, " ", 2)
|
||||
hash = parts[0]
|
||||
if len(parts) > 1 {
|
||||
message = parts[1]
|
||||
}
|
||||
return hash, message, nil
|
||||
}
|
||||
|
||||
// GetBranch returns the current branch name for the repository in dir.
|
||||
func GetBranch(dir string) (string, error) {
|
||||
git, err := exec.LookPath("git")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("git not found: %w", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(git, "rev-parse", "--abbrev-ref", "HEAD")
|
||||
cmd.Dir = dir
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("git rev-parse: %w", err)
|
||||
}
|
||||
return strings.TrimSpace(string(out)), nil
|
||||
}
|
||||
|
||||
// HasChanges returns true if the working tree in dir has uncommitted changes.
|
||||
func HasChanges(dir string) (bool, error) {
|
||||
git, err := exec.LookPath("git")
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("git not found: %w", err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(git, "status", "--porcelain")
|
||||
cmd.Dir = dir
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("git status: %w", err)
|
||||
}
|
||||
return strings.TrimSpace(string(out)) != "", nil
|
||||
}
|
||||
|
||||
// Log returns the last n commits from the repository in dir.
|
||||
func Log(dir string, n int) ([]CommitInfo, error) {
|
||||
git, err := exec.LookPath("git")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("git not found: %w", err)
|
||||
}
|
||||
|
||||
// Use a delimiter unlikely to appear in commit messages.
|
||||
const sep = "||SETEC||"
|
||||
format := fmt.Sprintf("%%h%s%%an%s%%ai%s%%s", sep, sep, sep)
|
||||
|
||||
cmd := exec.Command(git, "log", fmt.Sprintf("-n%d", n), fmt.Sprintf("--format=%s", format))
|
||||
cmd.Dir = dir
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("git log: %w", err)
|
||||
}
|
||||
|
||||
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
|
||||
var commits []CommitInfo
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
parts := strings.SplitN(line, sep, 4)
|
||||
if len(parts) < 4 {
|
||||
continue
|
||||
}
|
||||
commits = append(commits, CommitInfo{
|
||||
Hash: parts[0],
|
||||
Author: parts[1],
|
||||
Date: parts[2],
|
||||
Message: parts[3],
|
||||
})
|
||||
}
|
||||
return commits, nil
|
||||
}
|
||||
Reference in New Issue
Block a user