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