mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-14 15:24:52 +09:00
Rename to SourceVersion
This commit is contained in:
12 files changed
+70
-67
No files matched your search
@@ -80,7 +80,7 @@ export default class BaseConnection extends lib.Link {
|
||||
return modPack;
|
||||
}
|
||||
|
||||
getMod(mod: { name: string, version: lib.GameVersion, sha1?: string }) {
|
||||
getMod(mod: { name: string, version: lib.SourceVersion, sha1?: string }) {
|
||||
let filename = lib.ModInfo.filename(mod.name, mod.version);
|
||||
let modInfo = this._controller.modStore.files.get(filename);
|
||||
if (!modInfo) {
|
||||
|
||||
@@ -707,7 +707,7 @@ export default class ControlConnection extends BaseConnection {
|
||||
const release = releases.releases
|
||||
.filter(info => versionRange.testVersion(info.version))
|
||||
.reduce<ModPortalReleaseType | undefined>((max, cur) => (
|
||||
max && lib.integerGameVersion(max.version) > lib.integerGameVersion(cur.version) ? max : cur
|
||||
max && lib.integerSourceVersion(max.version) > lib.integerSourceVersion(cur.version) ? max : cur
|
||||
), undefined);
|
||||
|
||||
if (!release) {
|
||||
|
||||
@@ -766,7 +766,7 @@ export default class Controller {
|
||||
// migrate: 2.0.0-alpha.22 - old buildins used X.Y rather than X.Y.Z
|
||||
// All other versions are kept verbatim so they still match the mod's file name.
|
||||
if (lib.isPartialVersion(mod.version)) {
|
||||
mod.version = lib.normaliseFullVersion(mod.version) as lib.GameVersion;
|
||||
mod.version = lib.normaliseFullVersion(mod.version) as lib.SourceVersion;
|
||||
}
|
||||
}
|
||||
return json;
|
||||
|
||||
@@ -20,7 +20,7 @@ modCommands.add(new lib.Command({
|
||||
yargs.positional("mod-version", { describe: "Version of the mod", type: "string" });
|
||||
}],
|
||||
handler: async function(args: { name: string, modVersion: string }, control: Control) {
|
||||
if (!lib.isGameVersion(args.modVersion)) {
|
||||
if (!lib.isSourceVersion(args.modVersion)) {
|
||||
throw new lib.CommandError("mod-version must match format digit.digit.digit");
|
||||
}
|
||||
let modInfo = await control.send(new lib.ModGetRequest(args.name, args.modVersion));
|
||||
@@ -108,7 +108,7 @@ modCommands.add(new lib.Command({
|
||||
},
|
||||
control: Control
|
||||
) {
|
||||
const searchVersion = lib.normaliseGameVersion(String(args.factorioVersion));
|
||||
const searchVersion = lib.normaliseSourceVersion(String(args.factorioVersion));
|
||||
if (searchVersion === undefined) {
|
||||
throw new Error(`Invalid factorio version "${args.factorioVersion}"`);
|
||||
}
|
||||
@@ -191,7 +191,7 @@ modCommands.add(new lib.Command({
|
||||
yargs.positional("mod-version", { describe: "Version of mod to download", type: "string" });
|
||||
}],
|
||||
handler: async function(args: { name: string, modVersion: string }, control: Control) {
|
||||
if (!lib.isGameVersion(args.modVersion)) {
|
||||
if (!lib.isSourceVersion(args.modVersion)) {
|
||||
throw new lib.CommandError("mod-version must match format digit.digit.digit");
|
||||
}
|
||||
let streamId = await control.send(new lib.ModDownloadRequest(args.name, args.modVersion));
|
||||
@@ -211,7 +211,7 @@ modCommands.add(new lib.Command({
|
||||
yargs.positional("mod-version", { describe: "Version of mod to delete", type: "string" });
|
||||
}],
|
||||
handler: async function(args: { name: string, modVersion: string }, control: Control) {
|
||||
if (!lib.isGameVersion(args.modVersion)) {
|
||||
if (!lib.isSourceVersion(args.modVersion)) {
|
||||
throw new lib.CommandError("mod-version must match format digit.digit.digit");
|
||||
}
|
||||
await control.send(new lib.ModDeleteRequest(args.name, args.modVersion));
|
||||
|
||||
@@ -132,7 +132,7 @@ function setModPackMods(modPack: lib.ModPack, mods: string[] | undefined) {
|
||||
if (!version) {
|
||||
throw new lib.CommandError("Added mod must be formatted as name:version or name:version:sha1");
|
||||
}
|
||||
if (!lib.isGameVersion(version)) {
|
||||
if (!lib.isSourceVersion(version)) {
|
||||
throw new lib.CommandError("version must match the format digit.digit.digit");
|
||||
}
|
||||
if (sha1 && !/^[0-9a-f]{40}$/.test(sha1)) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Static } from "@sinclair/typebox";
|
||||
import { logger } from "./logging";
|
||||
import { downloadFile, safeOutputFile } from "./file_ops";
|
||||
import { ModPortalReleaseSchema, ModPortalDetailsSchema, ModNameVersionPair } from "./data/messages_mod";
|
||||
import { ModInfo, ModPack, MajorMinorVersion, ModVersionEquality, GameVersion } from "./data";
|
||||
import { ModInfo, ModPack, MajorMinorVersion, ModVersionEquality, SourceVersion } from "./data";
|
||||
|
||||
export interface ModStoreEvents {
|
||||
/** A stored mod was created, updated or deleted */
|
||||
@@ -44,7 +44,7 @@ export default class ModStore extends events.EventEmitter<ModStoreEvents> {
|
||||
super();
|
||||
}
|
||||
|
||||
getMod(name: string, version: GameVersion, sha1?: string) {
|
||||
getMod(name: string, version: SourceVersion, sha1?: string) {
|
||||
const mod = this.files.get(ModInfo.filename(name, version));
|
||||
if (!mod || sha1 && sha1 !== mod.sha1) {
|
||||
return undefined;
|
||||
@@ -86,11 +86,11 @@ export default class ModStore extends events.EventEmitter<ModStoreEvents> {
|
||||
this.emit("change", modInfo);
|
||||
}
|
||||
|
||||
async loadMod(name: string, version: GameVersion) {
|
||||
async loadMod(name: string, version: SourceVersion) {
|
||||
return await this.loadFile(ModInfo.filename(name, version));
|
||||
}
|
||||
|
||||
async deleteMod(name: string, version: GameVersion) {
|
||||
async deleteMod(name: string, version: SourceVersion) {
|
||||
return await this.deleteFile(ModInfo.filename(name, version));
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { ModRecord } from "./ModPack";
|
||||
|
||||
import {
|
||||
MajorMinorVersion, MajorMinorVersionSchema, normaliseMajorMinorVersion, integerMajorMinorVersion,
|
||||
GameVersion, GameVersionSchema, isGameVersion, normaliseGameVersion, integerGameVersion,
|
||||
SourceVersion, SourceVersionSchema, isSourceVersion, normaliseSourceVersion, integerSourceVersion,
|
||||
ModVersionEquality,
|
||||
} from "./version";
|
||||
|
||||
@@ -133,18 +133,18 @@ export default class ModInfo {
|
||||
* it is only safe to use for building file names and identifiers; use
|
||||
* {@link integerVersion} to compare it.
|
||||
*/
|
||||
version = "0.0.0" as GameVersion;
|
||||
version = "0.0.0" as SourceVersion;
|
||||
|
||||
/**
|
||||
* Integer representation of the version, normalised the lenient way the
|
||||
* game reads it so it can be compared and sorted.
|
||||
*/
|
||||
get integerVersion() {
|
||||
return integerGameVersion(this.version);
|
||||
return integerSourceVersion(this.version);
|
||||
}
|
||||
|
||||
get normalisedVersion() {
|
||||
return normaliseGameVersion(this.version);
|
||||
return normaliseSourceVersion(this.version);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -227,7 +227,7 @@ export default class ModInfo {
|
||||
* @param version - Mod's version
|
||||
* @returns string containing {name}_{version}.zip
|
||||
*/
|
||||
static filename(name: string, version: GameVersion) {
|
||||
static filename(name: string, version: SourceVersion) {
|
||||
return `${name}_${version}.zip`;
|
||||
}
|
||||
|
||||
@@ -258,13 +258,13 @@ export default class ModInfo {
|
||||
// lenient format the game accepts; they are normalised when read in fromJSON.
|
||||
static infoJsonSchema = Type.Object({
|
||||
"name": Type.String(),
|
||||
"version": GameVersionSchema,
|
||||
"version": SourceVersionSchema,
|
||||
"title": Type.String(),
|
||||
"author": Type.String(),
|
||||
"contact": Type.Optional(Type.String()),
|
||||
"homepage": Type.Optional(Type.String()),
|
||||
"description": Type.Optional(Type.String()),
|
||||
"factorio_version": Type.Optional(GameVersionSchema),
|
||||
"factorio_version": Type.Optional(SourceVersionSchema),
|
||||
"dependencies": Type.Optional(Type.Array(Type.String())),
|
||||
});
|
||||
|
||||
@@ -287,7 +287,7 @@ export default class ModInfo {
|
||||
// info.json fields
|
||||
if (json.name) { modInfo.name = json.name; }
|
||||
if (json.version) {
|
||||
if (!isGameVersion(json.version)) {
|
||||
if (!isSourceVersion(json.version)) {
|
||||
throw new Error(`Invalid mod version "${json.version}"`);
|
||||
}
|
||||
modInfo.version = json.version;
|
||||
@@ -298,7 +298,7 @@ export default class ModInfo {
|
||||
if (json.homepage) { modInfo.homepage = json.homepage; }
|
||||
if (json.description) { modInfo.description = json.description; }
|
||||
if (json.factorio_version) {
|
||||
const factorioVersion = normaliseGameVersion(json.factorio_version);
|
||||
const factorioVersion = normaliseSourceVersion(json.factorio_version);
|
||||
if (factorioVersion === undefined) {
|
||||
throw new Error(`Invalid factorio_version "${json.factorio_version}"`);
|
||||
}
|
||||
@@ -332,7 +332,7 @@ export default class ModInfo {
|
||||
if (this.contact) { json.contact = this.contact; }
|
||||
if (this.homepage) { json.homepage = this.homepage; }
|
||||
if (this.description) { json.description = this.description; }
|
||||
if (this.factorioVersion !== "0.12") { json.factorio_version = this.factorioVersion as GameVersion; }
|
||||
if (this.factorioVersion !== "0.12") { json.factorio_version = this.factorioVersion as SourceVersion; }
|
||||
if (this.dependencies.length !== 1 || this.dependencies[0].name !== "base") {
|
||||
json.dependencies = this.dependencySpecifications;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import ModInfo, { ModDependencyUnsatisfiedReason } from "./ModInfo";
|
||||
|
||||
import {
|
||||
PartialVersion, PartialVersionSchema, integerPartialVersion,
|
||||
GameVersion, GameVersionSchema, normaliseFullVersion,
|
||||
SourceVersion, SourceVersionSchema, normaliseFullVersion,
|
||||
} from "./version";
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ export interface ModRecord {
|
||||
/** if mod is to be loaded. */
|
||||
enabled: boolean,
|
||||
/** version of the mod, verbatim as it appears in the mod's file name. */
|
||||
version: GameVersion,
|
||||
version: SourceVersion,
|
||||
/** SHA1 hash of the zip file. */
|
||||
sha1?: string,
|
||||
/** Used inside packages\web_ui\src\components\ModPackViewPage.tsx to define an error type. */
|
||||
@@ -61,7 +61,7 @@ export interface ModRecord {
|
||||
const ModRecordJsonSchema = Type.Object({
|
||||
"name": Type.String(),
|
||||
"enabled": Type.Boolean(),
|
||||
"version": GameVersionSchema,
|
||||
"version": SourceVersionSchema,
|
||||
"sha1": Type.Optional(Type.String()),
|
||||
});
|
||||
|
||||
@@ -434,7 +434,7 @@ export default class ModPack {
|
||||
* @return Built in mods for the given version
|
||||
*/
|
||||
static getBuiltinMods(factorioVersion: PartialVersion) {
|
||||
const version = normaliseFullVersion(factorioVersion) as GameVersion;
|
||||
const version = normaliseFullVersion(factorioVersion) as SourceVersion;
|
||||
const integerVersion = integerPartialVersion(factorioVersion);
|
||||
let defaultMods: ModRecord[] = [
|
||||
// "core" not included because core cannot be disabled
|
||||
|
||||
@@ -5,7 +5,7 @@ import { JsonString, jsonArray } from "./composites";
|
||||
|
||||
import {
|
||||
MajorMinorVersion, MajorMinorVersionSchema, normaliseMajorMinorVersion,
|
||||
GameVersion, GameVersionSchema,
|
||||
SourceVersion, SourceVersionSchema,
|
||||
ModVersionEquality,
|
||||
} from "./version";
|
||||
|
||||
@@ -119,13 +119,13 @@ export class ModGetRequest {
|
||||
|
||||
constructor(
|
||||
public name: string,
|
||||
public version: GameVersion,
|
||||
public version: SourceVersion,
|
||||
public sha1?: string,
|
||||
) { }
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
"name": Type.String(),
|
||||
"version": GameVersionSchema,
|
||||
"version": SourceVersionSchema,
|
||||
"sha1": Type.Optional(Type.String()),
|
||||
});
|
||||
|
||||
@@ -205,9 +205,9 @@ export class ModSearchRequest {
|
||||
|
||||
// Define the structure for the latest release info from the portal
|
||||
export const ModPortalReleaseSchema = Type.Object({
|
||||
version: GameVersionSchema,
|
||||
version: SourceVersionSchema,
|
||||
// Match the structure from ModStore's ModRelease/ModDetails
|
||||
info_json: Type.Object({ factorio_version: GameVersionSchema }),
|
||||
info_json: Type.Object({ factorio_version: SourceVersionSchema }),
|
||||
released_at: Type.String(), // ISO 8601 date string
|
||||
download_url: Type.String(),
|
||||
file_name: Type.String(),
|
||||
@@ -276,13 +276,13 @@ export class ModDownloadRequest {
|
||||
|
||||
constructor(
|
||||
public name: string,
|
||||
public version: GameVersion,
|
||||
public version: SourceVersion,
|
||||
public sha1?: string,
|
||||
) { }
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
"name": Type.String(),
|
||||
"version": GameVersionSchema,
|
||||
"version": SourceVersionSchema,
|
||||
"sha1": Type.Optional(Type.String()),
|
||||
});
|
||||
|
||||
@@ -302,12 +302,12 @@ export class ModDeleteRequest {
|
||||
|
||||
constructor(
|
||||
public name: string,
|
||||
public version: GameVersion,
|
||||
public version: SourceVersion,
|
||||
) { }
|
||||
|
||||
static jsonSchema = Type.Object({
|
||||
"name": Type.String(),
|
||||
"version": GameVersionSchema,
|
||||
"version": SourceVersionSchema,
|
||||
});
|
||||
|
||||
static fromJSON(json: Static<typeof this.jsonSchema>) {
|
||||
|
||||
@@ -36,20 +36,24 @@ export const ApiVersions = ["0.13", "0.14", "0.15", "0.16", "0.17", "0.18", "1.0
|
||||
* optional, and any trailing content is ignored. The pattern is intentionally
|
||||
* not anchored at the end.
|
||||
*/
|
||||
const gameVersionRegExp = /^\s*(\d+)\.\s*(\d+)(?:\.\s*(\d+))?/;
|
||||
const sourceVersionRegExp = /^\s*(\d+)\.\s*(\d+)(?:\.\s*(\d+))?/;
|
||||
|
||||
/**
|
||||
* A raw, un-normalised version string exactly as the game reads it, such as a
|
||||
* mod's version taken from info.json or a mod file name.
|
||||
*/
|
||||
declare const gameVersionSymbol: unique symbol;
|
||||
export type GameVersion = string & { [gameVersionSymbol]: void };
|
||||
export const GameVersionSchema = Type.Unsafe<GameVersion>(
|
||||
Type.String({ pattern: gameVersionRegExp.source })
|
||||
declare const sourceVersionSymbol: unique symbol;
|
||||
export type SourceVersion = string & { [sourceVersionSymbol]: void };
|
||||
export const SourceVersionSchema = Type.Unsafe<SourceVersion>(
|
||||
Type.String({ pattern: sourceVersionRegExp.source })
|
||||
);
|
||||
|
||||
export function isGameVersion(input: string): input is GameVersion {
|
||||
return gameVersionRegExp.test(input);
|
||||
export function isSourceVersion(input: string): input is SourceVersion {
|
||||
return sourceVersionRegExp.test(input);
|
||||
}
|
||||
|
||||
export function integerSourceVersion(version: SourceVersion) {
|
||||
return integerFullVersion(normaliseSourceVersion(version));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,21 +64,17 @@ export function isGameVersion(input: string): input is GameVersion {
|
||||
* @returns The normalised full version, or undefined if no major and minor
|
||||
* could be read.
|
||||
*/
|
||||
export function normaliseGameVersion(input: GameVersion): FullVersion;
|
||||
export function normaliseGameVersion(input: string): FullVersion | undefined;
|
||||
export function normaliseSourceVersion(input: SourceVersion): FullVersion;
|
||||
export function normaliseSourceVersion(input: string): FullVersion | undefined;
|
||||
|
||||
export function normaliseGameVersion(input: string | GameVersion): FullVersion | undefined {
|
||||
const match = gameVersionRegExp.exec(input);
|
||||
export function normaliseSourceVersion(input: string | SourceVersion): FullVersion | undefined {
|
||||
const match = sourceVersionRegExp.exec(input);
|
||||
if (match === null) {
|
||||
return undefined;
|
||||
}
|
||||
return `${Number(match[1])}.${Number(match[2])}.${Number(match[3] ?? "0")}` as FullVersion;
|
||||
}
|
||||
|
||||
export function integerGameVersion(version: GameVersion) {
|
||||
return integerFullVersion(normaliseGameVersion(version));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches valid mod versions, where all parts are specified.
|
||||
*/
|
||||
@@ -213,8 +213,8 @@ export class ModVersionEquality {
|
||||
}
|
||||
}
|
||||
|
||||
testVersion(version: GameVersion) {
|
||||
return this.testIntegerVersion(integerGameVersion(version));
|
||||
testVersion(version: SourceVersion) {
|
||||
return this.testIntegerVersion(integerSourceVersion(version));
|
||||
}
|
||||
|
||||
toString() {
|
||||
@@ -276,11 +276,11 @@ export class ModVersionRange {
|
||||
return this.minVersion.testIntegerVersion(other) && this.maxVersion.testIntegerVersion(other);
|
||||
}
|
||||
|
||||
testVersion(version: PartialVersion | GameVersion) {
|
||||
testVersion(version: PartialVersion | SourceVersion) {
|
||||
if (isPartialVersion(version)) {
|
||||
return this.testIntegerVersion(integerPartialVersion(version));
|
||||
}
|
||||
return this.testIntegerVersion(integerGameVersion(version));
|
||||
return this.testIntegerVersion(integerSourceVersion(version));
|
||||
}
|
||||
|
||||
combineVersion(other: ModVersionEquality) {
|
||||
|
||||
@@ -164,13 +164,16 @@ function SearchModsButton() {
|
||||
const handleControllerDownload = (
|
||||
modName: string,
|
||||
modTitle: string | undefined,
|
||||
modVersion: lib.GameVersion | undefined,
|
||||
modVersion: lib.SourceVersion | undefined,
|
||||
portalFactorioVersion: lib.MajorMinorVersion,
|
||||
) => {
|
||||
if (modVersion) {
|
||||
control.send(
|
||||
new lib.ModPortalDownloadRequest(
|
||||
[{ name: modName, version: new lib.ModVersionEquality("=", lib.normaliseGameVersion(modVersion))}],
|
||||
[{
|
||||
name: modName,
|
||||
version: new lib.ModVersionEquality("=", lib.normaliseSourceVersion(modVersion)),
|
||||
}],
|
||||
portalFactorioVersion
|
||||
)
|
||||
).then(() => {
|
||||
|
||||
@@ -17,25 +17,25 @@ describe("lib/data/version", function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
describe("normaliseGameVersion()", function() {
|
||||
describe("normaliseSourceVersion()", function() {
|
||||
it("should normalise lenient version strings the way the game reads them", function() {
|
||||
// Major and minor required, patch optional and defaulting to 0.
|
||||
assert.equal(lib.normaliseGameVersion("1.1"), "1.1.0");
|
||||
assert.equal(lib.normaliseGameVersion("1.1.50"), "1.1.50");
|
||||
assert.equal(lib.normaliseGameVersion("0.18"), "0.18.0");
|
||||
assert.equal(lib.normaliseSourceVersion("1.1"), "1.1.0");
|
||||
assert.equal(lib.normaliseSourceVersion("1.1.50"), "1.1.50");
|
||||
assert.equal(lib.normaliseSourceVersion("0.18"), "0.18.0");
|
||||
// Leading whitespace and zeros are dropped.
|
||||
assert.equal(lib.normaliseGameVersion(" 1.1"), "1.1.0");
|
||||
assert.equal(lib.normaliseGameVersion("01.02.03"), "1.2.3");
|
||||
assert.equal(lib.normaliseGameVersion("1. 1. 50"), "1.1.50");
|
||||
assert.equal(lib.normaliseSourceVersion(" 1.1"), "1.1.0");
|
||||
assert.equal(lib.normaliseSourceVersion("01.02.03"), "1.2.3");
|
||||
assert.equal(lib.normaliseSourceVersion("1. 1. 50"), "1.1.50");
|
||||
// Anything after the patch (or a non-numeric patch) is ignored.
|
||||
assert.equal(lib.normaliseGameVersion("1.1.50-beta"), "1.1.50");
|
||||
assert.equal(lib.normaliseGameVersion("1.1.x"), "1.1.0");
|
||||
assert.equal(lib.normaliseGameVersion("1.1.50.60"), "1.1.50");
|
||||
assert.equal(lib.normaliseSourceVersion("1.1.50-beta"), "1.1.50");
|
||||
assert.equal(lib.normaliseSourceVersion("1.1.x"), "1.1.0");
|
||||
assert.equal(lib.normaliseSourceVersion("1.1.50.60"), "1.1.50");
|
||||
});
|
||||
it("should return undefined when no major.minor can be read", function() {
|
||||
const invalid = ["1", "", "latest", "abc", ".1.1", "x.y"];
|
||||
for (const test of invalid) {
|
||||
assert.equal(lib.normaliseGameVersion(test), undefined, test);
|
||||
assert.equal(lib.normaliseSourceVersion(test), undefined, test);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user