mirror of
https://github.com/mesonbuild/meson.git
synced 2026-11-06 05:16:42 +00:00
Fix meson dist --include-subprojects with redirected wraps
When redirected wraps were used, mdist was searching for the source directory in the subprojects directory of the root project. However, the source for redirected wraps is actually located in some child subprojects directory. Subsequently, this resulted in a FileNotFoundError. By skipping redirected wraps as we collect subprojects, we can effectively prevent the issue from occuring because the authoritative subproject will be picked up and included in the dist. Fixes: https://github.com/mesonbuild/meson/issues/12489 Signed-off-by: Tristan Partin <tristan@partin.io>
This commit is contained in:
1 parent
097b497d24
commit
66ab168e6f
3 files changed
+91
-4
No files matched your search
+5
-2
@@ -399,8 +399,11 @@ def run(options: argparse.Namespace) -> int:
|
||||
if options.include_subprojects:
|
||||
resolver = wrap.Resolver(src_root, b.subproject_dir, silent=True)
|
||||
for sub in set(itertools.chain(b.projects.host, b.projects.build)):
|
||||
if sub:
|
||||
directory = resolver.get_directory(sub)
|
||||
if not sub:
|
||||
continue
|
||||
|
||||
directory = resolver.get_directory(sub)
|
||||
if directory is not None:
|
||||
subprojects[sub] = os.path.join(b.subproject_dir, directory)
|
||||
extra_meson_args.append('-Dwrap_mode=nodownload')
|
||||
|
||||
|
||||
@@ -520,9 +520,11 @@ class Resolver:
|
||||
self.cargolocks.update(other_resolver.cargolocks)
|
||||
self.loaded_dirs.add(subdir)
|
||||
|
||||
def get_directory(self, packagename: str) -> str:
|
||||
def get_directory(self, packagename: str) -> T.Optional[str]:
|
||||
wrap = self.wraps.get(packagename)
|
||||
return wrap.directory if wrap else packagename
|
||||
if wrap:
|
||||
return None if wrap.redirected else wrap.directory
|
||||
return packagename
|
||||
|
||||
def find_dep_provider(self, packagename: str) -> T.Tuple[T.Optional[str], T.Optional[str]]:
|
||||
# Python's ini parser converts all key values to lowercase.
|
||||
|
||||
@@ -1675,6 +1675,88 @@ class AllPlatformTests(BasePlatformTests):
|
||||
# fails sometimes.
|
||||
pass
|
||||
|
||||
@skipIfNoExecutable('git')
|
||||
def test_dist_nested_promoted_subproject(self):
|
||||
'''
|
||||
https://github.com/mesonbuild/meson/issues/12489
|
||||
|
||||
A subproject (e.g. glib) can itself depend on a nested subproject
|
||||
(e.g. gvdb) whose sources are bundled inside the outer subproject's
|
||||
own "subprojects" directory rather than the main project's. Meson
|
||||
promotes the wrap file for such a nested subproject to the main
|
||||
project's subprojects directory (writing a [wrap-redirect] wrap
|
||||
there), but the actual source directory stays nested. `meson dist
|
||||
--include-subprojects` used to look for the nested subproject
|
||||
directly under the main project's subprojects directory (following
|
||||
the promoted wrap file naively) and crashed with a FileNotFoundError
|
||||
because that directory did not exist there.
|
||||
'''
|
||||
if self.backend is not Backend.ninja:
|
||||
raise SkipTest('Dist is only supported with Ninja')
|
||||
|
||||
with tempfile.TemporaryDirectory() as project_dir:
|
||||
with open(os.path.join(project_dir, 'meson.build'), 'w', encoding='utf-8') as f:
|
||||
f.write(textwrap.dedent('''\
|
||||
project('gtk', version : '1.0')
|
||||
subproject('glib')
|
||||
'''))
|
||||
|
||||
glib_dir = os.path.join(project_dir, 'subprojects', 'glib')
|
||||
gvdb_dir = os.path.join(glib_dir, 'subprojects', 'gvdb')
|
||||
os.makedirs(gvdb_dir)
|
||||
|
||||
# glib is a normal subproject with its own wrap file
|
||||
with open(os.path.join(project_dir, 'subprojects', 'glib.wrap'), 'w', encoding='utf-8') as f:
|
||||
f.write(textwrap.dedent('''\
|
||||
[wrap-file]
|
||||
directory = glib
|
||||
'''))
|
||||
|
||||
# Only the main project and glib's wrap file are tracked by git;
|
||||
# glib itself is *not* a git repository, mimicking a subproject
|
||||
# fetched/extracted from a tarball
|
||||
git_init(project_dir)
|
||||
|
||||
with open(os.path.join(glib_dir, 'meson.build'), 'w', encoding='utf-8') as f:
|
||||
f.write(textwrap.dedent('''\
|
||||
project('glib', version : '1.0')
|
||||
subproject('gvdb')
|
||||
'''))
|
||||
|
||||
# gvdb is bundled inside glib's own subprojects directory, with
|
||||
# its sources already extracted there
|
||||
with open(os.path.join(glib_dir, 'subprojects', 'gvdb.wrap'), 'w', encoding='utf-8') as f:
|
||||
f.write(textwrap.dedent('''\
|
||||
[wrap-file]
|
||||
directory = gvdb
|
||||
'''))
|
||||
with open(os.path.join(gvdb_dir, 'meson.build'), 'w', encoding='utf-8') as f:
|
||||
f.write(textwrap.dedent('''\
|
||||
project('gvdb', version : '1.0')
|
||||
'''))
|
||||
|
||||
self.init(project_dir)
|
||||
# Configuring writes the promoted [wrap-redirect] wrap file
|
||||
redirect_wrap = os.path.join(project_dir, 'subprojects', 'gvdb.wrap')
|
||||
self.assertPathExists(redirect_wrap)
|
||||
with open(redirect_wrap, encoding='utf-8') as f:
|
||||
self.assertIn('[wrap-redirect]', f.read())
|
||||
|
||||
self._run(self.meson_command + ['dist', '--include-subprojects', '--no-tests',
|
||||
'--formats', 'zip'],
|
||||
workdir=self.builddir)
|
||||
|
||||
zip_distfile = os.path.join(self.distdir, 'gtk-1.0.zip')
|
||||
self.assertPathExists(zip_distfile)
|
||||
z = zipfile.ZipFile(zip_distfile)
|
||||
names = set(z.namelist())
|
||||
# gvdb must end up nested inside glib, where it really lives...
|
||||
self.assertIn('gtk-1.0/subprojects/glib/subprojects/gvdb/meson.build', names)
|
||||
# ... and must not be duplicated (or looked up) directly under the
|
||||
# main project's subprojects directory.
|
||||
self.assertNotIn('gtk-1.0/subprojects/gvdb/meson.build', names)
|
||||
self.assertNotIn('gtk-1.0/subprojects/gvdb.wrap', names)
|
||||
|
||||
def create_dummy_subproject(self, project_dir, name):
|
||||
path = os.path.join(project_dir, 'subprojects', name)
|
||||
os.makedirs(path)
|
||||
|
||||
Reference in new issue
Block a user