Skip to content

Commit

Permalink
chore: add minimum git version support warning (#886)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrexox authored Dec 6, 2024
1 parent df484d9 commit 9df624c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 32 deletions.
25 changes: 21 additions & 4 deletions internal/git/repository.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package git

import (
"errors"
"fmt"
"os"
"path/filepath"
Expand All @@ -10,17 +11,20 @@ import (
"github.com/spf13/afero"

"github.com/evilmartians/lefthook/internal/log"
"github.com/evilmartians/lefthook/internal/version"
)

const (
minGitVersion = "2.31.0"
stashMessage = "lefthook auto backup"
unstagedPatchName = "lefthook-unstaged.patch"
infoDirMode = 0o775
minStatusLen = 3
)

var (
headBranchRegexp = regexp.MustCompile(`HEAD -> (?P<name>.*)$`)
reHeadBranch = regexp.MustCompile(`HEAD -> (?P<name>.*)$`)
reVersion = regexp.MustCompile(`\d+\.\d+\.\d+`)
cmdPushFilesBase = []string{"git", "diff", "--name-only", "HEAD", "@{push}"}
cmdPushFilesHead = []string{"git", "diff", "--name-only", "HEAD"}
cmdStagedFiles = []string{"git", "diff", "--name-only", "--cached", "--diff-filter=ACMR"}
Expand All @@ -36,6 +40,7 @@ var (
cmdRemotes = []string{"git", "branch", "--remotes"}
cmdHideUnstaged = []string{"git", "checkout", "--force", "--"}
cmdEmptyTreeSHA = []string{"git", "hash-object", "-t", "tree", "/dev/null"}
cmdGitVersion = []string{"git", "version"}
)

// Repository represents a git repository.
Expand All @@ -53,6 +58,18 @@ type Repository struct {

// NewRepository returns a Repository or an error, if git repository it not initialized.
func NewRepository(fs afero.Fs, git *CommandExecutor) (*Repository, error) {
gitVersionOut, err := git.Cmd(cmdGitVersion)
if err == nil {
gitVersion := reVersion.FindString(gitVersionOut)
if err = version.Check(minGitVersion, gitVersion); err != nil {
log.Debugf("[lefthook] version check warning: %s %s", gitVersion, err)

if errors.Is(err, version.ErrUncoveredVersion) {
log.Warn("Git version is too old. Minimum supported version is " + minGitVersion)
}
}
}

rootPath, err := git.Cmd(cmdRootPath)
if err != nil {
return nil, err
Expand Down Expand Up @@ -127,12 +144,12 @@ func (r *Repository) PushFiles() ([]string, error) {
}

for _, branch := range branches {
if !headBranchRegexp.MatchString(branch) {
if !reHeadBranch.MatchString(branch) {
continue
}

matches := headBranchRegexp.FindStringSubmatch(branch)
r.headBranch = matches[headBranchRegexp.SubexpIndex("name")]
matches := reHeadBranch.FindStringSubmatch(branch)
r.headBranch = matches[reHeadBranch.SubexpIndex("name")]
break
}
}
Expand Down
70 changes: 42 additions & 28 deletions internal/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ var (
`^(?P<major>\d+)(?:\.(?P<minor>\d+)(?:\.(?P<patch>\d+))?)?$`,
)

errIncorrectVersion = errors.New("format of 'min_version' setting is incorrect")
ErrInvalidVersion = errors.New("invalid version format")
ErrUncoveredVersion = errors.New("version is lower than required")

errInvalidMinVersion = errors.New("format of 'min_version' setting is incorrect")
)

func Version(verbose bool) string {
Expand All @@ -29,47 +32,58 @@ func Version(verbose bool) string {
return version
}

// CheckCovered returns true if given version is less or equal than current
// and false otherwise.
func CheckCovered(targetVersion string) error {
if len(targetVersion) == 0 {
return nil
}

if !versionRegexp.MatchString(targetVersion) {
return errIncorrectVersion
}

major, minor, patch, err := parseVersion(version)
if err != nil {
return err
func Check(wanted, given string) error {
if !versionRegexp.MatchString(given) {
return ErrInvalidVersion
}

tMajor, tMinor, tPatch, err := parseVersion(targetVersion)
major, minor, patch, err := parseVersion(given)
if err != nil {
return err
return ErrInvalidVersion
}

execPath, err := os.Executable()
wantMajor, wantMinor, wantPatch, err := parseVersion(wanted)
if err != nil {
execPath = "<unknown>"
return ErrInvalidVersion
}
errUncovered := fmt.Errorf("required lefthook version (%s) is higher than current (%s) at %s", targetVersion, version, execPath)

switch {
case major > tMajor:
case major > wantMajor:
return nil
case major < tMajor:
return errUncovered
case minor > tMinor:
case major < wantMajor:
return ErrUncoveredVersion
case minor > wantMinor:
return nil
case minor < tMinor:
return errUncovered
case patch >= tPatch:
case minor < wantMinor:
return ErrUncoveredVersion
case patch >= wantPatch:
return nil
default:
return errUncovered
return ErrUncoveredVersion
}
}

// CheckCovered returns true if given version is less or equal than current
// and false otherwise.
func CheckCovered(targetVersion string) error {
if len(targetVersion) == 0 {
return nil
}

err := Check(targetVersion, version)

if errors.Is(err, ErrUncoveredVersion) {
execPath, oserr := os.Executable()
if oserr != nil {
execPath = "<unknown>"
}

return fmt.Errorf("required lefthook version (%s) is higher than current (%s) at %s", targetVersion, version, execPath)
} else if errors.Is(err, ErrInvalidVersion) {
return errInvalidMinVersion
}

return err
}

// parseVersion parses the version string of "1.2.3", "1.2", or just "1" and
Expand Down

0 comments on commit 9df624c

Please sign in to comment.