mirror of
https://github.com/vrc-get/vrc-get.git
synced 2026-06-21 09:58:08 +00:00
167 lines
4.2 KiB
TypeScript
167 lines
4.2 KiB
TypeScript
import type { TauriVersion } from "@/lib/bindings";
|
|
|
|
function comparePrereleaseSegment(a: string, b: string) {
|
|
if (a === b) return 0;
|
|
|
|
const aIsNum = !!a.match(/^\d+$/);
|
|
const bIsNum = !!b.match(/^\d+$/);
|
|
|
|
if (aIsNum) {
|
|
if (bIsNum) {
|
|
const aNum = Number.parseInt(a, 10);
|
|
const bNum = Number.parseInt(b, 10);
|
|
if (aNum < bNum) return -1;
|
|
if (aNum > bNum) return 1;
|
|
return 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
} else {
|
|
if (!bIsNum) {
|
|
// the js does < > in unicode code point order, which is the same as ASCII order
|
|
if (a < b) return -1;
|
|
if (a > b) return 1;
|
|
return 0;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
export function compareVersion(a: TauriVersion, b: TauriVersion) {
|
|
if (a.major < b.major) return -1;
|
|
if (a.major > b.major) return 1;
|
|
|
|
if (a.minor < b.minor) return -1;
|
|
if (a.minor > b.minor) return 1;
|
|
|
|
if (a.patch < b.patch) return -1;
|
|
if (a.patch > b.patch) return 1;
|
|
|
|
// fast path: exactly the same prerelease
|
|
if (a.pre === b.pre) return 0;
|
|
|
|
// if either has no prerelease, it comes later
|
|
if (a.pre === "") return 1;
|
|
if (b.pre === "") return -1;
|
|
|
|
const aPrerelease = a.pre.split(".");
|
|
const bPrerelease = b.pre.split(".");
|
|
|
|
for (let i = 0; i < Math.min(aPrerelease.length, bPrerelease.length); i++) {
|
|
const cmp = comparePrereleaseSegment(aPrerelease[i], bPrerelease[i]);
|
|
if (cmp !== 0) return cmp;
|
|
}
|
|
|
|
if (aPrerelease.length < bPrerelease.length) return -1;
|
|
if (aPrerelease.length > bPrerelease.length) return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
export function toVersionString(
|
|
version: TauriVersion,
|
|
): `${number}.${number}.${number}${`-${string}` | ""}${`+${string}` | ""}` {
|
|
const versionString: `${number}.${number}.${number}` = `${version.major}.${version.minor}.${version.patch}`;
|
|
const withPre: `${number}.${number}.${number}${`-${string}` | ""}` =
|
|
version.pre ? `${versionString}-${version.pre}` : versionString;
|
|
return version.build ? `${withPre}+${version.build}` : withPre;
|
|
}
|
|
|
|
export function compareUnityVersion(a: [number, number], b: [number, number]) {
|
|
if (a[0] < b[0]) return -1;
|
|
if (a[0] > b[0]) return 1;
|
|
|
|
if (a[1] < b[1]) return -1;
|
|
if (a[1] > b[1]) return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// This ignores china version changes
|
|
export function compareUnityVersionString(a: string, b: string): 0 | 1 | -1 {
|
|
if (a === b) return 0;
|
|
|
|
const aParsed = parseUnityVersion(a);
|
|
const bParsed = parseUnityVersion(b);
|
|
|
|
if (!aParsed && !bParsed) {
|
|
const cmp = a.localeCompare(b);
|
|
return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
|
|
} else if (!aParsed) {
|
|
return 1;
|
|
} else if (!bParsed) {
|
|
return -1;
|
|
}
|
|
|
|
if (aParsed.major < bParsed.major) return -1;
|
|
if (aParsed.major > bParsed.major) return 1;
|
|
|
|
if (aParsed.minor < bParsed.minor) return -1;
|
|
if (aParsed.minor > bParsed.minor) return 1;
|
|
|
|
if (aParsed.patch < bParsed.patch) return -1;
|
|
if (aParsed.patch > bParsed.patch) return 1;
|
|
|
|
const channelCmp = compareUnityChannel(aParsed.channel, bParsed.channel);
|
|
if (channelCmp !== 0) return channelCmp;
|
|
|
|
if (aParsed.increment < bParsed.increment) return -1;
|
|
if (aParsed.increment > bParsed.increment) return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
interface UnityVersion {
|
|
major: number;
|
|
minor: number;
|
|
patch: number;
|
|
channel: "a" | "b" | "f" | "c" | "p" | "x";
|
|
increment: number;
|
|
chinaIncrement: number | null;
|
|
}
|
|
|
|
export function parseUnityVersion(version: string): UnityVersion | null {
|
|
let match = version.match(/^(\d+)\.(\d+)\.(\d+)([abfcpx])(\d+)(?:c(\d+))?$/);
|
|
if (!match) {
|
|
match = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
|
|
if (!match) {
|
|
return null;
|
|
}
|
|
}
|
|
return {
|
|
major: Number.parseInt(match[1], 10),
|
|
minor: Number.parseInt(match[2], 10),
|
|
patch: Number.parseInt(match[3], 10),
|
|
channel: (match[4] || "f") as UnityVersion["channel"],
|
|
increment: Number.parseInt(match[5] || "1", 10),
|
|
chinaIncrement: match[6] ? Number.parseInt(match[6], 10) : null,
|
|
};
|
|
}
|
|
|
|
function compareUnityChannel(
|
|
aIn: UnityVersion["channel"],
|
|
bIn: UnityVersion["channel"],
|
|
) {
|
|
const a = aIn === "c" ? "f" : aIn;
|
|
const b = bIn === "c" ? "f" : bIn;
|
|
|
|
if (a === b) return 0;
|
|
|
|
if (a === "a") return -1;
|
|
if (b === "a") return 1;
|
|
|
|
if (a === "b") return -1;
|
|
if (b === "b") return 1;
|
|
|
|
if (a === "f") return -1;
|
|
if (b === "f") return 1;
|
|
|
|
if (a === "p") return 1;
|
|
if (b === "p") return -1;
|
|
|
|
if (a === "x") return -1;
|
|
if (b === "x") return 1;
|
|
|
|
return 0;
|
|
}
|