Skip to content

Commit

Permalink
feat: add GitVersion struct
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryooooooga committed Dec 30, 2022
1 parent 41222f0 commit cd91118
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 84 deletions.
46 changes: 12 additions & 34 deletions pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import (
"log"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"

"github.com/go-errors/errors"
Expand Down Expand Up @@ -100,52 +98,36 @@ func NewApp(config config.AppConfigurer, common *common.Common) (*App, error) {
return app, err
}

gitVersion, err := app.validateGitVersion()
if err != nil {
return app, err
}

showRecentRepos, err := app.setupRepo()
if err != nil {
return app, err
}

app.Gui, err = gui.NewGui(common, config, app.Updater, showRecentRepos, dirName)
app.Gui, err = gui.NewGui(common, config, gitVersion, app.Updater, showRecentRepos, dirName)
if err != nil {
return app, err
}
return app, nil
}

func (app *App) validateGitVersion() error {
output, err := app.OSCommand.Cmd.New("git --version").RunWithOutput()
func (app *App) validateGitVersion() (*git_commands.GitVersion, error) {
version, err := git_commands.GetGitVersion(app.OSCommand)
// if we get an error anywhere here we'll show the same status
minVersionError := errors.New(app.Tr.MinGitVersionError)
if err != nil {
return minVersionError
return nil, minVersionError
}

if isGitVersionValid(output) {
return nil
if version.IsOlderThan(2, 0, 0) {
return nil, minVersionError
}

return minVersionError
}

func isGitVersionValid(versionStr string) bool {
// output should be something like: 'git version 2.23.0 (blah)'
re := regexp.MustCompile(`[^\d]+([\d\.]+)`)
matches := re.FindStringSubmatch(versionStr)

if len(matches) == 0 {
return false
}

gitVersion := matches[1]
majorVersion, err := strconv.Atoi(gitVersion[0:1])
if err != nil {
return false
}
if majorVersion < 2 {
return false
}

return true
return version, nil
}

func isDirectoryAGitRepository(dir string) (bool, error) {
Expand All @@ -166,10 +148,6 @@ func openRecentRepo(app *App) bool {
}

func (app *App) setupRepo() (bool, error) {
if err := app.validateGitVersion(); err != nil {
return false, err
}

if env.GetGitDirEnv() != "" {
// we've been given the git dir directly. We'll verify this dir when initializing our Git object
return false, nil
Expand Down
45 changes: 0 additions & 45 deletions pkg/app/app_test.go

This file was deleted.

5 changes: 4 additions & 1 deletion pkg/commands/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type Loaders struct {

func NewGitCommand(
cmn *common.Common,
version *git_commands.GitVersion,
osCommand *oscommands.OSCommand,
gitConfig git_config.IGitConfig,
syncMutex *deadlock.Mutex,
Expand All @@ -73,6 +74,7 @@ func NewGitCommand(

return NewGitCommandAux(
cmn,
version,
osCommand,
gitConfig,
dotGitDir,
Expand All @@ -83,6 +85,7 @@ func NewGitCommand(

func NewGitCommandAux(
cmn *common.Common,
version *git_commands.GitVersion,
osCommand *oscommands.OSCommand,
gitConfig git_config.IGitConfig,
dotGitDir string,
Expand All @@ -100,7 +103,7 @@ func NewGitCommandAux(

fileLoader := git_commands.NewFileLoader(cmn, cmd, configCommands)

gitCommon := git_commands.NewGitCommon(cmn, cmd, osCommand, dotGitDir, repo, configCommands, syncMutex)
gitCommon := git_commands.NewGitCommon(cmn, version, cmd, osCommand, dotGitDir, repo, configCommands, syncMutex)
statusCommands := git_commands.NewStatusCommands(gitCommon)
flowCommands := git_commands.NewFlowCommands(gitCommon)
remoteCommands := git_commands.NewRemoteCommands(gitCommon)
Expand Down
3 changes: 3 additions & 0 deletions pkg/commands/git_commands/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

type GitCommon struct {
*common.Common
version *GitVersion
cmd oscommands.ICmdObjBuilder
os *oscommands.OSCommand
dotGitDir string
Expand All @@ -20,6 +21,7 @@ type GitCommon struct {

func NewGitCommon(
cmn *common.Common,
version *GitVersion,
cmd oscommands.ICmdObjBuilder,
osCommand *oscommands.OSCommand,
dotGitDir string,
Expand All @@ -29,6 +31,7 @@ func NewGitCommon(
) *GitCommon {
return &GitCommon{
Common: cmn,
version: version,
cmd: cmd,
os: osCommand,
dotGitDir: dotGitDir,
Expand Down
67 changes: 67 additions & 0 deletions pkg/commands/git_commands/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package git_commands

import (
"errors"
"regexp"
"strconv"
"strings"

"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
)

type GitVersion struct {
Major, Minor, Patch int
Additional string
}

func GetGitVersion(osCommand *oscommands.OSCommand) (*GitVersion, error) {
versionStr, _, err := osCommand.Cmd.New("git --version").RunWithOutputs()
if err != nil {
return nil, err
}

version, err := ParseGitVersion(versionStr)
if err != nil {
return nil, err
}

return version, nil
}

func ParseGitVersion(versionStr string) (*GitVersion, error) {
// versionStr should be something like:
// git version 2.39.0
// git version 2.37.1 (Apple Git-137.1)
re := regexp.MustCompile(`[^\d]+(\d+)(\.\d+)?(\.\d+)?(.*)`)
matches := re.FindStringSubmatch(versionStr)

if len(matches) < 5 {
return nil, errors.New("unexpected git version format: " + versionStr)
}

v := &GitVersion{}
var err error

if v.Major, err = strconv.Atoi(matches[1]); err != nil {
return nil, err
}
if len(matches[2]) > 1 {
if v.Minor, err = strconv.Atoi(matches[2][1:]); err != nil {
return nil, err
}
}
if len(matches[3]) > 1 {
if v.Patch, err = strconv.Atoi(matches[3][1:]); err != nil {
return nil, err
}
}
v.Additional = strings.Trim(matches[4], " \r\n")

return v, nil
}

func (v *GitVersion) IsOlderThan(major, minor, patch int) bool {
actual := v.Major*1000*1000 + v.Minor*1000 + v.Patch
required := major*1000*1000 + minor*1000 + patch
return actual < required
}
47 changes: 47 additions & 0 deletions pkg/commands/git_commands/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package git_commands

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestParseGitVersion(t *testing.T) {
scenarios := []struct {
input string
expected GitVersion
}{
{
input: "git version 2.39.0",
expected: GitVersion{Major: 2, Minor: 39, Patch: 0, Additional: ""},
},
{
input: "git version 2.37.1 (Apple Git-137.1)",
expected: GitVersion{Major: 2, Minor: 37, Patch: 1, Additional: "(Apple Git-137.1)"},
},
{
input: "git version 2.37 (Apple Git-137.1)",
expected: GitVersion{Major: 2, Minor: 37, Patch: 0, Additional: "(Apple Git-137.1)"},
},
}

for _, s := range scenarios {
actual, err := ParseGitVersion(s.input)

assert.NoError(t, err)
assert.NotNil(t, actual)
assert.Equal(t, s.expected.Major, actual.Major)
assert.Equal(t, s.expected.Minor, actual.Minor)
assert.Equal(t, s.expected.Patch, actual.Patch)
assert.Equal(t, s.expected.Additional, actual.Additional)
}
}

func TestGitVersionIsOlderThan(t *testing.T) {
assert.False(t, (&GitVersion{2, 0, 0, ""}).IsOlderThan(1, 99, 99))
assert.False(t, (&GitVersion{2, 0, 0, ""}).IsOlderThan(2, 0, 0))
assert.False(t, (&GitVersion{2, 1, 0, ""}).IsOlderThan(2, 0, 9))

assert.True(t, (&GitVersion{2, 0, 1, ""}).IsOlderThan(2, 1, 0))
assert.True(t, (&GitVersion{2, 0, 1, ""}).IsOlderThan(3, 0, 0))
}
2 changes: 2 additions & 0 deletions pkg/commands/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/go-errors/errors"
gogit "github.com/jesseduffield/go-git/v5"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/git_config"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/utils"
Expand Down Expand Up @@ -218,6 +219,7 @@ func TestNewGitCommand(t *testing.T) {
s.setup()
s.test(
NewGitCommand(utils.NewDummyCommon(),
&git_commands.GitVersion{},
oscommands.NewDummyOSCommand(),
git_config.NewFakeGitConfig(nil),
&deadlock.Mutex{},
Expand Down
3 changes: 2 additions & 1 deletion pkg/gui/dummies.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gui

import (
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/updates"
Expand All @@ -16,6 +17,6 @@ func NewDummyUpdater() *updates.Updater {

func NewDummyGui() *Gui {
newAppConfig := config.NewDummyAppConfig()
dummyGui, _ := NewGui(utils.NewDummyCommon(), newAppConfig, NewDummyUpdater(), false, "")
dummyGui, _ := NewGui(utils.NewDummyCommon(), newAppConfig, &git_commands.GitVersion{}, NewDummyUpdater(), false, "")
return dummyGui
}
10 changes: 7 additions & 3 deletions pkg/gui/gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ type Repo string
// Gui wraps the gocui Gui object which handles rendering and events
type Gui struct {
*common.Common
g *gocui.Gui
git *commands.GitCommand
os *oscommands.OSCommand
g *gocui.Gui
gitVersion *git_commands.GitVersion
git *commands.GitCommand
os *oscommands.OSCommand

// this is the state of the GUI for the current repo
State *GuiRepoState
Expand Down Expand Up @@ -222,6 +223,7 @@ func (gui *Gui) onNewRepo(startArgs appTypes.StartArgs, reuseState bool) error {
var err error
gui.git, err = commands.NewGitCommand(
gui.Common,
gui.gitVersion,
gui.os,
git_config.NewStdCachedGitConfig(gui.Log),
gui.Mutexes.SyncMutex,
Expand Down Expand Up @@ -341,12 +343,14 @@ func initialContext(contextTree *context.ContextTree, startArgs appTypes.StartAr
func NewGui(
cmn *common.Common,
config config.AppConfigurer,
gitVersion *git_commands.GitVersion,
updater *updates.Updater,
showRecentRepos bool,
initialDir string,
) (*Gui, error) {
gui := &Gui{
Common: cmn,
gitVersion: gitVersion,
Config: config,
Updater: updater,
statusManager: &statusManager{},
Expand Down

0 comments on commit cd91118

Please sign in to comment.