summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharlie Hutcheson <chaz.hutcheson@gmail.com>2025-08-08 20:19:39 -0700
committerDylan Baker <dylan@pnwbakers.com>2025-10-17 14:55:35 -0700
commit1e7f6f09eba8f9ac121d8f58593bbbabebdc773a (patch)
treed570cf10d7cd18d66b3588866e354fdb86373638
parentf4ad0ef5a3c9ff69daed2987249c9a6fe30465c6 (diff)
downloadmeson-1e7f6f09eba8f9ac121d8f58593bbbabebdc773a.tar.gz
make wrap search custom subprojects dirs
Changes from Dylan: - Don't use Path - merge the lint fixes - Fix some typing issues - Handle non-meson projects - Remove some code duplication by putting `get_subproject_dir` in utils
-rw-r--r--mesonbuild/utils/universal.py23
-rw-r--r--mesonbuild/wrap/wrap.py1
-rw-r--r--mesonbuild/wrap/wraptool.py34
3 files changed, 48 insertions, 10 deletions
diff --git a/mesonbuild/utils/universal.py b/mesonbuild/utils/universal.py
index 6ba5474e4..e117f862f 100644
--- a/mesonbuild/utils/universal.py
+++ b/mesonbuild/utils/universal.py
@@ -108,6 +108,7 @@ __all__ = [
'get_compiler_for_source',
'get_filenames_templates_dict',
'get_rsp_threshold',
+ 'get_subproject_dir',
'get_variable_regex',
'get_wine_shortpath',
'git',
@@ -2065,6 +2066,8 @@ def detect_subprojects(spdir_name: str, current_dir: str = '',
continue
append_this = True
if os.path.isdir(trial):
+ spdir_name = get_subproject_dir(trial) or 'subprojects'
+
detect_subprojects(spdir_name, trial, result)
elif trial.endswith('.wrap') and os.path.isfile(trial):
basename = os.path.splitext(basename)[0]
@@ -2502,3 +2505,23 @@ class lazy_property(T.Generic[_T]):
value = self.__func(instance)
setattr(instance, self.__name, value)
return value
+
+
+def get_subproject_dir(directory: str = '.') -> T.Optional[str]:
+ """Get the name of the subproject directory for a specific project.
+
+ If the subproject does not have a meson.build file, it is called in an
+ invalid directory, it returns None
+
+ :param directory: Where to search, defaults to current working directory
+ :return: the name of the subproject directory or None.
+ """
+ from ..ast import IntrospectionInterpreter
+ from ..interpreterbase.exceptions import InvalidArguments
+ intr = IntrospectionInterpreter(directory, '', 'none')
+ try:
+ intr.load_root_meson_file()
+ except InvalidArguments: # Root meson file cannot be found
+ return None
+
+ return intr.extract_subproject_dir() or 'subprojects'
diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py
index d353130b8..8851b30a1 100644
--- a/mesonbuild/wrap/wrap.py
+++ b/mesonbuild/wrap/wrap.py
@@ -164,6 +164,7 @@ def parse_patch_url(patch_url: str) -> T.Tuple[str, str]:
else:
raise WrapException(f'Invalid wrapdb URL {patch_url}')
+
class WrapException(MesonException):
pass
diff --git a/mesonbuild/wrap/wraptool.py b/mesonbuild/wrap/wraptool.py
index 6f97fe221..85175114e 100644
--- a/mesonbuild/wrap/wraptool.py
+++ b/mesonbuild/wrap/wraptool.py
@@ -11,8 +11,6 @@ import typing as T
from glob import glob
from .wrap import (open_wrapdburl, read_and_decompress, WrapException, get_releases,
get_releases_data, parse_patch_url)
-from pathlib import Path
-
from .. import mesonlib, msubprojects
if T.TYPE_CHECKING:
@@ -91,11 +89,12 @@ def get_latest_version(name: str, allow_insecure: bool) -> T.Tuple[str, str]:
def install(options: 'argparse.Namespace') -> None:
name = options.name
- if not os.path.isdir('subprojects'):
+ subproject_dir_name = mesonlib.get_subproject_dir()
+ if subproject_dir_name is None or not os.path.isdir(subproject_dir_name):
raise SystemExit('Subprojects dir not found. Run this script in your source root directory.')
- if os.path.isdir(os.path.join('subprojects', name)):
+ if os.path.isdir(os.path.join(subproject_dir_name, name)):
raise SystemExit('Subproject directory for this project already exists.')
- wrapfile = os.path.join('subprojects', name + '.wrap')
+ wrapfile = os.path.join(subproject_dir_name, name + '.wrap')
if os.path.exists(wrapfile):
raise SystemExit('Wrap file already exists.')
(version, revision) = get_latest_version(name, options.allow_insecure)
@@ -143,11 +142,20 @@ def do_promotion(from_path: str, spdir_name: str) -> None:
outputdir = os.path.join(spdir_name, sproj_name)
if os.path.exists(outputdir):
raise SystemExit(f'Output dir {outputdir} already exists. Will not overwrite.')
- shutil.copytree(from_path, outputdir, ignore=shutil.ignore_patterns('subprojects'))
+
+ subpdir = mesonlib.get_subproject_dir()
+ if subpdir is not None:
+ ignore = shutil.ignore_patterns(subpdir)
+ else:
+ ignore = None
+
+ shutil.copytree(from_path, outputdir, ignore=ignore)
def promote(options: 'argparse.Namespace') -> None:
argument = options.project_path
- spdir_name = 'subprojects'
+ spdir_name = mesonlib.get_subproject_dir()
+ if spdir_name is None:
+ raise SystemExit('Subproject dir not found. Run this script in your source root directory.')
sprojs = mesonlib.detect_subprojects(spdir_name)
# check if the argument is a full path to a subproject directory or wrap file
@@ -170,7 +178,9 @@ def promote(options: 'argparse.Namespace') -> None:
def status(options: 'argparse.Namespace') -> None:
print('Subproject status')
- for w in glob('subprojects/*.wrap'):
+ subdir = mesonlib.get_subproject_dir()
+ assert subdir is not None, "This should only happen in a non-native subproject"
+ for w in glob(f'{subdir}/*.wrap'):
name = os.path.basename(w)[:-5]
try:
(latest_branch, latest_revision) = get_latest_version(name, options.allow_insecure)
@@ -189,8 +199,12 @@ def status(options: 'argparse.Namespace') -> None:
def update_db(options: 'argparse.Namespace') -> None:
data = get_releases_data(options.allow_insecure)
- Path('subprojects').mkdir(exist_ok=True)
- with Path('subprojects/wrapdb.json').open('wb') as f:
+ subproject_dir_name = mesonlib.get_subproject_dir()
+ if subproject_dir_name is None:
+ raise SystemExit('Subproject dir not found. Run this script in your source root directory.')
+
+ os.makedirs(subproject_dir_name, exist_ok=True)
+ with open(os.path.join(subproject_dir_name, 'wrapdb.json'), 'wb') as f:
f.write(data)
def run(options: 'argparse.Namespace') -> int: