aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Commands.md3
-rw-r--r--docs/markdown/snippets/devenv.md5
-rw-r--r--mesonbuild/mdevenv.py34
-rw-r--r--mesonbuild/minstall.py20
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: