From 16123f7259618be872735a155817fdbd0b0dd0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katharina=20Dr=C3=B6ge?= Date: Mon, 3 Nov 2025 17:50:25 +0100 Subject: [PATCH] Implement `--suffix` parameter for install/download command This makes it possible to download only files with a given suffix, which is helpful in case you want all files of a certain type --- legendary/cli.py | 3 +++ legendary/core.py | 14 ++++++++------ legendary/downloader/mp/manager.py | 22 ++++++++++++++-------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/legendary/cli.py b/legendary/cli.py index 9d8430d..998005d 100644 --- a/legendary/cli.py +++ b/legendary/cli.py @@ -969,6 +969,7 @@ class LegendaryCLI: override_base_url=args.override_base_url, platform=args.platform, file_prefix_filter=args.file_prefix, + file_suffix_filter=args.file_suffix, file_exclude_filter=args.file_exclude_prefix, file_install_tag=args.install_tag, dl_optimizations=args.order_opt, @@ -2764,6 +2765,8 @@ def main(): help='Platform for install (default: installed or Windows)') install_parser.add_argument('--prefix', dest='file_prefix', action='append', metavar='', help='Only fetch files whose path starts with (case insensitive)') + install_parser.add_argument('--suffix', dest='file_suffix', action='append', metavar='', + help='Only fetch files whose path ends with (case insensitive)') install_parser.add_argument('--exclude', dest='file_exclude_prefix', action='append', metavar='', type=str, help='Exclude files starting with (case insensitive)') install_parser.add_argument('--install-tag', dest='install_tag', action='append', metavar='', diff --git a/legendary/core.py b/legendary/core.py index 04344e3..29ce3f1 100644 --- a/legendary/core.py +++ b/legendary/core.py @@ -1326,12 +1326,13 @@ class LegendaryCore: game_folder: str = '', override_manifest: str = '', override_old_manifest: str = '', override_base_url: str = '', platform: str = 'Windows', file_prefix_filter: list = None, - file_exclude_filter: list = None, file_install_tag: list = None, - dl_optimizations: bool = False, dl_timeout: int = 10, - repair: bool = False, repair_use_latest: bool = False, - disable_delta: bool = False, override_delta_manifest: str = '', - egl_guid: str = '', preferred_cdn: str = None, - disable_https: bool = False, bind_ip: str = None) -> (DLManager, AnalysisResult, ManifestMeta): + file_suffix_filter: list = None, file_exclude_filter: list = None, + file_install_tag: list = None, dl_optimizations: bool = False, + dl_timeout: int = 10, repair: bool = False, + repair_use_latest: bool = False, disable_delta: bool = False, + override_delta_manifest: str = '', egl_guid: str = '', + preferred_cdn: str = None, disable_https: bool = False, + bind_ip: str = None) -> (DLManager, AnalysisResult, ManifestMeta): # load old manifest old_manifest = None @@ -1502,6 +1503,7 @@ class LegendaryCore: anlres = dlm.run_analysis(manifest=new_manifest, old_manifest=old_manifest, patch=not disable_patching, resume=not force, file_prefix_filter=file_prefix_filter, + file_suffix_filter=file_suffix_filter, file_exclude_filter=file_exclude_filter, file_install_tag=file_install_tag, processing_optimization=process_opt) diff --git a/legendary/downloader/mp/manager.py b/legendary/downloader/mp/manager.py index 90ab37a..b3526b8 100644 --- a/legendary/downloader/mp/manager.py +++ b/legendary/downloader/mp/manager.py @@ -81,8 +81,8 @@ class DLManager(Process): def run_analysis(self, manifest: Manifest, old_manifest: Manifest = None, patch=True, resume=True, file_prefix_filter=None, - file_exclude_filter=None, file_install_tag=None, - processing_optimization=False) -> AnalysisResult: + file_suffix_filter=None, file_exclude_filter=None, + file_install_tag=None, processing_optimization=False) -> AnalysisResult: """ Run analysis on manifest and old manifest (if not None) and return a result with a summary resources required in order to install the provided manifest. @@ -92,6 +92,7 @@ class DLManager(Process): :param patch: Patch instead of redownloading the entire file :param resume: Continue based on resume file if it exists :param file_prefix_filter: Only download files that start with this prefix + :param file_suffix_filter: Only download files that end with this prefix :param file_exclude_filter: Exclude files with this prefix from download :param file_install_tag: Only install files with the specified tag :param processing_optimization: Attempt to optimize processing order and RAM usage @@ -187,19 +188,24 @@ class DLManager(Process): mc.changed -= files_to_skip mc.unchanged |= files_to_skip - if file_prefix_filter: - if isinstance(file_prefix_filter, str): - file_prefix_filter = [file_prefix_filter] + if file_prefix_filter or file_suffix_filter: + file_prefix_filter = file_prefix_filter or [] + file_suffix_filter = file_suffix_filter or [] file_prefix_filter = [f.lower() for f in file_prefix_filter] - files_to_skip = set(i.filename for i in manifest.file_manifest_list.elements if not - any(i.filename.lower().startswith(pfx) for pfx in file_prefix_filter)) + file_suffix_filter = [f.lower() for f in file_suffix_filter] + files_to_skip = set( + i.filename + for i in manifest.file_manifest_list.elements + if not any(i.filename.lower().startswith(pfx) for pfx in file_prefix_filter) + and not any(i.filename.lower().endswith(sfx) for sfx in file_suffix_filter) + ) self.log.info(f'Found {len(files_to_skip)} files to skip based on include prefix(es)') mc.added -= files_to_skip mc.changed -= files_to_skip mc.unchanged |= files_to_skip - if file_prefix_filter or file_exclude_filter or file_install_tag: + if file_prefix_filter or file_suffix_filter or file_exclude_filter or file_install_tag: self.log.info(f'Remaining files after filtering: {len(mc.added) + len(mc.changed)}') # correct install size after filtering analysis_res.install_size = sum(fm.file_size for fm in manifest.file_manifest_list.elements