commit 1
This commit is contained in:
19
git/cmd.go
Normal file
19
git/cmd.go
Normal file
@ -0,0 +1,19 @@
|
||||
package git
|
||||
|
||||
import "os/exec"
|
||||
|
||||
// Execute runs a git command and returns the stdout
|
||||
func (g *Git) Execute(args ...string) (string, error) {
|
||||
|
||||
cmd := exec.Command("git", args...)
|
||||
if g.WorkingDir != "" {
|
||||
cmd.Dir = g.WorkingDir
|
||||
}
|
||||
|
||||
// Run and return stdout
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(out), nil
|
||||
}
|
28
git/cmd_test.go
Normal file
28
git/cmd_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestExecute runs a unit test with testify for git.Execute
|
||||
func TestExecute(t *testing.T) {
|
||||
require := require.New(t)
|
||||
assert := assert.New(t)
|
||||
|
||||
// Create a new git
|
||||
git := NewGit(&NewGitInput{
|
||||
Executable: "git",
|
||||
})
|
||||
|
||||
// Run the command
|
||||
out, err := git.Execute("version")
|
||||
|
||||
// Assert that the command ran successfully
|
||||
require.NoError(err)
|
||||
|
||||
// Assert that the output contains 'git version'
|
||||
assert.Contains(out, "git version")
|
||||
}
|
36
git/commit.go
Normal file
36
git/commit.go
Normal file
@ -0,0 +1,36 @@
|
||||
package git
|
||||
|
||||
import "strconv"
|
||||
|
||||
// GetHash returns the commit hash for the current HEAD
|
||||
func (g *Git) GetHash() (string, error) {
|
||||
|
||||
out, err := g.Execute("rev-parse", "HEAD")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetCommitRemote returns the commit hash for the current HEAD on the remote
|
||||
func (g *Git) GetCommitRemote() (string, error) {
|
||||
|
||||
out, err := g.Execute("ls-remote", "origin", "HEAD")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GetCommitsAhead returns the number of commits ahead of main
|
||||
func (g *Git) GetCommitsAhead() (int, error) {
|
||||
|
||||
out, err := g.Execute("rev-list", "--count", "HEAD", "^"+g.MainBranch)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return strconv.Atoi(out)
|
||||
}
|
36
git/git.go
Normal file
36
git/git.go
Normal file
@ -0,0 +1,36 @@
|
||||
package git
|
||||
|
||||
type Git struct {
|
||||
// Executable is the path to the git executable
|
||||
Executable string
|
||||
// WorkingDir is the path to the working directory
|
||||
WorkingDir string
|
||||
// MainBranch is the name of the main branch
|
||||
MainBranch string
|
||||
}
|
||||
|
||||
// NewGitInput is the input type for NewGit
|
||||
type NewGitInput struct {
|
||||
// Executable is the path to the git executable
|
||||
Executable string
|
||||
// WorkingDir is the path to the working directory
|
||||
WorkingDir *string
|
||||
// MainBranch is the name of the main branch
|
||||
MainBranch string
|
||||
}
|
||||
|
||||
// NewGit creates a new Git
|
||||
func NewGit(input *NewGitInput) *Git {
|
||||
git := &Git{
|
||||
Executable: input.Executable,
|
||||
}
|
||||
|
||||
if git.Executable == "" {
|
||||
git.Executable = "git"
|
||||
}
|
||||
if git.MainBranch == "" {
|
||||
git.MainBranch = "main"
|
||||
}
|
||||
|
||||
return git
|
||||
}
|
23
git/pull.go
Normal file
23
git/pull.go
Normal file
@ -0,0 +1,23 @@
|
||||
package git
|
||||
|
||||
// Pull pulls the latest changes from the remote
|
||||
func (g *Git) Pull() error {
|
||||
|
||||
_, err := g.Execute("pull")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// PullMain pulls the latest changes from the remote main branch
|
||||
func (g *Git) PullMain() error {
|
||||
|
||||
_, err := g.Execute("pull", "origin", g.MainBranch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
72
git/squash.go
Normal file
72
git/squash.go
Normal file
@ -0,0 +1,72 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SquashInput contains the input for Squash
|
||||
type SquashInput struct {
|
||||
Message *string
|
||||
}
|
||||
|
||||
// Squash squashes everything every commit ahead of main into one commit
|
||||
func (g *Git) Squash(input SquashInput) error {
|
||||
|
||||
// Get the current commit hash
|
||||
hash, err := g.GetHash()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the commit hash on the remote
|
||||
remote, err := g.GetCommitRemote()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the hashes are the same, there's nothing to squash
|
||||
if hash == remote {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get the number of commits ahead of main
|
||||
commits, err := g.GetCommitsAhead()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
message := ""
|
||||
|
||||
if input.Message != nil {
|
||||
message = *input.Message
|
||||
} else {
|
||||
|
||||
// Get array of commit messages
|
||||
out, err := g.Execute("log", "--pretty=format:%s", "-n", strconv.Itoa(commits))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
messages := strings.Split(out, "\n")
|
||||
|
||||
// Add `-` to each message
|
||||
for i, m := range messages {
|
||||
messages[i] = "- " + m
|
||||
}
|
||||
|
||||
// Join the messages
|
||||
message = strings.Join(messages, "\n")
|
||||
|
||||
// Add header comment
|
||||
message = "# Squashed " + strconv.Itoa(commits) + " commits\n\n" + message
|
||||
|
||||
}
|
||||
|
||||
// Squash the current commit into the previous commits
|
||||
_, err = g.Execute("rebase", "-i", hash+"~"+strconv.Itoa(commits), "-x", "git commit --amend -m \""+message+"\" ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user