diff --git a/version.go b/version.go index 054caa4..50d56b6 100644 --- a/version.go +++ b/version.go @@ -364,3 +364,37 @@ func (v Version) CompareSeries(w Version) int { func (v Version) AtLeast(w Version) bool { return v.Compare(w) >= 0 } + +// IncPatch returns a new version with the patch number incremented by 1. +// This method returns an error if the version is not a stable version. +func (v Version) IncPatch() (Version, error) { + if v.phase != stable { + return Version{}, fmt.Errorf("version %s is not a stable version", v.String()) + } + nextVersion := Version{ + phase: v.phase, + year: v.year, + ordinal: v.ordinal, + patch: v.patch + 1, + } + nextVersion.raw = nextVersion.Format("v%X.%Y.%Z") + return nextVersion, nil +} + +// IncPreRelease returns a new version with the pre-release part incremented by 1. +// This method returns an error if the version is not a pre-release. +func (v Version) IncPreRelease() (Version, error) { + if !(v.IsPrerelease()) { + return Version{}, errors.New("version is not a prerelease") + } + nextVersion := Version{ + raw: v.raw, + phase: v.phase, + year: v.year, + ordinal: v.ordinal, + patch: v.patch, + phaseOrdinal: v.phaseOrdinal + 1, + } + nextVersion.raw = nextVersion.Format("v%X.%Y.%Z-%P.%o") + return nextVersion, nil +} diff --git a/version_test.go b/version_test.go index 14ef93b..7baa926 100644 --- a/version_test.go +++ b/version_test.go @@ -662,3 +662,66 @@ func TestScan(t *testing.T) { err = v.Scan(123) // or any other type require.ErrorContains(t, err, "cannot convert int to Version") } + +func TestIncPatch(t *testing.T) { + testCases := []struct { + currentVersion string + nextVersion string + expectError bool + }{ + {"v21.2.0-alpha.1", "", true}, + {"v21.1.0-beta.3", "", true}, + {"v21.1.0-rc.3", "", true}, + {"v21.1.0-rc.3-cloudonly.1", "", true}, + {"v21.1.0-customLabel", "", true}, + {"v21.1.0-cloudonly.3", "", true}, + {"v20.2.7", "v20.2.8", false}, + {"v21.1.2", "v21.1.3", false}, + {"v21.1.3", "v21.1.4", false}, + {"v20.2.11", "v20.2.12", false}, + {"v21.1.0", "v21.1.1", false}, + } + for i, tc := range testCases { + t.Run(fmt.Sprintf("Version.IncPatch #%d: %s -> %s", i, tc.currentVersion, tc.nextVersion), func(t *testing.T) { + a := MustParse(tc.currentVersion) + b, err := a.IncPatch() + if tc.expectError { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, MustParse(tc.nextVersion), b) + }) + } +} + +func TestIncPreRelease(t *testing.T) { + testCases := []struct { + currentVersion string + nextVersion string + expectError bool + }{ + {"v21.2.0-alpha.1", "v21.2.0-alpha.2", false}, + {"v21.1.0-beta.3", "v21.1.0-beta.4", false}, + {"v21.1.0-rc.3", "v21.1.0-rc.4", false}, + {"v21.1.0-cloudonly.1", "", true}, + {"v21.1.0", "", true}, + {"v21.1.8", "", true}, + {"v26.4.8", "", true}, + {"v21.1.0-customLabel", "", true}, + {"v21.1.0-1-g9cbe7c5281", "", true}, + {"v21.1.0-1-g9cbe7c5281-customLabel", "", true}, + } + for i, tc := range testCases { + t.Run(fmt.Sprintf("Version.IncPhaseOrdinal #%d: %s -> %s", i, tc.currentVersion, tc.nextVersion), func(t *testing.T) { + a := MustParse(tc.currentVersion) + b, err := a.IncPreRelease() + if tc.expectError { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, MustParse(tc.nextVersion), b) + }) + } +}