diff --git a/lib/modules/versioning/api.ts b/lib/modules/versioning/api.ts index aaf75903ff3150..a2f52a8a738243 100644 --- a/lib/modules/versioning/api.ts +++ b/lib/modules/versioning/api.ts @@ -36,6 +36,7 @@ import * as semverCoerced from './semver-coerced'; import * as swift from './swift'; import type { VersioningApi, VersioningApiConstructor } from './types'; import * as ubuntu from './ubuntu'; +import * as unity3d from './unity3d'; const api = new Map(); export default api; @@ -77,3 +78,4 @@ api.set(semver.id, semver.api); api.set(semverCoerced.id, semverCoerced.api); api.set(swift.id, swift.api); api.set(ubuntu.id, ubuntu.api); +api.set(unity3d.id, unity3d.api); diff --git a/lib/modules/versioning/unity3d/index.spec.ts b/lib/modules/versioning/unity3d/index.spec.ts new file mode 100644 index 00000000000000..9e9bd324ed7275 --- /dev/null +++ b/lib/modules/versioning/unity3d/index.spec.ts @@ -0,0 +1,64 @@ +import unity3d from '.'; + +describe('modules/versioning/unity3d/index', () => { + it.each` + input | expected + ${'9.0.3'} | ${false} + ${'1.2019.3.22'} | ${false} + ${'3.0.0-beta'} | ${false} + ${'2.0.2-pre20191018090318'} | ${false} + ${'1.0.0+c30d7625'} | ${false} + ${'2.3.4-beta+1990ef74'} | ${false} + ${'17.04'} | ${false} + ${'3.0.0.beta'} | ${false} + ${'5.1.2-+'} | ${false} + ${'2022.2.12f1 (1234567890ab)'} | ${true} + ${'2022.2.11 (1234567890ab)'} | ${false} + ${'2021.1.10p1 (1234567890ab)'} | ${true} + ${'2021.1.9b1 (1234567890ab)'} | ${true} + ${'2021.1.1a1 (1234567890ab)'} | ${true} + `('isValid("$input") === $expected', ({ input, expected }) => { + const res = !!unity3d.isValid(input); + expect(res).toBe(expected); + }); + + it.each` + input | expected + ${'2022.2.12f1 (1234567890ab)'} | ${true} + ${'2021.1.10p1 (1234567890ab)'} | ${false} + ${'2021.1.9b1 (1234567890ab)'} | ${false} + ${'2021.1.1a1 (1234567890ab)'} | ${false} + `('isStable("$input") === $expected', ({ input, expected }) => { + expect(unity3d.isStable(input)).toBe(expected); + }); + + it.each` + a | b | expected + ${'2022.2.12f1 (1234567890ab)'} | ${'2022.2.12f1 (1234567890ab)'} | ${true} + ${'2021.1.10p1 (1234567890ab)'} | ${'2021.1.10p1 (1234567890ab)'} | ${true} + ${'2021.1.9b1 (1234567890ab)'} | ${'2021.1.9b1 (1234567890ab)'} | ${true} + ${'2021.1.1a1 (1234567890ab)'} | ${'2021.1.1a1 (1234567890ab)'} | ${true} + `('equals($a, $b) === $expected', ({ a, b, expected }) => { + expect(unity3d.equals(a, b)).toBe(expected); + }); + + it.each` + a | b | expected + ${'2022.2.12f1 (1234567890ab)'} | ${'2022.2.12b1 (1234567890ab)'} | ${true} + ${'2022.2.12f1 (1234567890ab)'} | ${'2021.1.10p1 (1234567890ab)'} | ${true} + ${'2021.1.10p1 (1234567890ab)'} | ${'2021.1.9b1 (1234567890ab)'} | ${true} + ${'2021.1.9b1 (1234567890ab)'} | ${'2021.1.1a1 (1234567890ab)'} | ${true} + ${'2021.1.10p1 (1234567890ab)'} | ${'2022.2.12f1 (1234567890ab)'} | ${false} + ${'2021.1.9b1 (1234567890ab)'} | ${'2021.1.10p1 (1234567890ab)'} | ${false} + ${'2021.1.1a1 (1234567890ab)'} | ${'2021.1.9b1 (1234567890ab)'} | ${false} + ${'2022.2.12b1 (1234567890ab)'} | ${'2022.2.12f1 (1234567890ab)'} | ${false} + ${'2021.1.10p1 (1234567890ab)'} | ${'2022.2.12f1 (1234567890ab)'} | ${false} + ${'2021.1.9b1 (1234567890ab)'} | ${'2021.1.10p1 (1234567890ab)'} | ${false} + ${'2021.1.1a1 (1234567890ab)'} | ${'2021.1.9b1 (1234567890ab)'} | ${false} + ${'2022.2.12f1 (1234567890ab)'} | ${'2021.1.10p1 (1234567890ab)'} | ${true} + ${'2021.1.10p1 (1234567890ab)'} | ${'2021.1.9b1 (1234567890ab)'} | ${true} + ${'2021.1.9b1 (1234567890ab)'} | ${'2021.1.1a1 (1234567890ab)'} | ${true} + `('isGreaterThan($a, $b) === $expected', ({ a, b, expected }) => { + expect(unity3d.isGreaterThan(a, b)).toBe(expected); + }); +}); diff --git a/lib/modules/versioning/unity3d/index.ts b/lib/modules/versioning/unity3d/index.ts new file mode 100644 index 00000000000000..07d0e3284fab32 --- /dev/null +++ b/lib/modules/versioning/unity3d/index.ts @@ -0,0 +1,50 @@ +import { regEx } from '../../../util/regex'; +import { GenericVersion, GenericVersioningApi } from '../generic'; +import type { VersioningApi } from '../types'; + +export const id = 'unity3d'; +export const displayName = 'Unity3D'; +export const urls = [ + 'https://docs.unity3d.com/Manual/ScriptCompilationAssemblyDefinitionFiles.html#version-define-expressions', +]; +export const supportsRanges = false; + +class Unity3dVersioningApi extends GenericVersioningApi { + private static readonly parsingRegex = regEx( + /^(?\d+)\.(?\d+)\.(?\d+)(?\w)(?\d+)/, + ); + + private static readonly ReleaseStreamType = [ + 'a', // Alpha + 'b', // Beta + 'p', // Patch + 'x', // Experimental + 'f', // Stable + 'c', // Stable (China) + ]; + private static readonly stableVersions = ['f', 'c']; + + protected _parse(version: string): GenericVersion | null { + const matches = Unity3dVersioningApi.parsingRegex.exec(version); + if (!matches?.groups) { + return null; + } + const { major, minor, patch, releaseStream, build } = matches.groups; + + const release = [ + parseInt(major, 10), + parseInt(minor, 10), + parseInt(patch, 10), + Unity3dVersioningApi.ReleaseStreamType.indexOf(releaseStream), + parseInt(build, 10), + ]; + const isStable = + Unity3dVersioningApi.stableVersions.includes(releaseStream); + + return { release, prerelease: isStable ? undefined : build }; + } +} + +export const api: VersioningApi = new Unity3dVersioningApi(); + +export default api; diff --git a/lib/modules/versioning/unity3d/readme.md b/lib/modules/versioning/unity3d/readme.md new file mode 100644 index 00000000000000..537f80fc6123ed --- /dev/null +++ b/lib/modules/versioning/unity3d/readme.md @@ -0,0 +1,13 @@ +Unity versioning follow semantic versioning, followed by a letter, number and an optional hash: + +- Major version is the year of release +- Minor and patch version are incremental, starting at 0 +- The letter denotes a stream (**a**lpha, **b**eta, **f**inal release, etc.) +- The number is a growing index +- The hash is calculated by Unity internally and irrelevant for comparision + +Examples: + +- `2023.2.10f1 (316c1fd686f6)` +- `2023.3.0a17` +- `2023.3.0b4 (2cd31b2a2ee2)`