Warn if wrap file changes

Save off the hash of the wrap file when first configuring a subproject.
When reconfiguring a subproject, check the hash of the wrap file
against the stored hash. If they don't match then warn the user.
pull/10814/head
Daniel Carson 2 years ago committed by Eli Schwartz
parent 97f248db24
commit 004575874f
  1. 13
      mesonbuild/msubprojects.py
  2. 38
      mesonbuild/wrap/wrap.py
  3. 18
      unittests/allplatformstests.py

@ -394,19 +394,22 @@ class Runner:
def update(self) -> bool:
self.log(f'Updating {self.wrap.name}...')
success = False
if self.wrap.type == 'file':
return self.update_file()
success = self.update_file()
elif self.wrap.type == 'git':
return self.update_git()
success = self.update_git()
elif self.wrap.type == 'hg':
return self.update_hg()
success = self.update_hg()
elif self.wrap.type == 'svn':
return self.update_svn()
success = self.update_svn()
elif self.wrap.type is None:
self.log(' -> Cannot update subproject with no wrap file')
else:
self.log(' -> Cannot update', self.wrap.type, 'subproject')
return True
if success:
self.wrap.update_hash_cache(self.wrap_resolver.dirname)
return success
def checkout(self) -> bool:
options = T.cast('CheckoutArguments', self.options)

@ -132,7 +132,9 @@ class PackageDefinition:
self.redirected = False
if self.has_wrap:
self.parse_wrap()
self.directory = self.values.get('directory', self.name)
self.directory = self.values.get('directory', self.name)
with open(fname, 'r', encoding='utf-8') as file:
self.wrapfile_hash = hashlib.sha256(file.read().encode('utf-8')).hexdigest()
if os.path.dirname(self.directory):
raise WrapException('Directory key must be a name and not a path')
if self.type and self.type not in ALL_TYPES:
@ -221,6 +223,14 @@ class PackageDefinition:
except KeyError:
raise WrapException(f'Missing key {key!r} in {self.basename}')
def get_hashfile(self, subproject_directory: str) -> str:
return os.path.join(subproject_directory, '.meson-subproject-wrap-hash.txt')
def update_hash_cache(self, subproject_directory: str) -> None:
if self.has_wrap:
with open(self.get_hashfile(subproject_directory), 'w', encoding='utf-8') as file:
file.write(self.wrapfile_hash + '\n')
def get_directory(subdir_root: str, packagename: str) -> str:
fname = os.path.join(subdir_root, packagename + '.wrap')
if os.path.isfile(fname):
@ -367,6 +377,7 @@ class Resolver:
# The directory is there and has meson.build? Great, use it.
if method == 'meson' and os.path.exists(meson_file):
self.validate()
return rel_path
if method == 'cmake' and os.path.exists(cmake_file):
return rel_path
@ -403,6 +414,11 @@ class Resolver:
if method == 'cmake' and not os.path.exists(cmake_file):
raise WrapException('Subproject exists but has no CMakeLists.txt file')
# At this point, the subproject has been successfully resolved for the
# first time so save off the hash of the entire wrap file for future
# reference.
self.wrap.update_hash_cache(self.dirname)
return rel_path
def check_can_download(self) -> None:
@ -504,6 +520,26 @@ class Resolver:
if push_url:
verbose_git(['remote', 'set-url', '--push', 'origin', push_url], self.dirname, check=True)
def validate(self) -> None:
# This check is only for subprojects with wraps.
if not self.wrap.has_wrap:
return
# Retrieve original hash, if it exists.
hashfile = self.wrap.get_hashfile(self.dirname)
if os.path.isfile(hashfile):
with open(hashfile, 'r', encoding='utf-8') as file:
expected_hash = file.read().strip()
else:
# If stored hash doesn't exist then don't warn.
return
actual_hash = self.wrap.wrapfile_hash
# Compare hashes and warn the user if they don't match.
if expected_hash != actual_hash:
mlog.warning(f'Subproject {self.wrap.name}\'s revision may be out of date; its wrap file has changed since it was first configured')
def is_git_full_commit_id(self, revno: str) -> bool:
result = False
if len(revno) in (40, 64): # 40 for sha1, 64 for upcoming sha256

@ -3733,10 +3733,26 @@ class AllPlatformTests(BasePlatformTests):
patch_directory = wrap_git_builddef
revision = master
'''.format(upstream_uri)))
self.init(srcdir)
out = self.init(srcdir)
self.build()
self.run_tests()
# Make sure the warning does not occur on the first init.
out_of_date_warning = 'revision may be out of date'
self.assertNotIn(out_of_date_warning, out)
# Change the wrap's revisions, reconfigure, and make sure it does
# warn on the reconfigure.
with open(os.path.join(srcdir, 'subprojects', 'wrap_git.wrap'), 'w', encoding='utf-8') as f:
f.write(textwrap.dedent('''
[wrap-git]
url = {}
patch_directory = wrap_git_builddef
revision = not-master
'''.format(upstream_uri)))
out = self.init(srcdir, extra_args='--reconfigure')
self.assertIn(out_of_date_warning, out)
def test_extract_objects_custom_target_no_warning(self):
testdir = os.path.join(self.common_test_dir, '22 object extraction')

Loading…
Cancel
Save