build: use the unified pickle loader to handle more edge cases

We have divergent implementations of loading a pickled *.dat file. The
Build class loader has a better error message. But the generic loader
handles TypeError and ModuleNotFoundError. Merge the implementations,
and use it for Build as well.

Fixes #11051
This commit is contained in:
Eli Schwartz 2022-11-16 19:20:33 -05:00 committed by Dylan Baker
parent 3a4aa109b4
commit 0d3be23377
2 changed files with 12 additions and 20 deletions

View File

@ -36,7 +36,7 @@ from .mesonlib import (
extract_as_list, typeslistify, stringlistify, classify_unity_sources,
get_filenames_templates_dict, substitute_values, has_path_sep,
OptionKey, PerMachineDefaultable, OptionOverrideProxy,
MesonBugException, EnvironmentVariables
MesonBugException, EnvironmentVariables, pickle_load,
)
from .compilers import (
is_object, clink_langs, sort_clink, all_languages,
@ -2900,24 +2900,11 @@ def get_sources_string_names(sources, backend):
def load(build_dir: str) -> Build:
filename = os.path.join(build_dir, 'meson-private', 'build.dat')
load_fail_msg = f'Build data file {filename!r} is corrupted. Try with a fresh build tree.'
nonexisting_fail_msg = f'No such build data file as "{filename!r}".'
try:
with open(filename, 'rb') as f:
obj = pickle.load(f)
return pickle_load(filename, 'Build data', Build)
except FileNotFoundError:
raise MesonException(nonexisting_fail_msg)
except (pickle.UnpicklingError, EOFError):
raise MesonException(load_fail_msg)
except AttributeError:
raise MesonException(
f"Build data file {filename!r} references functions or classes that don't "
"exist. This probably means that it was generated with an old "
"version of meson. Try running from the source directory "
f"meson setup {build_dir} --wipe")
if not isinstance(obj, Build):
raise MesonException(load_fail_msg)
return obj
raise MesonException(f'No such build data file as {filename!r}.')
def save(obj: Build, filename: str) -> None:
with open(filename, 'wb') as f:

View File

@ -2289,16 +2289,21 @@ def pickle_load(filename: str, object_name: str, object_type: T.Type) -> T.Any:
except (pickle.UnpicklingError, EOFError):
raise MesonException(load_fail_msg)
except (TypeError, ModuleNotFoundError, AttributeError):
build_dir = os.path.dirname(os.path.dirname(filename))
raise MesonException(
f"{object_name} file {filename!r} references functions or classes that don't "
"exist. This probably means that it was generated with an old "
"version of meson.")
"version of meson. Try running from the source directory "
f'meson setup {build_dir} --wipe')
if not isinstance(obj, object_type):
raise MesonException(load_fail_msg)
from ..coredata import version as coredata_version
from ..coredata import major_versions_differ, MesonVersionMismatchException
if major_versions_differ(obj.version, coredata_version):
raise MesonVersionMismatchException(obj.version, coredata_version)
version = getattr(obj, 'version', None)
if version is None:
version = obj.environment.coredata.version
if major_versions_differ(version, coredata_version):
raise MesonVersionMismatchException(version, coredata_version)
return obj