diff options
-rw-r--r-- | docs/markdown/Commands.md | 3 | ||||
-rw-r--r-- | docs/markdown/snippets/devenv.md | 5 | ||||
-rw-r--r-- | mesonbuild/mdevenv.py | 34 | ||||
-rw-r--r-- | mesonbuild/minstall.py | 20 |
4 files changed, 47 insertions, 15 deletions
diff --git a/docs/markdown/Commands.md b/docs/markdown/Commands.md index 2dbe79b..2623b5c 100644 --- a/docs/markdown/Commands.md +++ b/docs/markdown/Commands.md @@ -321,4 +321,7 @@ These variables are set in environment in addition to those set using `meson.add layout must match the installed tree layout otherwise `import subdir.mod` cannot work. +Since *Since 0.62.0* if bash-completion scripts are being installed and the +shell is bash, they will be automatically sourced. + {{ devenv_arguments.inc }} diff --git a/docs/markdown/snippets/devenv.md b/docs/markdown/snippets/devenv.md index 0d18889..19a272c 100644 --- a/docs/markdown/snippets/devenv.md +++ b/docs/markdown/snippets/devenv.md @@ -3,3 +3,8 @@ `PYTHONPATH` now includes every directory where a python module is being installed using [`python.install_sources()`](Python-module.md#install_sources) and [`python.extension_module()`](Python-module.md#extension_module). + +## Bash completion scripts sourced in `meson devenv` + +If bash-completion scripts are being installed and the shell is bash, they will +be automatically sourced. diff --git a/mesonbuild/mdevenv.py b/mesonbuild/mdevenv.py index 3c522a6..3bd66ef 100644 --- a/mesonbuild/mdevenv.py +++ b/mesonbuild/mdevenv.py @@ -3,10 +3,12 @@ import argparse import tempfile from pathlib import Path -from . import build -from .mesonlib import MesonException, RealPathAction, is_windows, setup_vsenv +from . import build, minstall, dependencies +from .mesonlib import MesonException, RealPathAction, is_windows, setup_vsenv, OptionKey import typing as T +if T.TYPE_CHECKING: + from .backends import InstallData def add_arguments(parser: argparse.ArgumentParser) -> None: parser.add_argument('-C', dest='wd', action=RealPathAction, @@ -36,11 +38,30 @@ def get_env(b: build.Build, build_dir: str) -> T.Dict[str, str]: return extra_env.get_env(env) +def bash_completion_files(b: build.Build, install_data: 'InstallData') -> T.List[str]: + result = [] + dep = dependencies.PkgConfigDependency('bash-completion', b.environment, + {'silent': True, 'version': '>=2.10'}) + if dep.found(): + prefix = b.environment.coredata.get_option(OptionKey('prefix')) + assert isinstance(prefix, str), 'for mypy' + datadir = b.environment.coredata.get_option(OptionKey('datadir')) + assert isinstance(datadir, str), 'for mypy' + datadir_abs = os.path.join(prefix, datadir) + completionsdir = dep.get_variable(pkgconfig='completionsdir', pkgconfig_define=['datadir', datadir_abs]) + assert isinstance(completionsdir, str), 'for mypy' + completionsdir_path = Path(completionsdir) + for f in install_data.data: + if completionsdir_path in Path(f.install_path).parents: + result.append(f.path) + return result + def run(options: argparse.Namespace) -> int: buildfile = Path(options.wd) / 'meson-private' / 'build.dat' if not buildfile.is_file(): raise MesonException(f'Directory {options.wd!r} does not seem to be a Meson build directory.') b = build.load(options.wd) + install_data = minstall.load_install_data(str(buildfile.parent / 'install.dat')) setup_vsenv(b.need_vsenv) devenv = get_env(b, options.wd) @@ -64,12 +85,15 @@ def run(options: argparse.Namespace) -> int: args += ['/k', f'prompt {prompt_prefix} $P$G'] else: args = [os.environ.get("SHELL", os.path.realpath("/bin/sh"))] - if "bash" in args[0] and not os.environ.get("MESON_DISABLE_PS1_OVERRIDE"): + if "bash" in args[0]: + # Let the GC remove the tmp file tmprc = tempfile.NamedTemporaryFile(mode='w') tmprc.write('[ -e ~/.bashrc ] && . ~/.bashrc\n') - tmprc.write(f'export PS1="{prompt_prefix} $PS1"') + if not os.environ.get("MESON_DISABLE_PS1_OVERRIDE"): + tmprc.write(f'export PS1="{prompt_prefix} $PS1"\n') + for f in bash_completion_files(b, install_data): + tmprc.write(f'. "{f}"\n') tmprc.flush() - # Let the GC remove the tmp file args.append("--rcfile") args.append(tmprc.name) diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index 75a3240..80b0239 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -127,6 +127,15 @@ class DirMaker: append_to_log(self.lf, d) +def load_install_data(fname: str) -> InstallData: + with open(fname, 'rb') as ifile: + obj = pickle.load(ifile) + if not isinstance(obj, InstallData) or not hasattr(obj, 'version'): + raise MesonVersionMismatchException('<unknown>', coredata_version) + if major_versions_differ(obj.version, coredata_version): + raise MesonVersionMismatchException(obj.version, coredata_version) + return obj + def is_executable(path: str, follow_symlinks: bool = False) -> bool: '''Checks whether any of the "x" bits are set in the source file mode.''' return bool(os.stat(path, follow_symlinks=follow_symlinks).st_mode & 0o111) @@ -510,17 +519,8 @@ class Installer: self.do_copyfile(abs_src, abs_dst) self.set_mode(abs_dst, install_mode, data.install_umask) - @staticmethod - def check_installdata(obj: InstallData) -> InstallData: - if not isinstance(obj, InstallData) or not hasattr(obj, 'version'): - raise MesonVersionMismatchException('<unknown>', coredata_version) - if major_versions_differ(obj.version, coredata_version): - raise MesonVersionMismatchException(obj.version, coredata_version) - return obj - def do_install(self, datafilename: str) -> None: - with open(datafilename, 'rb') as ifile: - d = self.check_installdata(pickle.load(ifile)) + d = load_install_data(datafilename) destdir = self.options.destdir if destdir is None: |