118 lines
3.0 KiB
Go
118 lines
3.0 KiB
Go
package git
|
|
|
|
import (
|
|
"fmt"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// Run executes a git command in the given directory and returns combined output.
|
|
func Run(dir string, args ...string) (string, error) {
|
|
cmd := exec.Command("git", args...)
|
|
cmd.Dir = dir
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return "", fmt.Errorf("git %s: %w\n%s", strings.Join(args, " "), err, out)
|
|
}
|
|
return strings.TrimSpace(string(out)), nil
|
|
}
|
|
|
|
// RepoRoot returns the root of the git repository.
|
|
func RepoRoot(dir string) (string, error) {
|
|
return Run(dir, "rev-parse", "--show-toplevel")
|
|
}
|
|
|
|
// Add stages the given paths.
|
|
func Add(dir string, paths ...string) error {
|
|
args := append([]string{"add", "--"}, paths...)
|
|
_, err := Run(dir, args...)
|
|
return err
|
|
}
|
|
|
|
// Commit creates a commit with the given message.
|
|
func Commit(dir, message string) error {
|
|
_, err := Run(dir, "commit", "-m", message)
|
|
return err
|
|
}
|
|
|
|
// Tag creates an annotated tag.
|
|
func Tag(dir, name, message string) error {
|
|
_, err := Run(dir, "tag", "-a", name, "-m", message)
|
|
return err
|
|
}
|
|
|
|
// TagLightweight creates a lightweight tag.
|
|
func TagLightweight(dir, name string) error {
|
|
_, err := Run(dir, "tag", name)
|
|
return err
|
|
}
|
|
|
|
// Push pushes the current branch and all tags to origin.
|
|
func Push(dir string) error {
|
|
_, err := Run(dir, "push", "--follow-tags")
|
|
return err
|
|
}
|
|
|
|
// PushTag pushes a specific tag to origin.
|
|
func PushTag(dir, tag string) error {
|
|
_, err := Run(dir, "push", "origin", tag)
|
|
return err
|
|
}
|
|
|
|
// CurrentBranch returns the current branch name.
|
|
func CurrentBranch(dir string) (string, error) {
|
|
return Run(dir, "rev-parse", "--abbrev-ref", "HEAD")
|
|
}
|
|
|
|
// TagName returns the conventional tag name for a project version.
|
|
// For a single-project repo (projectName == "") it returns "v<version>".
|
|
// For monorepos it returns "<projectName>@v<version>".
|
|
func TagName(projectName, version string) string {
|
|
if projectName == "" {
|
|
return "v" + version
|
|
}
|
|
return projectName + "@v" + version
|
|
}
|
|
|
|
// TagExists returns true if the tag already exists locally.
|
|
func TagExists(dir, tag string) (bool, error) {
|
|
out, err := Run(dir, "tag", "-l", tag)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return strings.TrimSpace(out) == tag, nil
|
|
}
|
|
|
|
// BranchExists returns true if the given local branch exists.
|
|
func BranchExists(dir, branch string) (bool, error) {
|
|
out, err := Run(dir, "branch", "--list", branch)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return strings.TrimSpace(out) != "", nil
|
|
}
|
|
|
|
// CheckoutBranch checks out an existing branch.
|
|
func CheckoutBranch(dir, branch string) error {
|
|
_, err := Run(dir, "checkout", branch)
|
|
return err
|
|
}
|
|
|
|
// CheckoutNewBranch creates and checks out a new branch from the given base.
|
|
func CheckoutNewBranch(dir, branch, base string) error {
|
|
_, err := Run(dir, "checkout", "-B", branch, base)
|
|
return err
|
|
}
|
|
|
|
// PushBranch force-pushes a branch to origin.
|
|
func PushBranch(dir, branch string) error {
|
|
_, err := Run(dir, "push", "--force-with-lease", "origin", branch)
|
|
return err
|
|
}
|
|
|
|
// FetchOrigin fetches from origin.
|
|
func FetchOrigin(dir string) error {
|
|
_, err := Run(dir, "fetch", "origin")
|
|
return err
|
|
}
|