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
This commit is contained in:
AuroraAeon 2026-09-22 18:58:18 +08:00
parent f548e57e54
commit 72ca3d5f64
3 changed files with 37 additions and 4 deletions

View File

@ -45,6 +45,31 @@ describe('git-version tests', () => {
expect(version.checkMinimum(new GitVersion('5.1.2'))).toBeFalsy() 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 () => { it('sparse checkout', async () => {
const minSparseVer = MinimumGitSparseCheckoutVersion const minSparseVer = MinimumGitSparseCheckoutVersion
expect(new GitVersion('1.0').checkMinimum(minSparseVer)).toBeFalsy() expect(new GitVersion('1.0').checkMinimum(minSparseVer)).toBeFalsy()

8
dist/index.js vendored
View File

@ -35553,8 +35553,12 @@ class GitVersion {
} }
// Minor is equal // Minor is equal
if (this.minor === minimum.minor) { if (this.minor === minimum.minor) {
// Patch is insufficient // Patch is insufficient. The patch component is only compared when it
if (this.patch && this.patch < (minimum.patch || 0)) { // 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; return false;
} }
} }

View File

@ -43,8 +43,12 @@ export class GitVersion {
// Minor is equal // Minor is equal
if (this.minor === minimum.minor) { if (this.minor === minimum.minor) {
// Patch is insufficient // Patch is insufficient. The patch component is only compared when it
if (this.patch && this.patch < (minimum.patch || 0)) { // 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 return false
} }
} }