cleanup comments, update translations, bump to 0.4.1
This commit is contained in:
parent
9edcc9841b
commit
7d8ab87eee
28 changed files with 412 additions and 1114 deletions
|
|
@ -7,9 +7,8 @@ const { rewireSymlinks } = require('./symlinks')
|
|||
const { removeTree, treeSize } = require('./fsutil')
|
||||
const { normalizePathName } = require('./names')
|
||||
|
||||
// An app path stored relative to its PREFIX ROOT ("drive_c/..." for plain
|
||||
// wine, "pfx/drive_c/..." for Proton-managed prefixes): wine resolves it
|
||||
// under C:\, everything else is FILES-relative or absolute.
|
||||
// An app path stored relative to its prefix root ("drive_c/..." or
|
||||
// "pfx/drive_c/..."); everything else is FILES-relative or absolute.
|
||||
const PREFIX_REL_RE = /^(pfx[/\\])?drive_c([/\\]|$)/i
|
||||
const isPrefixRel = v => typeof v === 'string' && PREFIX_REL_RE.test(v)
|
||||
|
||||
|
|
@ -48,12 +47,8 @@ function prefixExists(name) {
|
|||
}
|
||||
}
|
||||
|
||||
// Every Windows C: drive a prefix has: plain wine keeps one at the top
|
||||
// (WINEPREFIX=<prefix>), legacy Proton-managed prefixes nest one under pfx/
|
||||
// (WINEPREFIX=<prefix>/pfx). A prefix used with BOTH wine kinds has both, and
|
||||
// an import may come from either one - so callers that can accept several get
|
||||
// them all, top level first. A unified prefix (pfx -> .) reaches the same
|
||||
// drive twice; it is reported once.
|
||||
// Every Windows C: drive a prefix has (top-level for plain wine, under pfx/
|
||||
// for Proton); a unified prefix reports its single drive once.
|
||||
function prefixDriveRoots(name) {
|
||||
const root = prefixPath(name)
|
||||
const found = []
|
||||
|
|
@ -79,22 +74,9 @@ function lstatOrNull(p) {
|
|||
}
|
||||
}
|
||||
|
||||
// Wine keeps its C: drive at <prefix>/drive_c, Proton always runs its prefix
|
||||
// from <compatdata>/pfx - and PLWL points compatdata at the launcher's prefix
|
||||
// folder, so without a link a prefix used with both wine kinds grows TWO C:
|
||||
// drives with separate registries, saves and installed DLLs. Making `pfx` a
|
||||
// relative symlink back to the prefix itself collapses them: Proton's
|
||||
// <compatdata>/pfx resolves to the prefix root, the exact folder wine uses.
|
||||
// Every walker PLWL owns (fsutil, symlinks, LAN sync) treats symlinks as
|
||||
// links and never follows them, so the self-reference is safe.
|
||||
//
|
||||
// Only a prefix that has no pfx AT ALL gets the link - that covers a fresh
|
||||
// prefix and a plain-wine prefix first used through Proton. An existing
|
||||
// layout is left exactly as it is: a prefix from an older PLWL keeps its real
|
||||
// pfx/ folder (and here the two wine kinds keep two C: drives), and a prefix
|
||||
// with both real drive_c trees keeps them - moving Windows installs around
|
||||
// behind the user's back loses data and breaks the absolute/relative links
|
||||
// inside them.
|
||||
// Without a link, a prefix used with both wine kinds grows two C: drives;
|
||||
// `pfx` -> prefix root collapses them. Only a prefix with no pfx at all gets
|
||||
// the link - an existing layout is left exactly as it is.
|
||||
function ensureUnifiedPrefix(name) {
|
||||
if (!name) return false
|
||||
const pfx = path.join(prefixPath(name), 'pfx')
|
||||
|
|
@ -108,12 +90,8 @@ function ensureUnifiedPrefix(name) {
|
|||
}
|
||||
}
|
||||
|
||||
// True when a path IS one of a prefix's own roots: the prefix folder, its
|
||||
// pfx/ or either drive_c. A copy/move import of such a folder would move the
|
||||
// prefix's C: drive (or the whole prefix) into files/apps, gutting it - the
|
||||
// "import from a prefix" flow is the one that works in place. Both drive
|
||||
// layouts are checked literally, not through prefixDriveRoots(): a prefix used
|
||||
// with wine AND Proton has a drive_c each and BOTH are off limits.
|
||||
// True when a path IS one of a prefix's own roots (folder, pfx/, drive_c):
|
||||
// importing one would gut the prefix.
|
||||
function isPrefixRoot(p) {
|
||||
if (!p) return false
|
||||
const abs = path.resolve(String(p))
|
||||
|
|
@ -140,9 +118,7 @@ function createPrefix(name) {
|
|||
return { ok: true, name: clean }
|
||||
}
|
||||
|
||||
// A prefix is a whole windows drive - removal is measured before it starts
|
||||
// (staging) so the UI can show a bar that actually moves while the tree is
|
||||
// walked file by file (removeTree), instead of one blocking rmSync.
|
||||
// Removal is measured (staging) so the UI shows a bar that moves.
|
||||
async function deletePrefix(name, onProgress) {
|
||||
if (String(name).toLowerCase() === MAIN.toLowerCase()) return { ok: false, error: 'isMain' }
|
||||
const defs = listPrefixes()
|
||||
|
|
@ -158,19 +134,13 @@ async function deletePrefix(name, onProgress) {
|
|||
return { ok: true }
|
||||
}
|
||||
|
||||
// A prefix that arrived from another machine (or a launcher that was moved) is
|
||||
// full of absolute symlinks into its wine/proton build - fonts, built-in
|
||||
// program stubs, dlls. Rewire them to relative paths so the prefix keeps
|
||||
// working here and stays relocatable (same healing wine builds get on import).
|
||||
// Rewire absolute links to relative so a moved prefix keeps working.
|
||||
async function healPrefix(name) {
|
||||
if (!name) return 0
|
||||
return rewireSymlinks(prefixPath(name), [DIRS.FILES])
|
||||
}
|
||||
|
||||
// Renaming a prefix moves its folder on disk and follows the name into the
|
||||
// registry (default included) and every app that runs in it. Prefix imports
|
||||
// keep their stored paths (they are relative to the prefix root), so only the
|
||||
// reference changes - the files move with the folder.
|
||||
// Rename moves the folder and follows the name through the registry.
|
||||
function renamePrefix(oldName, newName) {
|
||||
const clean = normalizePathName(newName)
|
||||
if (!clean) return { ok: false, error: 'invalidName' }
|
||||
|
|
@ -180,8 +150,7 @@ function renamePrefix(oldName, newName) {
|
|||
if (entry.locked || String(oldName).toLowerCase() === MAIN.toLowerCase()) return { ok: false, error: 'isMain' }
|
||||
if (clean === oldName) return { ok: true, name: clean, games: 0 }
|
||||
if (defs.prefixes.some(p => p.name === clean) || fs.existsSync(prefixPath(clean))) return { ok: false, error: 'alreadyExists' }
|
||||
// a registered prefix whose folder wine has not created yet can still be
|
||||
// renamed - only the registry entry exists
|
||||
// a registered prefix without a folder yet can still be renamed
|
||||
if (fs.existsSync(prefixPath(oldName))) {
|
||||
try {
|
||||
fs.renameSync(prefixPath(oldName), prefixPath(clean))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue