diff --git a/pkg/commands/git_commands/version.go b/pkg/commands/git_commands/version.go index 0cf4b485c..1b1351df4 100644 --- a/pkg/commands/git_commands/version.go +++ b/pkg/commands/git_commands/version.go @@ -32,7 +32,7 @@ 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+)?(.*)`) + re := regexp.MustCompile(`[^\d]*(\d+)(\.\d+)?(\.\d+)?(.*)`) matches := re.FindStringSubmatch(versionStr) if len(matches) < 5 { @@ -65,3 +65,7 @@ func (v *GitVersion) IsOlderThan(major, minor, patch int) bool { required := major*1000*1000 + minor*1000 + patch return actual < required } + +func (v *GitVersion) IsOlderThanVersion(version *GitVersion) bool { + return v.IsOlderThan(version.Major, version.Minor, version.Patch) +} diff --git a/pkg/integration/components/runner.go b/pkg/integration/components/runner.go index 43e4f9304..03ca81295 100644 --- a/pkg/integration/components/runner.go +++ b/pkg/integration/components/runner.go @@ -8,6 +8,7 @@ import ( "path/filepath" "github.com/jesseduffield/lazycore/pkg/utils" + "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" ) @@ -42,6 +43,11 @@ func RunTests( return err } + gitVersion, err := getGitVersion() + if err != nil { + return err + } + for _, test := range tests { test := test @@ -51,7 +57,7 @@ func RunTests( ) for i := 0; i < maxAttempts; i++ { - err := runTest(test, paths, projectRootDir, logf, runCmd, sandbox, keyPressDelay) + err := runTest(test, paths, projectRootDir, logf, runCmd, sandbox, keyPressDelay, gitVersion) if err != nil { if i == maxAttempts-1 { return err @@ -77,12 +83,18 @@ func runTest( runCmd func(cmd *exec.Cmd) error, sandbox bool, keyPressDelay int, + gitVersion *git_commands.GitVersion, ) error { if test.Skip() { logf("Skipping test %s", test.Name()) return nil } + if !test.ShouldRunForGitVersion(gitVersion) { + logf("Skipping test %s for git version %d.%d.%d", test.Name(), gitVersion.Major, gitVersion.Minor, gitVersion.Patch) + return nil + } + logf("path: %s", paths.Root()) if err := prepareTestDir(test, paths, projectRootDir); err != nil { @@ -144,6 +156,16 @@ func globalGitConfigPath(rootDir string) string { return filepath.Join(rootDir, "test", "global_git_config") } +func getGitVersion() (*git_commands.GitVersion, error) { + osCommand := oscommands.NewDummyOSCommand() + cmdObj := osCommand.Cmd.New("git --version") + versionStr, err := cmdObj.RunWithOutput() + if err != nil { + return nil, err + } + return git_commands.ParseGitVersion(versionStr) +} + func getLazygitCommand(test *IntegrationTest, paths Paths, rootDir string, sandbox bool, keyPressDelay int) (*exec.Cmd, error) { osCommand := oscommands.NewDummyOSCommand() diff --git a/pkg/integration/components/test.go b/pkg/integration/components/test.go index e1767f475..847781c8e 100644 --- a/pkg/integration/components/test.go +++ b/pkg/integration/components/test.go @@ -5,6 +5,8 @@ import ( "strconv" "strings" + "github.com/jesseduffield/generics/slices" + "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/env" integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types" @@ -28,6 +30,7 @@ type IntegrationTest struct { testDriver *TestDriver, keys config.KeybindingConfig, ) + gitVersion GitVersionRestriction } var _ integrationTypes.IntegrationTest = &IntegrationTest{} @@ -45,6 +48,56 @@ type NewIntegrationTestArgs struct { ExtraCmdArgs string // for when a test is flakey Skip bool + // to run a test only on certain git versions + GitVersion GitVersionRestriction +} + +type GitVersionRestriction struct { + // Only one of these fields can be non-empty; use functions below to construct + from string + before string + includes []string +} + +// Verifies the version is at least the given version (inclusive) +func From(version string) GitVersionRestriction { + return GitVersionRestriction{from: version} +} + +// Verifies the version is before the given version (exclusive) +func Before(version string) GitVersionRestriction { + return GitVersionRestriction{before: version} +} + +func Includes(versions ...string) GitVersionRestriction { + return GitVersionRestriction{includes: versions} +} + +func (self GitVersionRestriction) shouldRunOnVersion(version *git_commands.GitVersion) bool { + if self.from != "" { + from, err := git_commands.ParseGitVersion(self.from) + if err != nil { + panic("Invalid git version string: " + self.from) + } + return !version.IsOlderThanVersion(from) + } + if self.before != "" { + before, err := git_commands.ParseGitVersion(self.before) + if err != nil { + panic("Invalid git version string: " + self.before) + } + return version.IsOlderThanVersion(before) + } + if len(self.includes) != 0 { + return slices.Some(self.includes, func(str string) bool { + v, err := git_commands.ParseGitVersion(str) + if err != nil { + panic("Invalid git version string: " + str) + } + return version.Major == v.Major && version.Minor == v.Minor && version.Patch == v.Patch + }) + } + return true } func NewIntegrationTest(args NewIntegrationTestArgs) *IntegrationTest { @@ -63,6 +116,7 @@ func NewIntegrationTest(args NewIntegrationTestArgs) *IntegrationTest { setupRepo: args.SetupRepo, setupConfig: args.SetupConfig, run: args.Run, + gitVersion: args.GitVersion, } } @@ -82,6 +136,10 @@ func (self *IntegrationTest) Skip() bool { return self.skip } +func (self *IntegrationTest) ShouldRunForGitVersion(version *git_commands.GitVersion) bool { + return self.gitVersion.shouldRunOnVersion(version) +} + func (self *IntegrationTest) SetupConfig(config *config.AppConfig) { self.setupConfig(config) } diff --git a/pkg/integration/components/test_test.go b/pkg/integration/components/test_test.go index 4216b8130..062382c2d 100644 --- a/pkg/integration/components/test_test.go +++ b/pkg/integration/components/test_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/jesseduffield/gocui" + "github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/gui/types" @@ -87,3 +88,65 @@ func TestSuccess(t *testing.T) { assert.EqualValues(t, []string{"a", "b"}, driver.pressedKeys) assert.Equal(t, "", driver.failureMessage) } + +func TestGitVersionRestriction(t *testing.T) { + scenarios := []struct { + testName string + gitVersion GitVersionRestriction + expectedShouldRun bool + }{ + { + testName: "From, current is newer", + gitVersion: From("2.24.9"), + expectedShouldRun: true, + }, + { + testName: "From, current is same", + gitVersion: From("2.25.0"), + expectedShouldRun: true, + }, + { + testName: "From, current is older", + gitVersion: From("2.26.0"), + expectedShouldRun: false, + }, + { + testName: "Before, current is older", + gitVersion: Before("2.24.9"), + expectedShouldRun: false, + }, + { + testName: "Before, current is same", + gitVersion: Before("2.25.0"), + expectedShouldRun: false, + }, + { + testName: "Before, current is newer", + gitVersion: Before("2.26.0"), + expectedShouldRun: true, + }, + { + testName: "Includes, current is included", + gitVersion: Includes("2.23.0", "2.25.0"), + expectedShouldRun: true, + }, + { + testName: "Includes, current is not included", + gitVersion: Includes("2.23.0", "2.27.0"), + expectedShouldRun: false, + }, + } + + currentGitVersion := git_commands.GitVersion{Major: 2, Minor: 25, Patch: 0} + + for _, s := range scenarios { + t.Run(s.testName, func(t *testing.T) { + test := NewIntegrationTest(NewIntegrationTestArgs{ + Description: unitTestDescription, + GitVersion: s.gitVersion, + }) + shouldRun := test.ShouldRunForGitVersion(¤tGitVersion) + assert.Equal(t, shouldRun, s.expectedShouldRun) + }) + } +}