commit 1
This commit is contained in:
		
							
								
								
									
										6
									
								
								.devcontainer/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.devcontainer/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					FROM mcr.microsoft.com/devcontainers/go:1-1.21-bullseye
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Install Magefile from GitHub release
 | 
				
			||||||
 | 
					ARG MAGE_VERSION=1.15.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN wget -q https://github.com/magefile/mage/releases/download/v${MAGE_VERSION}/mage_${MAGE_VERSION}_Linux-64bit.tar.gz -O - | tar -xz -C /usr/local/bin
 | 
				
			||||||
							
								
								
									
										24
									
								
								.devcontainer/devcontainer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								.devcontainer/devcontainer.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					// For format details, see https://aka.ms/devcontainer.json. For config options, see the
 | 
				
			||||||
 | 
					// README at: https://github.com/devcontainers/templates/tree/main/src/go
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						"name": "Go",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"build": {
 | 
				
			||||||
 | 
							"dockerfile": "Dockerfile"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Features to add to the dev container. More info: https://containers.dev/features.
 | 
				
			||||||
 | 
						//"features": {},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Use 'forwardPorts' to make a list of ports inside the container available locally.
 | 
				
			||||||
 | 
						// "forwardPorts": [],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Use 'postCreateCommand' to run commands after the container is created.
 | 
				
			||||||
 | 
						// "postCreateCommand": "go version",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Configure tool-specific properties.
 | 
				
			||||||
 | 
						// "customizations": {},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
 | 
				
			||||||
 | 
						// "remoteUser": "root"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					module gitea.layla.gg/layla/gsquash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					go 1.21
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require (
 | 
				
			||||||
 | 
						github.com/davecgh/go-spew v1.1.1 // indirect
 | 
				
			||||||
 | 
						github.com/magefile/mage v1.15.0 // indirect
 | 
				
			||||||
 | 
						github.com/pmezard/go-difflib v1.0.0 // indirect
 | 
				
			||||||
 | 
						github.com/stretchr/testify v1.8.4 // indirect
 | 
				
			||||||
 | 
						gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										11
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 | 
				
			||||||
 | 
					github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
				
			||||||
 | 
					github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
 | 
				
			||||||
 | 
					github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
 | 
				
			||||||
 | 
					github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
				
			||||||
 | 
					github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
				
			||||||
 | 
					github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
 | 
				
			||||||
 | 
					github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 | 
				
			||||||
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
 | 
					gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 | 
				
			||||||
 | 
					gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 | 
				
			||||||
							
								
								
									
										22
									
								
								magefile.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								magefile.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					//go:build mage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/magefile/mage/sh"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Build builds the binary
 | 
				
			||||||
 | 
					func Build() error {
 | 
				
			||||||
 | 
						return sh.RunV("go", "build", "-o", "gsquash", "main.go")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Install installs the binary
 | 
				
			||||||
 | 
					func Install() error {
 | 
				
			||||||
 | 
						return sh.RunV("go", "install")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Test runs the tests
 | 
				
			||||||
 | 
					func Test() error {
 | 
				
			||||||
 | 
						return sh.RunV("go", "test", "./...")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user