aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/cargo/__init__.py5
-rw-r--r--mesonbuild/cargo/interpreter.py46
-rw-r--r--mesonbuild/cargo/manifest.py17
-rw-r--r--mesonbuild/wrap/wrap.py45
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)