From 04f233a80d570c90c1a152114cbf3bdad6a61607 Mon Sep 17 00:00:00 2001 From: Charles Brunet Date: Thu, 9 Feb 2023 07:19:52 -0500 Subject: [PATCH] allow install script to run in dry-run mode --- docs/markdown/snippets/run_script_dry_run.md | 8 ++++++++ docs/yaml/builtins/meson.yaml | 12 ++++++++++++ mesonbuild/interpreter/mesonmain.py | 3 +++ mesonbuild/minstall.py | 8 +++++--- mesonbuild/utils/core.py | 1 + .../common/53 install script/meson.build | 2 +- .../common/53 install script/myinstall.py | 18 ++++++++++++++---- unittests/allplatformstests.py | 14 ++++++++++++++ 8 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 docs/markdown/snippets/run_script_dry_run.md diff --git a/docs/markdown/snippets/run_script_dry_run.md b/docs/markdown/snippets/run_script_dry_run.md new file mode 100644 index 000000000..aee32c72c --- /dev/null +++ b/docs/markdown/snippets/run_script_dry_run.md @@ -0,0 +1,8 @@ +## Allow custom install scripts to run with `--dry-run` option + +An new `dry_run` keyword is added to `meson.add_install_script()` +to allow a custom install script to run when meson is invoked +with `meson install --dry-run`. + +In dry run mode, the `MESON_INSTALL_DRY_RUN` environment variable +is set. diff --git a/docs/yaml/builtins/meson.yaml b/docs/yaml/builtins/meson.yaml index 1dd746f94..5ef445d84 100644 --- a/docs/yaml/builtins/meson.yaml +++ b/docs/yaml/builtins/meson.yaml @@ -64,6 +64,9 @@ methods: *(since 0.54.0)* If `meson install` is called with the `--quiet` option, the environment variable `MESON_INSTALL_QUIET` will be set. + *(since 1.1.0)* If `meson install` is called with the `--dry-run` option, the + environment variable `MESON_INSTALL_DRY_RUN` will be set. + Meson uses the `DESTDIR` environment variable as set by the inherited environment to determine the (temporary) installation location for files. Your install script must be aware of this while @@ -125,6 +128,15 @@ methods: to install only a subset of the files. By default the script has no install tag which means it is not being run when `meson install --tags` argument is specified. + + dry_run: + type: bool + since: 1.1.0 + default: false + description: | + If `true` the script will be run even if `--dry-run` option is provided to + the `meson install` command. The script can use the `MESON_INSTALL_DRY_RUN` + variable to determine if it is in dry run mode or not. - name: add_postconf_script returns: void diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py index c8c80b29b..cd3d5edde 100644 --- a/mesonbuild/interpreter/mesonmain.py +++ b/mesonbuild/interpreter/mesonmain.py @@ -38,6 +38,7 @@ if T.TYPE_CHECKING: skip_if_destdir: bool install_tag: str + dry_run: bool class NativeKW(TypedDict): @@ -152,6 +153,7 @@ class MesonMain(MesonInterpreterObject): 'meson.add_install_script', KwargInfo('skip_if_destdir', bool, default=False, since='0.57.0'), KwargInfo('install_tag', (str, NoneType), since='0.60.0'), + KwargInfo('dry_run', bool, default=False, since='1.1.0'), ) def add_install_script_method( self, @@ -162,6 +164,7 @@ class MesonMain(MesonInterpreterObject): script = self._find_source_script('add_install_script', args[0], script_args) script.skip_if_destdir = kwargs['skip_if_destdir'] script.tag = kwargs['install_tag'] + script.dry_run = kwargs['dry_run'] self.build.install_scripts.append(script) @typed_pos_args( diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index 8c74990ad..40c2d2d41 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -361,9 +361,9 @@ class Installer: return p.returncode, o, e return 0, '', '' - def run_exe(self, *args: T.Any, **kwargs: T.Any) -> int: - if not self.dry_run: - return run_exe(*args, **kwargs) + def run_exe(self, exe: ExecutableSerialisation, extra_env: T.Optional[T.Dict[str, str]] = None) -> int: + if (not self.dry_run) or exe.dry_run: + return run_exe(exe, extra_env) return 0 def should_install(self, d: T.Union[TargetInstallData, InstallEmptyDir, @@ -655,6 +655,8 @@ class Installer: } if self.options.quiet: env['MESON_INSTALL_QUIET'] = '1' + if self.dry_run: + env['MESON_INSTALL_DRY_RUN'] = '1' for i in d.install_scripts: if not self.should_install(i): diff --git a/mesonbuild/utils/core.py b/mesonbuild/utils/core.py index 43984131d..9b9afab86 100644 --- a/mesonbuild/utils/core.py +++ b/mesonbuild/utils/core.py @@ -152,3 +152,4 @@ class ExecutableSerialisation: self.pickled = False self.skip_if_destdir = False self.subproject = '' + self.dry_run = False diff --git a/test cases/common/53 install script/meson.build b/test cases/common/53 install script/meson.build index 24d5dc84b..03f8b2c9f 100644 --- a/test cases/common/53 install script/meson.build +++ b/test cases/common/53 install script/meson.build @@ -1,6 +1,6 @@ project('custom install script', 'c') -meson.add_install_script('myinstall.py', 'diiba/daaba', 'file.dat') +meson.add_install_script('myinstall.py', 'diiba/daaba', 'file.dat', dry_run: true) meson.add_install_script('myinstall.py', 'this/should', 'also-work.dat') subdir('src') diff --git a/test cases/common/53 install script/myinstall.py b/test cases/common/53 install script/myinstall.py index a57334242..5e5a929fa 100755 --- a/test cases/common/53 install script/myinstall.py +++ b/test cases/common/53 install script/myinstall.py @@ -5,6 +5,7 @@ import os import shutil prefix = os.environ['MESON_INSTALL_DESTDIR_PREFIX'] +dry_run = bool(os.environ.get('MESON_INSTALL_DRY_RUN')) def main() -> None: @@ -16,15 +17,24 @@ def main() -> None: dirname = os.path.join(prefix, args.dirname) if not os.path.exists(dirname): - os.makedirs(dirname) + if dry_run: + print(f"DRYRUN: Creating directory {dirname}") + else: + os.makedirs(dirname) if args.mode == 'create': for name in args.files: - with open(os.path.join(dirname, name), 'w') as f: - f.write('') + if dry_run: + print(f'DRYRUN: Writing file {name}') + else: + with open(os.path.join(dirname, name), 'w') as f: + f.write('') else: for name in args.files: - shutil.copy(name, dirname) + if dry_run: + print(f"DRYRUN: Copying file {name} to {dirname}") + else: + shutil.copy(name, dirname) if __name__ == "__main__": diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 5f4af3b24..64ac749a7 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -4243,6 +4243,20 @@ class AllPlatformTests(BasePlatformTests): do_install('runtime,custom', expected_runtime_custom, 1) do_install(None, expected_all, 2) + + def test_install_script_dry_run(self): + testdir = os.path.join(self.common_test_dir, '53 install script') + self.init(testdir) + self.build() + + cmd = self.meson_command + ['install', '--dry-run', '--destdir', self.installdir] + outputs = self._run(cmd, workdir=self.builddir) + + installpath = Path(self.installdir) + self.assertFalse((installpath / 'usr/diiba/daaba/file.dat').exists()) + self.assertIn("DRYRUN: Writing file file.dat", outputs) + + def test_introspect_install_plan(self): testdir = os.path.join(self.unit_test_dir, '98 install all targets') introfile = os.path.join(self.builddir, 'meson-info', 'intro-install_plan.json')