Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
compare an explicit patch of zero against the minimum version
GitVersion.checkMinimum guarded the patch comparison with a truthiness check
on `this.patch`, so a version whose patch component was explicitly zero was
treated as if the patch were unspecified and the comparison was skipped
entirely. That made `new GitVersion('4.5.0').checkMinimum(new GitVersion('4.5.1'))`
return true.

Compare the patch only when it was actually specified, distinguishing an
explicit zero from an unspecified one. A two-part version such as "2.28" still
leaves patch as NaN and continues to satisfy any patch of that minor version,
which is the behavior the existing tests rely on.

* compare an explicit patch of zero against the minimum version
* add regression coverage for an explicit patch of zero
* rebuild dist
  • Loading branch information
AuroraAeon committed Sep 22, 2026
commit 72ca3d5f64bbd508b6081820e907a137fafa6628
25 changes: 25 additions & 0 deletions __test__/git-version.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,31 @@ describe('git-version tests', () => {
expect(version.checkMinimum(new GitVersion('5.1.2'))).toBeFalsy()
})

it('compares an explicit patch of zero', async () => {
// A patch component of zero must be compared, not treated as unspecified
// (0 is falsy). A patch left unspecified by a two-part version such as
// "2.28" is treated as satisfying any patch of that minor version.
expect(
new GitVersion('4.5.0').checkMinimum(new GitVersion('4.5.1'))
).toBeFalsy()
expect(
new GitVersion('2.28.0').checkMinimum(new GitVersion('2.28.1'))
).toBeFalsy()
expect(
new GitVersion('4.5.0').checkMinimum(new GitVersion('4.5.0'))
).toBeTruthy()
expect(
new GitVersion('4.5.0').checkMinimum(new GitVersion('4.5'))
).toBeTruthy()
expect(
new GitVersion('4.5.1').checkMinimum(new GitVersion('4.5.0'))
).toBeTruthy()
// Unspecified patch satisfies any patch of the same minor version
expect(
new GitVersion('4.5').checkMinimum(new GitVersion('4.5.0'))
).toBeTruthy()
})

it('sparse checkout', async () => {
const minSparseVer = MinimumGitSparseCheckoutVersion
expect(new GitVersion('1.0').checkMinimum(minSparseVer)).toBeFalsy()
Expand Down
8 changes: 6 additions & 2 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35553,8 +35553,12 @@ class GitVersion {
}
// Minor is equal
if (this.minor === minimum.minor) {
// Patch is insufficient
if (this.patch && this.patch < (minimum.patch || 0)) {
// Patch is insufficient. The patch component is only compared when it
// was explicitly specified: an instance built from a two-part version
// (e.g. "2.28") leaves patch as NaN, which is treated as satisfying any
// patch of that minor version. An explicit zero must not be mistaken for
// an unspecified value, because 0 is falsy.
if (!Number.isNaN(this.patch) && this.patch < (minimum.patch || 0)) {
return false;
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/git-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ export class GitVersion {

// Minor is equal
if (this.minor === minimum.minor) {
// Patch is insufficient
if (this.patch && this.patch < (minimum.patch || 0)) {
// Patch is insufficient. The patch component is only compared when it
// was explicitly specified: an instance built from a two-part version
// (e.g. "2.28") leaves patch as NaN, which is treated as satisfying any
// patch of that minor version. An explicit zero must not be mistaken for
// an unspecified value, because 0 is falsy.
if (!Number.isNaN(this.patch) && this.patch < (minimum.patch || 0)) {
return false
}
}
Expand Down