mirror of
https://github.com/derrod/legendary.git
synced 2025-01-21 14:40:59 +00:00
[cli/core/downloader] Support filtering by install tags
Also adds tsv option for list-files and fixes no_install not being set with --exclude. Install tags are only present in some titles, I'm not entirely sure how EGL uses them. Perhaps to allow one manifest to be used on different platforms? Or to only download extra assets when the user wants to? Either way, it's another filtering feature that may be useful, though for now it's mostly another toy to explore EPIC's distribution system with.
This commit is contained in:
parent
531af3f586
commit
9b5620ca30
|
@ -173,16 +173,24 @@ class LegendaryCLI:
|
|||
files = sorted(manifest.file_manifest_list.elements,
|
||||
key=lambda a: a.filename.lower())
|
||||
|
||||
if args.install_tag:
|
||||
files = [fm for fm in files if args.install_tag in fm.install_tags]
|
||||
|
||||
if args.hashlist:
|
||||
for fm in files:
|
||||
print(f'{fm.hash.hex()} *{fm.filename}')
|
||||
elif args.csv:
|
||||
writer = csv.writer(stdout)
|
||||
writer.writerow(['path', 'hash', 'size'])
|
||||
writer.writerows((fm.filename, fm.hash.hex(), fm.file_size) for fm in files)
|
||||
elif args.csv or args.tsv:
|
||||
writer = csv.writer(stdout, dialect='excel-tab' if args.tsv else 'excel')
|
||||
writer.writerow(['path', 'hash', 'size', 'install_tags'])
|
||||
writer.writerows((fm.filename, fm.hash.hex(), fm.file_size, '|'.join(fm.install_tags))for fm in files)
|
||||
else:
|
||||
install_tags = set()
|
||||
for fm in files:
|
||||
print(fm.filename)
|
||||
for t in fm.install_tags:
|
||||
install_tags.add(t)
|
||||
# use the log output so this isn't included when piping file list into file
|
||||
logger.info(f'Install tags: {", ".join(sorted(install_tags))}')
|
||||
|
||||
def launch_game(self, args, extra):
|
||||
app_name = args.app_name
|
||||
|
@ -232,7 +240,7 @@ class LegendaryCLI:
|
|||
logger.error('Login failed! Cannot continue with download process.')
|
||||
exit(1)
|
||||
|
||||
if args.file_prefix:
|
||||
if args.file_prefix or args.file_exclude_prefix or args.install_tag:
|
||||
args.no_install = True
|
||||
|
||||
if args.update_only:
|
||||
|
@ -273,7 +281,8 @@ class LegendaryCLI:
|
|||
override_base_url=args.override_base_url,
|
||||
platform_override=args.platform_override,
|
||||
file_prefix_filter=args.file_prefix,
|
||||
file_exclude_filter=args.file_exclude_prefix)
|
||||
file_exclude_filter=args.file_exclude_prefix,
|
||||
file_install_tag=args.install_tag)
|
||||
|
||||
# game is either up to date or hasn't changed, so we have nothing to do
|
||||
if not analysis.dl_size:
|
||||
|
@ -454,6 +463,8 @@ def main():
|
|||
help='Only fetch files whose path starts with <prefix> (case insensitive)')
|
||||
install_parser.add_argument('--exclude', dest='file_exclude_prefix', action='store', metavar='<prefix>',
|
||||
type=str, help='Exclude files starting with <prefix> (case insensitive)')
|
||||
install_parser.add_argument('--install-tag', dest='install_tag', action='store', metavar='<prefix>',
|
||||
type=str, help='Only download files with the specified install tag (testing)')
|
||||
|
||||
launch_parser.add_argument('--offline', dest='offline', action='store_true',
|
||||
default=False, help='Skip login and launch game without online authentication')
|
||||
|
@ -485,8 +496,11 @@ def main():
|
|||
list_files_parser.add_argument('--manifest', dest='override_manifest', action='store', metavar='<uri>',
|
||||
help='Manifest URL or path to use instead of the CDN one')
|
||||
list_files_parser.add_argument('--csv', dest='csv', action='store_true', help='Output in CSV format')
|
||||
list_files_parser.add_argument('--tsv', dest='tsv', action='store_true', help='Output in TSV format')
|
||||
list_files_parser.add_argument('--hashlist', dest='hashlist', action='store_true',
|
||||
help='Output file hash list in hashcheck/sha1sum compatible format')
|
||||
list_files_parser.add_argument('--install-tag', dest='install_tag', action='store', metavar='<prefix>',
|
||||
type=str, help='Show only files with specified install tag')
|
||||
|
||||
args, extra = parser.parse_known_args()
|
||||
|
||||
|
|
|
@ -356,7 +356,8 @@ class LegendaryCore:
|
|||
game_folder: str = '', override_manifest: str = '',
|
||||
override_old_manifest: str = '', override_base_url: str = '',
|
||||
platform_override: str = '', file_prefix_filter: str = '',
|
||||
file_exclude_filter: str = '' ) -> (DLManager, AnalysisResult, ManifestMeta):
|
||||
file_exclude_filter: str = '', file_install_tag: str = ''
|
||||
) -> (DLManager, AnalysisResult, ManifestMeta):
|
||||
# load old manifest
|
||||
old_manifest = None
|
||||
|
||||
|
@ -430,7 +431,8 @@ 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_exclude_filter=file_exclude_filter)
|
||||
file_exclude_filter=file_exclude_filter,
|
||||
file_install_tag=file_install_tag)
|
||||
|
||||
prereq = None
|
||||
if new_manifest.meta.prereq_ids:
|
||||
|
|
|
@ -242,7 +242,7 @@ 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) -> AnalysisResult:
|
||||
file_exclude_filter=None, file_install_tag=None) -> 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.
|
||||
|
@ -278,6 +278,16 @@ class DLManager(Process):
|
|||
except Exception as e:
|
||||
self.log.warning(f'Reading resume file failed: {e!r}, continuing as normal...')
|
||||
|
||||
# Not entirely sure what install tags are used for, only some titles have them.
|
||||
# Let's add it for testing anyway.
|
||||
if file_install_tag:
|
||||
files_to_skip = set(i.filename for i in manifest.file_manifest_list.elements
|
||||
if file_install_tag not in i.install_tags)
|
||||
self.log.info(f'Found {len(files_to_skip)} files to skip based on install tag.')
|
||||
mc.added -= files_to_skip
|
||||
mc.changed -= files_to_skip
|
||||
mc.unchanged |= files_to_skip
|
||||
|
||||
# if include/exclude prefix has been set: mark all files that are not to be downloaded as unchanged
|
||||
if file_exclude_filter:
|
||||
file_exclude_filter = file_exclude_filter.lower()
|
||||
|
@ -295,7 +305,7 @@ class DLManager(Process):
|
|||
mc.changed -= files_to_skip
|
||||
mc.unchanged |= files_to_skip
|
||||
|
||||
if file_prefix_filter or file_exclude_filter:
|
||||
if file_prefix_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
|
||||
|
|
Loading…
Reference in a new issue