Fix install_data() default install path

This fixes two issues in constructing the default installation path
when install_dir is not specified:

- inside a subproject, install_data() would construct the destination
  path using the parent project name instead than the current project
  name,

- when specifying preserve_path, install_data() would construct the
  destination path omitting the project name.

Fixes #11910.
pull/12044/head
Daniele Nicolodi 2 years ago committed by Eli Schwartz
parent a0f165b2fa
commit 9eb7fe332f
  1. 2
      docs/yaml/functions/install_data.yaml
  2. 3
      mesonbuild/backend/backends.py
  3. 28
      mesonbuild/interpreter/interpreter.py
  4. 1
      mesonbuild/modules/python.py
  5. 4
      test cases/common/12 data/meson.build
  6. 0
      test cases/common/12 data/subdir/data.txt
  7. 1
      test cases/common/12 data/subprojects/moredata/data.txt
  8. 3
      test cases/common/12 data/subprojects/moredata/meson.build
  9. 4
      test cases/common/12 data/test.json
  10. 13
      unittests/allplatformstests.py

@ -12,6 +12,8 @@ varargs:
warnings:
- the `install_mode` kwarg ignored integer values between 0.59.0 -- 1.1.0.
- an omitted `install_dir` kwarg did not work correctly inside of a subproject until 1.3.0.
- an omitted `install_dir` kwarg did not work correctly when combined with the `preserve_path` kwarg untill 1.3.0.
kwargs:
install_dir:

@ -1866,9 +1866,6 @@ class Backend:
assert isinstance(de, build.Data)
subdir = de.install_dir
subdir_name = de.install_dir_name
if not subdir:
subdir = os.path.join(self.environment.get_datadir(), self.interpreter.build.project_name)
subdir_name = os.path.join('{datadir}', self.interpreter.build.project_name)
for src_file, dst_name in zip(de.sources, de.rename):
assert isinstance(src_file, mesonlib.File)
dst_abs = os.path.join(subdir, dst_name)

@ -2465,24 +2465,31 @@ class Interpreter(InterpreterBase, HoldableObject):
'"rename" and "sources" argument lists must be the same length if "rename" is given. '
f'Rename has {len(rename)} elements and sources has {len(sources)}.')
install_dir = kwargs['install_dir']
if not install_dir:
subdir = self.active_projectname
install_dir = P_OBJ.OptionString(os.path.join(self.environment.get_datadir(), subdir), os.path.join('{datadir}', subdir))
if self.is_subproject():
FeatureNew.single_use('install_data() without install_dir inside of a subproject', '1.3.0', self.subproject,
'This was broken and would install to the project name of the parent project instead',
node)
if kwargs['preserve_path']:
FeatureNew.single_use('install_data() with preserve_path and without install_dir', '1.3.0', self.subproject,
'This was broken and would not add the project name to the install path',
node)
install_mode = self._warn_kwarg_install_mode_sticky(kwargs['install_mode'])
return self.install_data_impl(sources, kwargs['install_dir'], install_mode,
rename, kwargs['install_tag'],
return self.install_data_impl(sources, install_dir, install_mode, rename, kwargs['install_tag'],
preserve_path=kwargs['preserve_path'])
def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: T.Optional[str],
def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: str,
install_mode: FileMode, rename: T.Optional[str],
tag: T.Optional[str],
install_dir_name: T.Optional[str] = None,
install_data_type: T.Optional[str] = None,
preserve_path: bool = False) -> build.Data:
install_dir_name = install_dir.optname if isinstance(install_dir, P_OBJ.OptionString) else install_dir
idir = install_dir or ''
idir_name = install_dir_name or idir or '{datadir}'
if isinstance(idir_name, P_OBJ.OptionString):
idir_name = idir_name.optname
dirs = collections.defaultdict(list)
ret_data = []
if preserve_path:
for file in sources:
dirname = os.path.dirname(file.fname)
@ -2490,8 +2497,9 @@ class Interpreter(InterpreterBase, HoldableObject):
else:
dirs[''].extend(sources)
ret_data = []
for childdir, files in dirs.items():
d = build.Data(files, os.path.join(idir, childdir), os.path.join(idir_name, childdir),
d = build.Data(files, os.path.join(install_dir, childdir), os.path.join(install_dir_name, childdir),
install_mode, self.subproject, rename, tag, install_data_type)
ret_data.append(d)

@ -224,7 +224,6 @@ class PythonInstallation(ExternalProgramHolder):
self.interpreter.source_strings_to_files(args[0]),
install_dir,
mesonlib.FileMode(), rename=None, tag=tag, install_data_type='python',
install_dir_name=install_dir.optname,
preserve_path=kwargs['preserve_path'])
@noPosargs

@ -22,3 +22,7 @@ install_data(sources : ['vanishing/to_be_renamed_2.txt', 'to_be_renamed_3.txt'],
install_dir : 'share/renamed',
rename : ['renamed 2.txt', 'renamed 3.txt'])
install_data(sources : 'to_be_renamed_4.txt', rename : 'some/nested/path.txt')
install_data('subdir/data.txt', preserve_path : true)
subproject('moredata')

@ -0,0 +1,3 @@
project('moredata')
install_data('data.txt')

@ -10,6 +10,8 @@
{"type": "file", "file": "usr/share/renamed/renamed 2.txt"},
{"type": "file", "file": "usr/share/renamed/renamed 3.txt"},
{"type": "file", "file": "etc/etcfile.dat"},
{"type": "file", "file": "usr/bin/runscript.sh"}
{"type": "file", "file": "usr/bin/runscript.sh"},
{"type": "file", "file": "usr/share/moredata/data.txt"},
{"type": "file", "file": "usr/share/data install test/subdir/data.txt"}
]
}

@ -4130,7 +4130,8 @@ class AllPlatformTests(BasePlatformTests):
]
bar_expected = [
'bar',
'share/foo/bar.dat',
'share/bar',
'share/bar/bar.dat',
'include/bar.h',
'bin/bar' + exe_suffix,
'bar/barfile'
@ -4410,9 +4411,9 @@ class AllPlatformTests(BasePlatformTests):
Path(installpath, 'usr/share/foo2.h'),
Path(installpath, 'usr/share/out1.txt'),
Path(installpath, 'usr/share/out2.txt'),
Path(installpath, 'usr/share/install tag'),
Path(installpath, 'usr/share/install tag/aaa.txt'),
Path(installpath, 'usr/share/install tag/bbb.txt'),
Path(installpath, 'usr/share/subproject'),
Path(installpath, 'usr/share/subproject/aaa.txt'),
Path(installpath, 'usr/share/subproject/bbb.txt'),
}
def do_install(tags, expected_files, expected_scripts):
@ -4613,12 +4614,12 @@ class AllPlatformTests(BasePlatformTests):
'subproject': None,
},
f'{testdir}/subprojects/subproject/aaa.txt': {
'destination': '{datadir}/install tag/aaa.txt',
'destination': '{datadir}/subproject/aaa.txt',
'tag': None,
'subproject': 'subproject',
},
f'{testdir}/subprojects/subproject/bbb.txt': {
'destination': '{datadir}/install tag/bbb.txt',
'destination': '{datadir}/subproject/bbb.txt',
'tag': 'data',
'subproject': 'subproject',
},

Loading…
Cancel
Save