diff options
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/cargo/__init__.py | 5 | ||||
-rw-r--r-- | mesonbuild/cargo/interpreter.py | 46 | ||||
-rw-r--r-- | mesonbuild/cargo/manifest.py | 17 | ||||
-rw-r--r-- | mesonbuild/wrap/wrap.py | 45 |
4 files changed, 91 insertions, 22 deletions
diff --git a/mesonbuild/cargo/__init__.py b/mesonbuild/cargo/__init__.py index 0007b9d..10cb0be 100644 --- a/mesonbuild/cargo/__init__.py +++ b/mesonbuild/cargo/__init__.py @@ -1,5 +1,6 @@ __all__ = [ - 'interpret' + 'interpret', + 'load_wraps', ] -from .interpreter import interpret +from .interpreter import interpret, load_wraps diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 1d06474..13568cd 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -18,12 +18,14 @@ import json import os import shutil import collections +import urllib.parse import typing as T from . import builder from . import version from ..mesonlib import MesonException, Popen_safe, OptionKey -from .. import coredata, options +from .. import coredata, options, mlog +from ..wrap.wrap import PackageDefinition if T.TYPE_CHECKING: from types import ModuleType @@ -731,3 +733,45 @@ def interpret(subp_name: str, subdir: str, env: Environment) -> T.Tuple[mparser. ast.extend(_create_lib(cargo, build, crate_type)) return build.block(ast), project_options + + +def load_wraps(source_dir: str, subproject_dir: str) -> T.List[PackageDefinition]: + """ Convert Cargo.lock into a list of wraps """ + + wraps: T.List[PackageDefinition] = [] + filename = os.path.join(source_dir, 'Cargo.lock') + if os.path.exists(filename): + cargolock = T.cast('manifest.CargoLock', load_toml(filename)) + for package in cargolock['package']: + name = package['name'] + version = package['version'] + subp_name = _dependency_name(name, _version_to_api(version)) + source = package.get('source') + if source is None: + # This is project's package, or one of its workspace members. + pass + elif source == 'registry+https://github.com/rust-lang/crates.io-index': + url = f'https://crates.io/api/v1/crates/{name}/{version}/download' + directory = f'{name}-{version}' + wraps.append(PackageDefinition.from_values(subp_name, subproject_dir, 'file', { + 'directory': directory, + 'source_url': url, + 'source_filename': f'{directory}.tar.gz', + 'source_hash': package['checksum'], + 'method': 'cargo', + })) + elif source.startswith('git+'): + parts = urllib.parse.urlparse(source[4:]) + query = urllib.parse.parse_qs(parts.query) + branch = query['branch'][0] if 'branch' in query else '' + revision = parts.fragment or branch + url = urllib.parse.urlunparse(parts._replace(params='', query='', fragment='')) + wraps.append(PackageDefinition.from_values(subp_name, subproject_dir, 'git', { + 'directory': name, + 'url': url, + 'revision': revision, + 'method': 'cargo', + })) + else: + mlog.warning(f'Unsupported source URL in {filename}: {source}') + return wraps diff --git a/mesonbuild/cargo/manifest.py b/mesonbuild/cargo/manifest.py index e6192d0..183d91e 100644 --- a/mesonbuild/cargo/manifest.py +++ b/mesonbuild/cargo/manifest.py @@ -225,3 +225,20 @@ class VirtualManifest(TypedDict): """ workspace: Workspace + +class CargoLockPackage(TypedDict, total=False): + + """A description of a package in the Cargo.lock file format.""" + + name: str + version: str + source: str + checksum: str + + +class CargoLock(TypedDict, total=False): + + """A description of the Cargo.lock file format.""" + + version: str + package: T.List[CargoLockPackage] diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index 96b0ef3..4e98c60 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -324,25 +324,32 @@ class Resolver: mlog.warning(f'failed to process netrc file: {e}.', fatal=False) def load_wraps(self) -> None: - if not os.path.isdir(self.subdir_root): - return - root, dirs, files = next(os.walk(self.subdir_root)) - ignore_dirs = {'packagecache', 'packagefiles'} - for i in files: - if not i.endswith('.wrap'): - continue - fname = os.path.join(self.subdir_root, i) - wrap = PackageDefinition.from_wrap_file(fname, self.subproject) - self.wraps[wrap.name] = wrap - ignore_dirs |= {wrap.directory, wrap.name} - # Add dummy package definition for directories not associated with a wrap file. - for i in dirs: - if i in ignore_dirs: - continue - fname = os.path.join(self.subdir_root, i) - wrap = PackageDefinition.from_directory(fname) - self.wraps[wrap.name] = wrap - + # Load Cargo.lock at the root of source tree + source_dir = os.path.dirname(self.subdir_root) + if os.path.exists(os.path.join(source_dir, 'Cargo.lock')): + from .. import cargo + for wrap in cargo.load_wraps(source_dir, self.subdir_root): + self.wraps[wrap.name] = wrap + # Load subprojects/*.wrap + if os.path.isdir(self.subdir_root): + root, dirs, files = next(os.walk(self.subdir_root)) + for i in files: + if not i.endswith('.wrap'): + continue + fname = os.path.join(self.subdir_root, i) + wrap = PackageDefinition.from_wrap_file(fname, self.subproject) + self.wraps[wrap.name] = wrap + # Add dummy package definition for directories not associated with a wrap file. + ignore_dirs = {'packagecache', 'packagefiles'} + for wrap in self.wraps.values(): + ignore_dirs |= {wrap.directory, wrap.name} + for i in dirs: + if i in ignore_dirs: + continue + fname = os.path.join(self.subdir_root, i) + wrap = PackageDefinition.from_directory(fname) + self.wraps[wrap.name] = wrap + # Add provided deps and programs into our lookup tables for wrap in self.wraps.values(): self.add_wrap(wrap) |