Refuse a game folder whose path leaves no room for the game's files.

Windows and the build tools stop at 260 characters for a file's whole path, and a built game needs up to 128 below
its folder. A deeper folder made the build stop in the middle with a file "not found"; Begin Installation and the
install job now refuse it first and name both lengths.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
chrg6
2026-11-12 22:24:26 -05:00
parent 0a85e33e0f
commit 8c32aedabb
5 changed files with 71 additions and 1 deletions

View File

@@ -9,7 +9,7 @@ import threading
import time
import traceback
from . import build, feed, gamefiles, locks, net, toolchain, updater, versions, winsys
from . import build, feed, gamefiles, locks, net, paths, toolchain, updater, versions, winsys
RECHECK = 3600 # seconds between update checks while the launcher stays open, hidden during play included
@@ -456,6 +456,9 @@ class InstallJob(Job):
return build.install_args(self.ctx.layout, self.dump, self.game_dir)
def run(self):
too_long = paths.long_path_problem(self.game_dir) # the window asks first (begin_install); the command line here
if too_long:
raise build.BuildError(too_long)
self.ensure_tools('tools')
self.make_game(self.args(),
{s: s for s in ('check', 'exefs', 'romfs', 'lift', 'compile', 'shaders', 'prompts', 'scan')})

View File

@@ -38,6 +38,29 @@ def ansi_safe(path):
return False
# Windows: a file's whole path may be 259 characters for the programs that do not ask for more, and the build's tools
# (the MSYS2 compiler, linker and resource compiler, tar) are among them whatever the system's long path setting.
# LONGEST_IN_GAME is the room the game folder's own files need below it: the longest path a built game folder held
# was 106 characters (romfs-patches-playstation-label\System\Resource\ResourceSizeTable...rsizetable.zs), and a file
# is written under a temporary name up to 22 characters longer before it gets its own.
WINDOWS_PATH_MAX = 259
LONGEST_IN_GAME = 128
def long_path_problem(game_dir):
"""'' when the files of a game built into game_dir fit Windows' path length, else the sentence that says how long
the folder's path is and how long it may be. Always '' elsewhere. Without it a build into a deep folder stops
somewhere in the middle with "file not found" for a file that is there."""
if os.name != 'nt' or not game_dir:
return ''
n, most = len(os.path.abspath(str(game_dir))), WINDOWS_PATH_MAX - 1 - LONGEST_IN_GAME
if n <= most:
return ''
return (f'the path of the game folder is {n} characters long, and the game\'s files need {LONGEST_IN_GAME} more: '
f'Windows and the build tools stop at {WINDOWS_PATH_MAX + 1} for a file\'s whole path. Choose a folder '
f'whose path has at most {most} characters, such as D:\\Games\\NX2navi')
def fixed_drive(drive):
"""True when drive (X:\\) is a fixed disk (GetDriveTypeW DRIVE_FIXED), not a network, removable or optical drive.
True where that cannot be asked."""

View File

@@ -39,6 +39,7 @@ from tkinter import filedialog
from .. import NAME, build, feed, gameini, gamefiles, jobs, locks, mods, saves, steam, versions, winsys
from ..context import Context
from ..paths import long_path_problem
from . import art, picture, sound
W, H = 1000, 640
@@ -966,6 +967,11 @@ class App:
self.choose_dump()
return
gd = self.game_dir()
too_long = long_path_problem(gd) # told here, not as a missing file halfway through the build
if too_long:
self.message = App.friendly(too_long)
self.render()
return
drop_partial_image(gd) # before the free space is measured
if free_gb(gd) < 34 and not (Path(gd) / 'romfs' / 'romfs.bin').is_file():
self.message = f'{drive_of(gd)} has {free_gb(gd):.0f} GB free; the game needs about 34 GB.'