init
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
// About me: Writes the missing Steam libraryfolders.vdf into a Wine prefix from
|
||||
// the Linux side, before Vortex is ever started. Vortex core scans Steam at
|
||||
// startup and reads C:\Program Files (x86)\Steam\config\libraryfolders.vdf; when
|
||||
// SteamTinkerLaunch has not created it, the unhandled ENOENT shows up as
|
||||
// "unrecoverable error" and Vortex dies. Running this once repairs the prefix.
|
||||
//
|
||||
// Usage: node scripts/repair-prefix.mjs [--prefix <pfx>] [--force] [--dry-run]
|
||||
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, writeFileSync } from 'node:fs';
|
||||
import { homedir } from 'node:os';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
import { findSteamLibraries, findSteamRoots } from '../src/discovery.ts';
|
||||
import {
|
||||
PREFIX_STEAM_DIR,
|
||||
buildShimVdf,
|
||||
dedupeByCanonicalPath,
|
||||
ensureSteamShim,
|
||||
} from '../src/steamShim.ts';
|
||||
|
||||
const DEFAULT_PREFIX = resolve(homedir(), '.config/steamtinkerlaunch/vortex/compatdata/pfx');
|
||||
|
||||
function parseArgs(argv) {
|
||||
const args = { prefix: DEFAULT_PREFIX, force: false, dryRun: false };
|
||||
for (let i = 0; i < argv.length; i += 1) {
|
||||
if (argv[i] === '--prefix') {
|
||||
args.prefix = resolve(argv[i + 1] ?? '');
|
||||
i += 1;
|
||||
} else if (argv[i] === '--force') {
|
||||
args.force = true;
|
||||
} else if (argv[i] === '--dry-run') {
|
||||
args.dryRun = true;
|
||||
} else {
|
||||
throw new Error(`unknown argument: ${argv[i]}`);
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the paths Vortex would see inside the prefix to real Linux paths:
|
||||
* Z: is the Linux root, C: is the prefix's drive_c.
|
||||
*/
|
||||
function toRealPath(prefix, winPath) {
|
||||
const normalised = winPath.replace(/\\/g, '/');
|
||||
if (/^[zZ]:/.test(normalised)) {
|
||||
return normalised.slice(2) || '/';
|
||||
}
|
||||
if (/^[cC]:/.test(normalised)) {
|
||||
return resolve(prefix, 'drive_c', normalised.slice(3));
|
||||
}
|
||||
return normalised;
|
||||
}
|
||||
|
||||
function prefixFileAccess(prefix) {
|
||||
return {
|
||||
exists: (p) => existsSync(toRealPath(prefix, p)),
|
||||
readFile: (p) => readFileSync(toRealPath(prefix, p), 'utf8'),
|
||||
readDir: (p) => {
|
||||
try {
|
||||
return readdirSync(toRealPath(prefix, p));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const args = parseArgs(process.argv.slice(2));
|
||||
|
||||
if (!existsSync(args.prefix)) {
|
||||
console.error(`prefix not found: ${args.prefix}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const files = prefixFileAccess(args.prefix);
|
||||
|
||||
// Only the Wine-side (Z:) view is useful here: the shim has to contain paths
|
||||
// Vortex can open from inside the prefix.
|
||||
const libraries = dedupeByCanonicalPath(
|
||||
[
|
||||
...new Set(
|
||||
findSteamRoots(files)
|
||||
.filter((root) => root.startsWith('Z:'))
|
||||
.flatMap((root) => findSteamLibraries(files, root)),
|
||||
),
|
||||
],
|
||||
(candidate) => realpathSync(toRealPath(args.prefix, candidate)),
|
||||
);
|
||||
|
||||
console.log(`prefix: ${args.prefix}`);
|
||||
console.log(`steam dir: ${toRealPath(args.prefix, PREFIX_STEAM_DIR)}`);
|
||||
console.log(`libraries: ${libraries.length === 0 ? '(none found)' : ''}`);
|
||||
for (const library of libraries) {
|
||||
console.log(` ${library}`);
|
||||
}
|
||||
|
||||
if (args.dryRun) {
|
||||
console.log('--- shim that would be written ---');
|
||||
console.log(buildShimVdf(libraries));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const writer = {
|
||||
makeDir: (p) => mkdirSync(toRealPath(args.prefix, p), { recursive: true }),
|
||||
writeFile: (p, contents) => writeFileSync(toRealPath(args.prefix, p), contents, 'utf8'),
|
||||
};
|
||||
|
||||
const result = ensureSteamShim(files, writer, libraries, { overwrite: args.force });
|
||||
console.log(`result: ${result.action} -> ${toRealPath(args.prefix, result.path)}`);
|
||||
|
||||
if (result.action === 'skipped') {
|
||||
console.error(
|
||||
libraries.length === 0
|
||||
? 'no Steam libraries found under /home; pass --prefix for the right prefix or check your Steam install'
|
||||
: `no Steam directory at ${toRealPath(args.prefix, PREFIX_STEAM_DIR)}; is this the Vortex prefix?`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
Reference in New Issue
Block a user