From 2cd39da2cbd584247fcb6c35487a19f71ff4571f Mon Sep 17 00:00:00 2001 From: Eloston Date: Tue, 20 Mar 2018 22:09:26 +0000 Subject: [PATCH] buildkit.extractors: Refactoring and formatting --- buildkit/cli.py | 27 +++-- buildkit/common.py | 26 ++++- buildkit/config.py | 7 +- buildkit/extractors.py | 197 +++++++++++++++++++++++------------ buildkit/source_retrieval.py | 68 +++++++----- 5 files changed, 212 insertions(+), 113 deletions(-) diff --git a/buildkit/cli.py b/buildkit/cli.py index 3c960898..c434f8b0 100644 --- a/buildkit/cli.py +++ b/buildkit/cli.py @@ -25,8 +25,8 @@ from . import source_retrieval from . import domain_substitution from .common import ( CONFIG_BUNDLES_DIR, BUILDSPACE_DOWNLOADS, BUILDSPACE_TREE, - BUILDSPACE_TREE_PACKAGING, BUILDSPACE_USER_BUNDLE, - BuildkitAbort, get_resources_dir, get_logger) + BUILDSPACE_TREE_PACKAGING, BUILDSPACE_USER_BUNDLE, SEVENZIP_USE_REGISTRY, + BuildkitAbort, ExtractorEnum, get_resources_dir, get_logger) from .config import ConfigBundle # Classes @@ -136,14 +136,14 @@ def _add_getsrc(subparsers): """Downloads, checks, and unpacks the necessary files into the buildspace tree""" def _callback(args): try: - user_binaries = {} - if args.tar_path is not None: - user_binaries['tar'] = args.tar_path - if args.sevenz_path is not None: - user_binaries['7z'] = args.sevenz_path + extractors = { + ExtractorEnum.SEVENZIP: args.sevenz_path, + ExtractorEnum.TAR: args.tar_path, + } source_retrieval.retrieve_and_extract( - args.bundle, args.downloads, args.tree, prune_binaries=args.prune_binaries, - show_progress=args.show_progress, user_binaries=user_binaries) + config_bundle=args.bundle, buildspace_downloads=args.downloads, + buildspace_tree=args.tree, prune_binaries=args.prune_binaries, + show_progress=args.show_progress, extractors=extractors) except FileExistsError as exc: get_logger().error('Directory is not empty: %s', exc) raise _CLIError() @@ -185,9 +185,14 @@ def _add_getsrc(subparsers): '--hide-progress-bar', action='store_false', dest='show_progress', help='Hide the download progress.') parser.add_argument( - '--tar-path', help='Path to the tar binary.') + '--tar-path', default='tar', + help=('(Linux and macOS only) Command or path to the BSD or GNU tar ' + 'binary for extraction. Default: %(default)s')) parser.add_argument( - '--7z-path', help='Path to the 7z.exe binary.', dest='sevenz_path') + '--7z-path', dest='sevenz_path', default=SEVENZIP_USE_REGISTRY, + help=('(Windows only) Command or path to the 7-Zip 7z.exe binary. If ' + '"_use_registry" is specified, determine the path from the registry. ' + 'Default: %(default)s')) parser.set_defaults(callback=_callback) def _add_prubin(subparsers): diff --git a/buildkit/common.py b/buildkit/common.py index c7b120d4..92ca5289 100644 --- a/buildkit/common.py +++ b/buildkit/common.py @@ -6,6 +6,7 @@ """Common code and constants""" +import enum import os import logging import platform @@ -24,6 +25,8 @@ BUILDSPACE_TREE = 'buildspace/tree' BUILDSPACE_TREE_PACKAGING = 'buildspace/tree/ungoogled_packaging' BUILDSPACE_USER_BUNDLE = 'buildspace/user_bundle' +SEVENZIP_USE_REGISTRY = '_use_registry' + _ENV_FORMAT = "BUILDKIT_{}" # Public classes @@ -38,6 +41,16 @@ class BuildkitAbort(BuildkitError): It should only be caught by the user of buildkit's library interface. """ +class PlatformEnum(enum.Enum): + """Enum for platforms that need distinction for certain functionality""" + UNIX = 'unix' # Currently covers anything that isn't Windows + WINDOWS = 'windows' + +class ExtractorEnum: #pylint: disable=too-few-public-methods + """Enum for extraction binaries""" + SEVENZIP = '7z' + TAR = 'tar' + # Public methods def get_logger(name=__package__, initial_level=logging.DEBUG): @@ -107,11 +120,16 @@ def ensure_empty_dir(path, parents=False): if not dir_empty(path): raise exc -def is_windows_platform(): +def get_running_platform(): """ - Returns True if we are running on a Windows platform, either natively or - inside WSL/MSYS2 + Returns a PlatformEnum value indicating the platform that buildkit is running on. + + NOTE: Platform detection should only be used when no cross-platform alternative is available. """ uname = platform.uname() # detect native python and WSL - return uname.system == 'Windows' or 'Microsoft' in uname.release + if uname.system == 'Windows' or 'Microsoft' in uname.release: + return PlatformEnum.WINDOWS + else: + # Only Windows and UNIX-based platforms need to be distinguished right now. + return PlatformEnum.UNIX diff --git a/buildkit/config.py b/buildkit/config.py index 3dab6ee2..98aed43b 100644 --- a/buildkit/config.py +++ b/buildkit/config.py @@ -18,7 +18,7 @@ import shutil from pathlib import Path from .common import ( - ENCODING, CONFIG_BUNDLES_DIR, BuildkitAbort, + ENCODING, CONFIG_BUNDLES_DIR, BuildkitAbort, ExtractorEnum, get_logger, get_resources_dir, ensure_empty_dir) from .third_party import schema @@ -619,13 +619,14 @@ class ExtraDepsIni(IniConfigFile): _hashes = ('md5', 'sha1', 'sha256', 'sha512') _required_keys = ('version', 'url', 'download_name') - _optional_keys = ('strip_leading_dirs','extractor') - _passthrough_properties = (*_required_keys, *_optional_keys) + _optional_keys = ('strip_leading_dirs') + _passthrough_properties = (*_required_keys, *_optional_keys, 'extractor') _schema = schema.Schema(schema_inisections({ schema.Optional(schema.And(str, len)): schema_dictcast({ **{x: schema.And(str, len) for x in _required_keys}, **{schema.Optional(x): schema.And(str, len) for x in _optional_keys}, + schema.Optional('extractor'): schema.Or(ExtractorEnum.TAR, ExtractorEnum.SEVENZIP), schema.Or(*_hashes): schema.And(str, len), }) })) diff --git a/buildkit/extractors.py b/buildkit/extractors.py index dbb63826..2dbef71f 100644 --- a/buildkit/extractors.py +++ b/buildkit/extractors.py @@ -14,7 +14,22 @@ import subprocess import tarfile from pathlib import Path, PurePosixPath -from .common import ENCODING, BuildkitAbort, get_logger, ensure_empty_dir, is_windows_platform +from .common import ( + SEVENZIP_USE_REGISTRY, BuildkitAbort, PlatformEnum, ExtractorEnum, get_logger, + get_running_platform) + +DEFAULT_EXTRACTORS = { + ExtractorEnum.SEVENZIP: SEVENZIP_USE_REGISTRY, + ExtractorEnum.TAR: 'tar', +} + +def _find_extractor_binary(extractor_cmd): + """Returns a string path to the binary; None if it couldn't be found""" + if not extractor_cmd: + return None + if Path(extractor_cmd).is_file(): + return extractor_cmd + return shutil.which(extractor_cmd) def _process_relative_to(unpack_root, relative_to): """ @@ -23,7 +38,9 @@ def _process_relative_to(unpack_root, relative_to): """ relative_root = unpack_root / relative_to if not relative_root.is_dir(): - raise Exception('Could not find relative_to directory in extracted files: {}', relative_to) + get_logger().error( + 'Could not find relative_to directory in extracted files: %s', relative_to) + raise BuildkitAbort() for src_path in relative_root.iterdir(): dest_path = unpack_root / src_path.name src_path.rename(dest_path) @@ -33,56 +50,65 @@ def _prune_tree(unpack_root, ignore_files): """ Run through the list of pruned files, delete them, and remove them from the set """ - deleted_files = [] + deleted_files = set() for relative_file in ignore_files: - file = unpack_root / relative_file - if not file.is_file(): + file_path = unpack_root / relative_file + if not file_path.is_file(): continue - file.unlink() - deleted_files.append((Path(relative_file).as_posix())) - for d in deleted_files: - ignore_files.remove(d) + file_path.unlink() + deleted_files.add(Path(relative_file).as_posix()) + for deleted_path in deleted_files: + ignore_files.remove(deleted_path) -def _extract_tar_file_7z(binary, tar_path, buildspace_tree, unpack_dir, ignore_files, relative_to): +def _extract_tar_with_7z(binary, archive_path, buildspace_tree, unpack_dir, ignore_files, #pylint: disable=too-many-arguments + relative_to): + get_logger().debug('Using 7-zip extractor') out_dir = buildspace_tree / unpack_dir - cmd1 = [binary, 'x', str(tar_path), '-so'] - cmd2 = [binary, 'x', '-si', '-aoa', '-ttar', '-o{}'.format(str(out_dir))] - cmdline = '{} | {}'.format(' '.join(cmd1), ' '.join(cmd2)) - get_logger().debug("7z command line: {}".format(cmdline)) + if not relative_to is None and (out_dir / relative_to).exists(): + get_logger().error( + 'Temporary unpacking directory already exists: %s', out_dir / relative_to) + raise BuildkitAbort() + cmd1 = (binary, 'x', str(archive_path), '-so') + cmd2 = (binary, 'x', '-si', '-aoa', '-ttar', '-o{}'.format(str(out_dir))) + get_logger().debug('7z command line: %s | %s', + ' '.join(cmd1), ' '.join(cmd2)) - p1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE) - p2 = subprocess.Popen(cmd2, stdin=p1.stdout, stdout=subprocess.PIPE) - p1.stdout.close() - (stdout_data, stderr_data) = p2.communicate() - if p2.returncode != 0: - get_logger().debug('stdout: {}'.format(stdout_data)) - get_logger().debug('stderr: {}'.format(stderr_data)) - raise Exception('7z commands returned non-zero status: {}'.format(p2.returncode)) + proc1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE) + proc2 = subprocess.Popen(cmd2, stdin=proc1.stdout, stdout=subprocess.PIPE) + proc1.stdout.close() + (stdout_data, stderr_data) = proc2.communicate() + if proc2.returncode != 0: + get_logger().error('7z commands returned non-zero status: %s', proc2.returncode) + get_logger().debug('stdout: %s', stdout_data) + get_logger().debug('stderr: %s', stderr_data) + raise BuildkitAbort() - if relative_to is not None: + if not relative_to is None: _process_relative_to(out_dir, relative_to) _prune_tree(out_dir, ignore_files) -def _extract_tar_file_tar(binary, tar_path, buildspace_tree, unpack_dir, ignore_files, relative_to): +def _extract_tar_with_tar(binary, archive_path, buildspace_tree, unpack_dir, #pylint: disable=too-many-arguments + ignore_files, relative_to): + get_logger().debug('Using BSD or GNU tar extractor') out_dir = buildspace_tree / unpack_dir out_dir.mkdir(exist_ok=True) - cmd = [binary, '-xf', str(tar_path), '-C', str(out_dir)] - cmdline = ' '.join(cmd) - get_logger().debug("tar command line: {}".format(cmdline)) + cmd = (binary, '-xf', str(archive_path), '-C', str(out_dir)) + get_logger().debug('tar command line: %s', ' '.join(cmd)) result = subprocess.run(cmd) if result.returncode != 0: - raise Exception('tar command returned {}'.format(result.returncode)) + get_logger().error('tar command returned %s', result.returncode) + raise BuildkitAbort() # for gnu tar, the --transform option could be used. but to keep compatibility with # bsdtar on macos, we just do this ourselves - if relative_to is not None: + if not relative_to is None: _process_relative_to(out_dir, relative_to) _prune_tree(out_dir, ignore_files) -def _extract_tar_file_python(tar_path, buildspace_tree, unpack_dir, ignore_files, relative_to): - +def _extract_tar_with_python(archive_path, buildspace_tree, unpack_dir, ignore_files, relative_to): + get_logger().debug('Using pure Python tar extractor') class NoAppendList(list): """Hack to workaround memory issues with large tar files""" def append(self, obj): @@ -103,7 +129,7 @@ def _extract_tar_file_python(tar_path, buildspace_tree, unpack_dir, ignore_files get_logger().exception('Unexpected exception during symlink support check.') raise BuildkitAbort() - with tarfile.open(str(tar_path)) as tar_file_obj: + with tarfile.open(str(archive_path)) as tar_file_obj: tar_file_obj.members = NoAppendList() for tarinfo in tar_file_obj: try: @@ -134,11 +160,12 @@ def _extract_tar_file_python(tar_path, buildspace_tree, unpack_dir, ignore_files get_logger().exception('Exception thrown for tar member: %s', tarinfo.name) raise BuildkitAbort() -def extract_tar_file(tar_path, buildspace_tree, unpack_dir, ignore_files, relative_to, user_binaries): +def extract_tar_file(archive_path, buildspace_tree, unpack_dir, ignore_files, relative_to, #pylint: disable=too-many-arguments + extractors=None): """ - One-time tar extraction function + Extract regular or compressed tar archive into the buildspace tree. - tar_path is the pathlib.Path to the archive to unpack + archive_path is the pathlib.Path to the archive to unpack buildspace_tree is a pathlib.Path to the buildspace tree. unpack_dir is a pathlib.Path relative to buildspace_tree to unpack the archive. It must already exist. @@ -147,56 +174,90 @@ def extract_tar_file(tar_path, buildspace_tree, unpack_dir, ignore_files, relati Files that have been ignored are removed from the set. relative_to is a pathlib.Path for directories that should be stripped relative to the root of the archive. - user_binaries is a dict of user-provided utility binaries, if available + extractors is a dictionary of PlatformEnum to a command or path to the + extractor binary. Defaults to 'tar' for tar, and '_use_registry' for 7-Zip. Raises BuildkitAbort if unexpected issues arise during unpacking. """ - - def lookup_binary(name): - return user_binaries.get(name) or shutil.which(name) - - tar_bin = lookup_binary('tar') - sevenz_bin = lookup_binary('7z') resolved_tree = buildspace_tree.resolve() - common_args = [tar_path, resolved_tree, unpack_dir, ignore_files, relative_to] + if extractors is None: + extractors = DEFAULT_EXTRACTORS - if is_windows_platform(): - if sevenz_bin is not None: - _extract_tar_file_7z(sevenz_bin, *common_args) - else: - get_logger().info('7z.exe not found. Using built-in Python extractor') - _extract_tar_file_python(*common_args) + current_platform = get_running_platform() + if current_platform == PlatformEnum.WINDOWS: + # TODO: Add option to get 7z.exe path from registry at path + # "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe" + sevenzip_cmd = extractors.get(ExtractorEnum.SEVENZIP) + if sevenzip_cmd == SEVENZIP_USE_REGISTRY: + raise NotImplementedError() + sevenzip_bin = _find_extractor_binary(sevenzip_cmd) + if not sevenzip_bin is None: + _extract_tar_with_7z( + binary=sevenzip_bin, archive_path=archive_path, buildspace_tree=resolved_tree, + unpack_dir=unpack_dir, ignore_files=ignore_files, relative_to=relative_to) + return + elif current_platform == PlatformEnum.UNIX: + # NOTE: 7-zip isn't an option because it doesn't preserve file permissions + tar_bin = _find_extractor_binary(extractors.get(ExtractorEnum.TAR)) + if not tar_bin is None: + _extract_tar_with_tar( + binary=tar_bin, archive_path=archive_path, buildspace_tree=resolved_tree, + unpack_dir=unpack_dir, ignore_files=ignore_files, relative_to=relative_to) + return else: - if tar_bin is not None: - _extract_tar_file_tar(tar_bin, *common_args) - else: - # we dont try 7z on unix because it doesnt preserve file permissions - get_logger().info('tar command not found. Using built-in Python extractor') - _extract_tar_file_python(*common_args) - -def extract_7z_file(tar_path, buildspace_tree, unpack_dir, ignore_files, relative_to, user_binaries): + # This is not a normal code path, so make it clear. + raise NotImplementedError(current_platform) + # Fallback to Python-based extractor on all platforms + _extract_tar_with_python( + archive_path=archive_path, buildspace_tree=resolved_tree, unpack_dir=unpack_dir, + ignore_files=ignore_files, relative_to=relative_to) +def extract_with_7z(archive_path, buildspace_tree, unpack_dir, ignore_files, relative_to, #pylint: disable=too-many-arguments + extractors=None): """ - One-time 7zip extraction function + (Windows only) Extract archives with 7-zip into the buildspace tree. + Only supports archives with one layer of unpacking, unlike compressed tar archives. - Same arguments as extract_tar_file + archive_path is the pathlib.Path to the archive to unpack + buildspace_tree is a pathlib.Path to the buildspace tree. + unpack_dir is a pathlib.Path relative to buildspace_tree to unpack the archive. + It must already exist. + + ignore_files is a set of paths as strings that should not be extracted from the archive. + Files that have been ignored are removed from the set. + relative_to is a pathlib.Path for directories that should be stripped relative to the + root of the archive. + extractors is a dictionary of PlatformEnum to a command or path to the + extractor binary. Defaults to 'tar' for tar, and '_use_registry' for 7-Zip. + + Raises BuildkitAbort if unexpected issues arise during unpacking. """ - sevenz_bin = user_binaries.get('7z') or shutil.which('7z') - if sevenz_bin is None: - raise Exception('Unable to locate 7z binary') + # TODO: Add option to get 7z.exe path from registry at path + # "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe" + # TODO: It would be nice to extend this to support arbitrary standard IO chaining of 7z + # instances, so _extract_tar_with_7z and other future formats could use this. + if extractors is None: + extractors = DEFAULT_EXTRACTORS + sevenzip_cmd = extractors.get(ExtractorEnum.SEVENZIP) + if sevenzip_cmd == SEVENZIP_USE_REGISTRY: + raise NotImplementedError() + sevenzip_bin = _find_extractor_binary(sevenzip_cmd) resolved_tree = buildspace_tree.resolve() - common_args = [tar_path, resolved_tree, unpack_dir, ignore_files, relative_to] out_dir = resolved_tree / unpack_dir - cmd = [sevenz_bin, 'x', str(tar_path), '-aoa', '-o{}'.format(str(out_dir))] - cmdline = ' '.join(cmd) - get_logger().debug("7z command line: {}".format(cmdline)) + if not relative_to is None and (out_dir / relative_to).exists(): + get_logger().error( + 'Temporary unpacking directory already exists: %s', out_dir / relative_to) + raise BuildkitAbort() + cmd = (sevenzip_bin, 'x', str(archive_path), '-aoa', '-o{}'.format(str(out_dir))) + get_logger().debug('7z command line: %s', ' '.join(cmd)) result = subprocess.run(cmd) if result.returncode != 0: - raise Exception('7z command returned {}'.format(result.returncode)) + get_logger().error('7z command returned %s', result.returncode) + raise BuildkitAbort() - if relative_to is not None: + if not relative_to is None: _process_relative_to(out_dir, relative_to) _prune_tree(out_dir, ignore_files) diff --git a/buildkit/source_retrieval.py b/buildkit/source_retrieval.py index 1a104f6a..c04f32ef 100644 --- a/buildkit/source_retrieval.py +++ b/buildkit/source_retrieval.py @@ -8,14 +8,13 @@ Module for the downloading, checking, and unpacking of necessary files into the buildspace tree """ -import os -import tarfile import urllib.request import hashlib -from pathlib import Path, PurePosixPath +from pathlib import Path -from .common import ENCODING, BuildkitAbort, get_logger, ensure_empty_dir -from .extractors import extract_tar_file, extract_7z_file +from .common import ( + ENCODING, ExtractorEnum, get_logger, ensure_empty_dir) +from .extractors import extract_tar_file, extract_with_7z # Constants @@ -83,14 +82,16 @@ def _chromium_hashes_generator(hashes_path): else: get_logger().warning('Skipping unknown hash algorithm: %s', hash_name) -def _setup_chromium_source(config_bundle, buildspace_downloads, buildspace_tree, - show_progress, pruning_set, user_binaries): +def _setup_chromium_source(config_bundle, buildspace_downloads, buildspace_tree, #pylint: disable=too-many-arguments + show_progress, pruning_set, extractors=None): """ Download, check, and extract the Chromium source code into the buildspace tree. Arguments of the same name are shared with retreive_and_extract(). pruning_set is a set of files to be pruned. Only the files that are ignored during extraction are removed from the set. + extractors is a dictionary of PlatformEnum to a command or path to the + extractor binary. Defaults to 'tar' for tar, and '_use_registry' for 7-Zip. Raises source_retrieval.HashMismatchError when the computed and expected hashes do not match. Raises source_retrieval.NotAFileError when the archive name exists but is not a file. @@ -123,18 +124,22 @@ def _setup_chromium_source(config_bundle, buildspace_downloads, buildspace_tree, if not hasher.hexdigest().lower() == hash_hex.lower(): raise HashMismatchError(source_archive) get_logger().info('Extracting archive...') - extract_tar_file(source_archive, buildspace_tree, Path(), pruning_set, - Path('chromium-{}'.format(config_bundle.version.chromium_version)), - user_binaries) + extract_tar_file( + archive_path=source_archive, buildspace_tree=buildspace_tree, unpack_dir=Path(), + ignore_files=pruning_set, + relative_to=Path('chromium-{}'.format(config_bundle.version.chromium_version)), + extractors=extractors) -def _setup_extra_deps(config_bundle, buildspace_downloads, buildspace_tree, show_progress, - pruning_set, user_binaries): +def _setup_extra_deps(config_bundle, buildspace_downloads, buildspace_tree, show_progress, #pylint: disable=too-many-arguments,too-many-locals + pruning_set, extractors=None): """ Download, check, and extract extra dependencies into the buildspace tree. Arguments of the same name are shared with retreive_and_extract(). pruning_set is a set of files to be pruned. Only the files that are ignored during extraction are removed from the set. + extractors is a dictionary of PlatformEnum to a command or path to the + extractor binary. Defaults to 'tar' for tar, and '_use_registry' for 7-Zip. Raises source_retrieval.HashMismatchError when the computed and expected hashes do not match. Raises source_retrieval.NotAFileError when the archive name exists but is not a file. @@ -154,30 +159,35 @@ def _setup_extra_deps(config_bundle, buildspace_downloads, buildspace_tree, show if not hasher.hexdigest().lower() == hash_hex.lower(): raise HashMismatchError(dep_archive) get_logger().info('Extracting archive...') - extractors = {'7z': extract_7z_file, 'tar': extract_tar_file} - extractor_name = dep_properties.extractor or 'tar' - extractor_fn = extractors.get(extractor_name) - if extractor_fn is None: - raise Exception('Unknown extractor: {}. Supported values: {}' - .format(extractor_name, [k for k in extractors.keys()])) + extractor_name = dep_properties.extractor or ExtractorEnum.TAR + if extractor_name == ExtractorEnum.SEVENZIP: + extractor_func = extract_with_7z + elif extractor_name == ExtractorEnum.TAR: + extractor_func = extract_tar_file + else: + # This is not a normal code path + raise NotImplementedError(extractor_name) if dep_properties.strip_leading_dirs is None: strip_leading_dirs_path = None else: strip_leading_dirs_path = Path(dep_properties.strip_leading_dirs) - extractor_fn(dep_archive, buildspace_tree, Path(dep_name), pruning_set, - strip_leading_dirs_path, user_binaries) + extractor_func( + archive_path=dep_archive, buildspace_tree=buildspace_tree, + unpack_dir=Path(dep_name), ignore_files=pruning_set, + relative_to=strip_leading_dirs_path, extractors=extractors) -def retrieve_and_extract(config_bundle, buildspace_downloads, buildspace_tree, - prune_binaries=True, show_progress=True, user_binaries={}): +def retrieve_and_extract(config_bundle, buildspace_downloads, buildspace_tree, #pylint: disable=too-many-arguments + prune_binaries=True, show_progress=True, extractors=None): """ Downloads, checks, and unpacks the Chromium source code and extra dependencies defined in the config bundle into the buildspace tree. - Currently for extra dependencies, only compressed tar files are supported. buildspace_downloads is the path to the buildspace downloads directory, and buildspace_tree is the path to the buildspace tree. + extractors is a dictionary of PlatformEnum to a command or path to the + extractor binary. Defaults to 'tar' for tar, and '_use_registry' for 7-Zip. Raises FileExistsError when the buildspace tree already exists and is not empty Raises FileNotFoundError when buildspace/downloads does not exist or through @@ -197,10 +207,14 @@ def retrieve_and_extract(config_bundle, buildspace_downloads, buildspace_tree, remaining_files = set(config_bundle.pruning) else: remaining_files = set() - _setup_chromium_source(config_bundle, buildspace_downloads, buildspace_tree, show_progress, - remaining_files, user_binaries) - _setup_extra_deps(config_bundle, buildspace_downloads, buildspace_tree, show_progress, - remaining_files, user_binaries) + _setup_chromium_source( + config_bundle=config_bundle, buildspace_downloads=buildspace_downloads, + buildspace_tree=buildspace_tree, show_progress=show_progress, + pruning_set=remaining_files, extractors=extractors) + _setup_extra_deps( + config_bundle=config_bundle, buildspace_downloads=buildspace_downloads, + buildspace_tree=buildspace_tree, show_progress=show_progress, + pruning_set=remaining_files, extractors=extractors) if remaining_files: logger = get_logger() for path in remaining_files: