From 085d70be31b83ff30fd56b64f122be3609c339b0 Mon Sep 17 00:00:00 2001 From: Vincent Date: Sun, 18 Feb 2024 04:22:08 +0100 Subject: [PATCH] feat: Adds unity3d versioning --- lib/modules/versioning/api.ts | 2 + lib/modules/versioning/unity3d/index.spec.ts | 64 ++++++++++++++++ lib/modules/versioning/unity3d/index.ts | 81 ++++++++++++++++++++ lib/modules/versioning/unity3d/readme.md | 5 ++ 4 files changed, 152 insertions(+) create mode 100644 lib/modules/versioning/unity3d/index.spec.ts create mode 100644 lib/modules/versioning/unity3d/index.ts create mode 100644 lib/modules/versioning/unity3d/readme.md 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..750a0039370627 --- /dev/null +++ b/lib/modules/versioning/unity3d/index.ts @@ -0,0 +1,81 @@ +import semver from 'semver'; +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:~:text=characters%20are%20supported.-,Unity%20version%20numbers,-Current%20versions%20of', +]; +export const supportsRanges = false; + +class Unity3dVersioningApi extends GenericVersioningApi { + private static readonly ReleaseStreamType = new Map([ + ['Alpha', 'a'], + ['Beta', 'b'], + ['Patch', 'p'], + ['Experimental', 'x'], + ['Stable', 'f'], + ['Stable (China)', 'c'], + ]); + private static readonly ReleaseStreamTypeKeyOrder = Array.from( + Unity3dVersioningApi.ReleaseStreamType.values(), + ); + + protected _parse(version: string): GenericVersion | null { + const matches = regEx( + /^(?\d+)\.(?\d+)\.(?\d+)(?\w)(?\d+)/gm, + ).exec(version); + if (!matches?.groups) { + return null; + } + const { Major, Minor, Patch, ReleaseStream, Build } = matches.groups; + + const release = [ + parseInt(Major), + parseInt(Minor), + parseInt(Patch) * 1000 + parseInt(Build), + ]; + const stable = [ + Unity3dVersioningApi.ReleaseStreamType.get('Stable'), + Unity3dVersioningApi.ReleaseStreamType.get('Stable (China)'), + ].includes(ReleaseStream); + + let suffix = ''; + if (version.match(/\([a-f0-9]+\)$/)) { + suffix = version.substring(1).substring(version.length - 2); + } + return { release, prerelease: stable ? undefined : Build, suffix }; + } + + protected override _compare(lhs: string, rhs: string): number { + const semverLhs = semver.parse(lhs.split(/(?=[a-z])/)[0])!; + const semverRhs = semver.parse(rhs.split(/(?=[a-z])/)[0])!; + + const releaseStreamLhs = lhs.match(/([a-z])/)![0]; + const releaseStreamRhs = rhs.match(/([a-z])/)![0]; + + const indexLhs = + Unity3dVersioningApi.ReleaseStreamTypeKeyOrder.indexOf(releaseStreamLhs); + const indexRhs = + Unity3dVersioningApi.ReleaseStreamTypeKeyOrder.indexOf(releaseStreamRhs); + + const semVerCompare = semverLhs.compare(semverRhs); + if (semVerCompare !== 0) { + return semVerCompare; + } + + if (indexLhs > indexRhs) { + return 1; + } + if (indexLhs < indexRhs) { + return -1; + } + return 0; + } +} + +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..2e2e0fd43f593d --- /dev/null +++ b/lib/modules/versioning/unity3d/readme.md @@ -0,0 +1,5 @@ +Unity versioning follow semantic versioning, followed by a letter, number and hash. + +- 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