Readd support for direct installs

This commit is contained in:
Cooldude2606 committed 2026-02-05 14:30:48 +00:00
1 parent 4cbc30f627
commit b4338a209c
4 files changed
+103 -69

No files matched your search

-26
View File
@@ -25,7 +25,6 @@ import * as lib from "@clusterio/lib";
import { ConsoleTransport, levels, logger } from "@clusterio/lib";
import Host from "./src/Host";
import { getFactorioVersion } from "./src/server";
let host: Host | undefined;
@@ -237,31 +236,6 @@ async function startHost() {
tlsCa = await fs.readFile(tlsCaPath, "utf8");
}
// Migrate from single factorio version to multiple
const factorioDir = hostConfig.get("host.factorio_directory");
const singleFactorioVersion = await getFactorioVersion(factorioDir);
if (singleFactorioVersion !== null) {
const dst = path.join(factorioDir, singleFactorioVersion);
logger.info(`Found single factorio version in ${factorioDir} moving to ${dst}`);
const stats = await fs.lstat(factorioDir);
if (stats.isSymbolicLink()) {
// For symlinks we want to move the file, but cant move it into itself so need a tmp move
const tmpPath = `${factorioDir}.tmp`;
await fs.move(factorioDir, tmpPath);
await fs.ensureDir(factorioDir);
await fs.move(tmpPath, dst);
} else {
// It is a directory here, otherwise no version would have been found
// We will only move known files in case a version was incorrectly installed in the dir
await fs.ensureDir(dst);
await Promise.all(
["bin", "data", "config-path.cfg"].map(name => (
fs.move(path.join(factorioDir, name), path.join(dst, name))
))
);
}
}
let hostConnector = new HostConnector(hostConfig, tlsCa, pluginInfos);
host = new Host(
hostConnector,
+32 -12
View File
@@ -18,7 +18,7 @@ const execFileAsync = util.promisify(child_process.execFile);
*
* @param factorioDir - Path factorio dir containing data/changelog.txt.
*/
export async function getFactorioVersion(factorioDir: string) {
async function getFactorioVersion(factorioDir: string) {
let changelog;
const changelogPath = path.join(factorioDir, "data", "changelog.txt");
try {
@@ -35,7 +35,8 @@ export async function getFactorioVersion(factorioDir: string) {
if (index !== -1) {
const name = line.slice(0, index).trim();
if (name.toLowerCase() === "version") {
return line.slice(index + 1).trim();
const version = line.slice(index + 1).trim();
return lib.isFullVersion(version) ? version : null;
}
}
}
@@ -77,6 +78,12 @@ function versionOrder(a: string, b: string) {
async function listFactorioVersions(factorioDir: string) {
const versions = new Set<lib.FullVersion>();
const directVersion = await getFactorioVersion(factorioDir);
if (directVersion !== null) {
versions.add(directVersion);
return { direct: true, versions };
}
for (const name of await fs.readdir(factorioDir)) {
// We do not use withFileTypes or lstat because we want to follow symlinks
const fullPath = path.join(factorioDir, name);
@@ -90,14 +97,14 @@ async function listFactorioVersions(factorioDir: string) {
}
const version = await getFactorioVersion(fullPath);
if (version === null || !lib.isFullVersion(version)) {
if (version === null) {
continue;
}
versions.add(version);
}
return versions;
return { direct: false, versions };
}
/**
@@ -178,6 +185,16 @@ async function downloadAndExtractTar(url: string, targetDir: string) {
* @internal
*/
async function findVersion(factorioDir: string, targetVersion: lib.TargetVersion): Promise<[string, lib.FullVersion]> {
// Check if this is a direct installation dir
const directVersion = await getFactorioVersion(factorioDir);
if (directVersion !== null) {
if (targetVersion === "latest" || directVersion === targetVersion || directVersion.startsWith(targetVersion)) {
return [path.join(factorioDir, "data"), directVersion];
}
throw new Error(`Unable to find Factorio version ${targetVersion}`);
}
// Otherwise assume it is a directory of multiple versions
const versions = new Map<lib.FullVersion, string>();
for (const name of await fs.readdir(factorioDir)) {
// We do not use withFileTypes or lstat because we want to follow symlinks
@@ -192,7 +209,7 @@ async function findVersion(factorioDir: string, targetVersion: lib.TargetVersion
}
const version = await getFactorioVersion(fullPath);
if (version === null || !lib.isFullVersion(version)) {
if (version === null) {
continue;
}
@@ -973,16 +990,18 @@ export class FactorioServer extends events.EventEmitter<FactorioServerEvents> {
[0];
const installedVersions = await listFactorioVersions(this._factorioDir);
if (!installedVersions.has(latestVersion.version)) {
// Download the newer version
if (!installedVersions.versions.has(latestVersion.version)) {
const v = latestVersion.version;
if (process.platform === "linux") {
this._logger.info(`A newer version of factorio is available (${v}), starting download...`);
const dst = path.join(this._factorioDir, latestVersion.version);
await downloadAndExtractTar(latestVersion.headlessUrl, dst);
} else {
// Can't download if not linux or this is a direct install
if (installedVersions.direct || process.platform !== "linux") {
this._logger.info(`A newer version of factorio is available (${v}) but must be manually downloaded`);
}
// Download the newer version
this._logger.info(`A newer version of factorio is available (${v}), starting download...`);
const dst = path.join(this._factorioDir, latestVersion.version);
await downloadAndExtractTar(latestVersion.headlessUrl, dst);
this._logger.info(`Downloaded factorio version ${v}`);
}
}
@@ -1536,6 +1555,7 @@ export class FactorioServer extends events.EventEmitter<FactorioServerEvents> {
// For testing only
export const _getFactorioVersion = getFactorioVersion;
export const _versionOrder = versionOrder;
export const _findVersion = findVersion;
export const _listFactorioVersions = listFactorioVersions;
+68 -28
View File
@@ -11,17 +11,17 @@ const { testLines } = require("../lib/factorio/lines");
describe("host/server", function() {
describe("getFactorioVersion()", function() {
describe("_getFactorioVersion()", function() {
it("should get the version from a changelog", async function() {
let version = await hostServer.getFactorioVersion(path.join("test", "file", "changelogs", "good"));
let version = await hostServer._getFactorioVersion(path.join("test", "file", "changelogs", "good"));
assert.equal(version, "0.1.1");
});
it("should return null if unable to find the version", async function() {
let version = await hostServer.getFactorioVersion(path.join("test", "file", "changelogs", "bad"));
let version = await hostServer._getFactorioVersion(path.join("test", "file", "changelogs", "bad"));
assert.equal(version, null);
});
it("should return null if file does not exist", async function() {
let version = await hostServer.getFactorioVersion(path.join("test", "file", "changelogs", "not-exists"));
let version = await hostServer._getFactorioVersion(path.join("test", "file", "changelogs", "not-exists"));
assert.equal(version, null);
});
});
@@ -38,30 +38,59 @@ describe("host/server", function() {
});
describe("_findVersion()", function() {
it("should search given directory for latest Factorio install", async function() {
const installDir = path.join("test", "file", "factorio");
const [dir, version] = await hostServer._findVersion(installDir, "latest");
assert.equal(dir, path.join(installDir, "0.1.2", "data"));
assert.equal(version, "0.1.2");
describe("direct install", function() {
it("should search given directory for latest Factorio install", async function() {
const installDir = path.join("test", "file", "factorio", "0.1.2");
const [dir, version] = await hostServer._findVersion(installDir, "latest");
assert.equal(dir, path.join(installDir, "data"));
assert.equal(version, "0.1.2");
});
it("should search given directory for given Factorio install", async function() {
const installDir = path.join("test", "file", "factorio", "0.1.1");
const [dir, version] = await hostServer._findVersion(installDir, "0.1.1");
assert.equal(dir, path.join(installDir, "data"));
assert.equal(version, "0.1.1");
});
it("should search given directory for partly given Factorio install", async function() {
const installDir = path.join("test", "file", "factorio", "0.1.2");
const [dir, version] = await hostServer._findVersion(installDir, "0.1");
assert.equal(dir, path.join(installDir, "data"));
assert.equal(version, "0.1.2");
});
it("should search given directory for latest Factorio install", async function() {
const installDir = path.join("test", "file", "factorio");
const [dir, version] = await hostServer._findVersion(installDir, "latest");
assert.equal(dir, path.join(installDir, "0.1.2", "data"));
assert.equal(version, "0.1.2");
});
});
it("should search given directory for given Factorio install", async function() {
const installDir = path.join("test", "file", "factorio");
const [dir, version] = await hostServer._findVersion(installDir, "0.1.1");
assert.equal(dir, path.join(installDir, "0.1.1", "data"));
assert.equal(version, "0.1.1");
});
it("should search given directory for partly given Factorio install", async function() {
const installDir = path.join("test", "file", "factorio");
const [dir, version] = await hostServer._findVersion(installDir, "0.1");
assert.equal(dir, path.join(installDir, "0.1.2", "data"));
assert.equal(version, "0.1.2");
});
it("should reject if no factorio install with the given version was found", async function() {
let installDir = path.join("test", "file", "factorio");
await assert.rejects(
hostServer._findVersion(installDir, "0.1.3"),
new Error("Unable to find Factorio version 0.1.3")
);
describe("mutli install", function() {
it("should reject if no factorio install with the given version was found", async function() {
let installDir = path.join("test", "file", "factorio");
await assert.rejects(
hostServer._findVersion(installDir, "0.1.3"),
new Error("Unable to find Factorio version 0.1.3")
);
});
it("should search given directory for given Factorio install", async function() {
const installDir = path.join("test", "file", "factorio");
const [dir, version] = await hostServer._findVersion(installDir, "0.1.1");
assert.equal(dir, path.join(installDir, "0.1.1", "data"));
assert.equal(version, "0.1.1");
});
it("should search given directory for partly given Factorio install", async function() {
const installDir = path.join("test", "file", "factorio");
const [dir, version] = await hostServer._findVersion(installDir, "0.1");
assert.equal(dir, path.join(installDir, "0.1.2", "data"));
assert.equal(version, "0.1.2");
});
it("should reject if no factorio install with the given version was found", async function() {
let installDir = path.join("test", "file", "factorio");
await assert.rejects(
hostServer._findVersion(installDir, "0.1.3"),
new Error("Unable to find Factorio version 0.1.3")
);
});
});
it("should reject if no factorio install was found", async function() {
let installDir = path.join("test", "file");
@@ -73,10 +102,21 @@ describe("host/server", function() {
});
describe("_listFactorioVersions()", function() {
it("should list the version in a direct install", async function() {
const installDir = path.join("test", "file", "factorio", "0.1.1");
const installedVersions = await hostServer._listFactorioVersions(installDir);
assert.deepEqual(installedVersions, {
direct: true,
versions: new Set(["0.1.1"]),
});
});
it("should list all versions in a directory", async function() {
const installDir = path.join("test", "file", "factorio");
const installedVersions = await hostServer._listFactorioVersions(installDir);
assert.deepEqual(installedVersions, new Set(["0.1.1", "0.1.2"]));
assert.deepEqual(installedVersions, {
direct: false,
versions: new Set(["0.1.1", "0.1.2"]),
});
});
});
+3 -3
View File
@@ -5,7 +5,7 @@ const fs = require("fs-extra");
const path = require("path");
const lib = require("@clusterio/lib");
const { FactorioServer, getFactorioVersion } = require("@clusterio/host/dist/node/src/server");
const { FactorioServer, _getFactorioVersion } = require("@clusterio/host/dist/node/src/server");
const { logger } = lib;
const { slowTest, factorioDir } = require("./index");
@@ -20,7 +20,7 @@ describe("Integration of host/src/server", function() {
}
}
let version = await getFactorioVersion(factorioDir);
let version = await _getFactorioVersion(factorioDir);
if (version !== null) {
checkVersion(version);
} else {
@@ -30,7 +30,7 @@ describe("Integration of host/src/server", function() {
}
checkVersion(
await getFactorioVersion(path.join(factorioDir, entry.name))
await _getFactorioVersion(path.join(factorioDir, entry.name))
);
}
}