mirror of
https://github.com/derrod/legendary.git
synced 2025-02-26 15:36:45 +00:00
Also make verification and uninstallation case-insensitive if necessary
This also only enables case-insensitive file tasks if installing a Windows game
This commit is contained in:
parent
f08dbc4a62
commit
48b37d47cf
|
@ -1268,7 +1268,8 @@ class LegendaryCLI:
|
|||
|
||||
logger.info(f'Verifying "{igame.title}" version "{manifest.meta.build_version}"')
|
||||
repair_file = []
|
||||
for result, path, result_hash, bytes_read in validate_files(igame.install_path, file_list):
|
||||
for result, path, result_hash, bytes_read in validate_files(igame.install_path, file_list,
|
||||
case_insensitive=igame.platform.startswith('Win')):
|
||||
processed += bytes_read
|
||||
percentage = (processed / total_size) * 100.0
|
||||
num += 1
|
||||
|
|
|
@ -1498,7 +1498,7 @@ class LegendaryCore:
|
|||
|
||||
dlm = DLManager(install_path, base_url, resume_file=resume_file, status_q=status_q,
|
||||
max_shared_memory=max_shm * 1024 * 1024, max_workers=max_workers,
|
||||
dl_timeout=dl_timeout, bind_ip=bind_ip)
|
||||
dl_timeout=dl_timeout, bind_ip=bind_ip, case_insensitive=platform.startswith('Win'))
|
||||
anlres = dlm.run_analysis(manifest=new_manifest, old_manifest=old_manifest,
|
||||
patch=not disable_patching, resume=not force,
|
||||
file_prefix_filter=file_prefix_filter,
|
||||
|
@ -1697,7 +1697,8 @@ class LegendaryCore:
|
|||
fm.filename for fm in manifest.file_manifest_list.elements if
|
||||
not fm.install_tags or any(t in installed_game.install_tags for t in fm.install_tags)
|
||||
]
|
||||
if not delete_filelist(installed_game.install_path, filelist, delete_root_directory):
|
||||
if not delete_filelist(installed_game.install_path, filelist, delete_root_directory,
|
||||
case_insensitive=installed_game.platform.startswith('Win')):
|
||||
self.log.error(f'Deleting "{installed_game.install_path}" failed, please remove manually.')
|
||||
except Exception as e:
|
||||
self.log.error(f'Deleting failed with {e!r}, please remove {installed_game.install_path} manually.')
|
||||
|
@ -1717,7 +1718,10 @@ class LegendaryCore:
|
|||
and os.path.exists(os.path.join(installed_game.install_path, fm.filename))
|
||||
]
|
||||
|
||||
if not delete_filelist(installed_game.install_path, filelist):
|
||||
if not delete_filelist(
|
||||
installed_game.install_path, filelist,
|
||||
case_insensitive=installed_game.platform.startswith('Win')
|
||||
):
|
||||
self.log.warning(f'Deleting some deselected files failed, please check/remove manually.')
|
||||
|
||||
def prereq_installed(self, app_name):
|
||||
|
|
|
@ -22,7 +22,7 @@ from legendary.models.manifest import ManifestComparison, Manifest
|
|||
class DLManager(Process):
|
||||
def __init__(self, download_dir, base_url, cache_dir=None, status_q=None,
|
||||
max_workers=0, update_interval=1.0, dl_timeout=10, resume_file=None,
|
||||
max_shared_memory=1024 * 1024 * 1024, bind_ip=None):
|
||||
max_shared_memory=1024 * 1024 * 1024, bind_ip=None, case_insensitive=True):
|
||||
super().__init__(name='DLManager')
|
||||
self.log = logging.getLogger('DLM')
|
||||
self.proc_debug = False
|
||||
|
@ -42,6 +42,7 @@ class DLManager(Process):
|
|||
self.max_workers = max_workers or min(cpu_count() * 2, 16)
|
||||
self.dl_timeout = dl_timeout
|
||||
self.bind_ips = [] if not bind_ip else bind_ip.split(',')
|
||||
self.case_insensitive = case_insensitive
|
||||
|
||||
# Analysis stuff
|
||||
self.analysis = None
|
||||
|
@ -672,7 +673,8 @@ class DLManager(Process):
|
|||
|
||||
self.log.info('Starting file writing worker...')
|
||||
writer_p = FileWorker(self.writer_queue, self.writer_result_q, self.dl_dir,
|
||||
self.shared_memory.name, self.cache_dir, self.logging_queue)
|
||||
self.shared_memory.name, self.cache_dir, self.logging_queue,
|
||||
self.case_insensitive)
|
||||
self.children.append(writer_p)
|
||||
writer_p.start()
|
||||
|
||||
|
|
|
@ -148,7 +148,8 @@ class DLWorker(Process):
|
|||
|
||||
|
||||
class FileWorker(Process):
|
||||
def __init__(self, queue, out_queue, base_path, shm, cache_path=None, logging_queue=None):
|
||||
def __init__(self, queue, out_queue, base_path, shm, cache_path=None, logging_queue=None,
|
||||
case_insensitive: bool = True):
|
||||
super().__init__(name='FileWorker')
|
||||
self.q = queue
|
||||
self.o_q = out_queue
|
||||
|
@ -157,6 +158,7 @@ class FileWorker(Process):
|
|||
self.shm = SharedMemory(name=shm)
|
||||
self.log_level = logging.getLogger().level
|
||||
self.logging_queue = logging_queue
|
||||
self.case_insensitive = case_insensitive
|
||||
|
||||
def run(self):
|
||||
# we have to fix up the logger before we can start
|
||||
|
@ -189,7 +191,9 @@ class FileWorker(Process):
|
|||
|
||||
# make directories if required
|
||||
path, filename = os.path.split(j.filename)
|
||||
file_dir = case_insensitive_file_search(os.path.join(self.base_path, path))
|
||||
file_dir = os.path.join(self.base_path, path)
|
||||
if self.case_insensitive:
|
||||
file_dir = case_insensitive_file_search(file_dir)
|
||||
if not os.path.exists(file_dir):
|
||||
os.makedirs(file_dir)
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ from typing import List, Iterator
|
|||
|
||||
from filelock import FileLock
|
||||
|
||||
from legendary.lfs.wine_helpers import case_insensitive_file_search
|
||||
from legendary.models.game import VerifyResult
|
||||
|
||||
logger = logging.getLogger('LFS Utils')
|
||||
|
@ -34,7 +35,7 @@ def delete_folder(path: str, recursive=True) -> bool:
|
|||
|
||||
def delete_filelist(path: str, filenames: List[str],
|
||||
delete_root_directory: bool = False,
|
||||
silent: bool = False) -> bool:
|
||||
silent: bool = False, case_insensitive: bool = True) -> bool:
|
||||
dirs = set()
|
||||
no_error = True
|
||||
|
||||
|
@ -45,7 +46,10 @@ def delete_filelist(path: str, filenames: List[str],
|
|||
dirs.add(_dir)
|
||||
|
||||
try:
|
||||
os.remove(os.path.join(path, _dir, _fn))
|
||||
full_path = os.path.join(path, _dir, _fn)
|
||||
if case_insensitive:
|
||||
full_path = case_insensitive_file_search(full_path)
|
||||
os.remove(full_path)
|
||||
except Exception as e:
|
||||
if not silent:
|
||||
logger.error(f'Failed deleting file {filename} with {e!r}')
|
||||
|
@ -61,7 +65,10 @@ def delete_filelist(path: str, filenames: List[str],
|
|||
# remove all directories
|
||||
for _dir in sorted(dirs, key=len, reverse=True):
|
||||
try:
|
||||
os.rmdir(os.path.join(path, _dir))
|
||||
dir_path = os.path.join(path, _dir)
|
||||
if case_insensitive:
|
||||
dir_path = case_insensitive_file_search(dir_path)
|
||||
os.rmdir(dir_path)
|
||||
except FileNotFoundError:
|
||||
# directory has already been deleted, ignore that
|
||||
continue
|
||||
|
@ -81,7 +88,7 @@ def delete_filelist(path: str, filenames: List[str],
|
|||
|
||||
|
||||
def validate_files(base_path: str, filelist: List[tuple], hash_type='sha1',
|
||||
large_file_threshold=1024 * 1024 * 512) -> Iterator[tuple]:
|
||||
large_file_threshold=1024 * 1024 * 512, case_insensitive: bool = True) -> Iterator[tuple]:
|
||||
"""
|
||||
Validates the files in filelist in path against the provided hashes
|
||||
|
||||
|
@ -89,6 +96,7 @@ def validate_files(base_path: str, filelist: List[tuple], hash_type='sha1',
|
|||
:param filelist: list of tuples in format (path, hash [hex])
|
||||
:param hash_type: (optional) type of hash, default is sha1
|
||||
:param large_file_threshold: (optional) threshold for large files, default is 512 MiB
|
||||
:param case_insensitive: (optional) whether to search for files case insensitively
|
||||
:return: yields tuples in format (VerifyResult, path, hash [hex], bytes read)
|
||||
"""
|
||||
|
||||
|
@ -100,6 +108,8 @@ def validate_files(base_path: str, filelist: List[tuple], hash_type='sha1',
|
|||
|
||||
for file_path, file_hash in filelist:
|
||||
full_path = os.path.join(base_path, file_path)
|
||||
if case_insensitive:
|
||||
full_path = case_insensitive_file_search(full_path)
|
||||
# logger.debug(f'Checking "{file_path}"...')
|
||||
|
||||
if not os.path.exists(full_path):
|
||||
|
|
Loading…
Reference in a new issue