From ced9efb5793ff932a0132e79378ded4e393c200d Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Mon, 28 Jun 2021 11:53:34 -0400 Subject: Get wrap from wrapdb when not found locally Download wrap file from wrapdb automatically when it is not found locally but we have it in wrapdb.json. This makes for example `dependency('glib-2.0')` work out of the box simply by running `meson wrap update-db`, even if the project does not provide any wraps. --- mesonbuild/wrap/wrap.py | 68 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/mesonbuild/wrap/wrap.py b/mesonbuild/wrap/wrap.py index 10aa1b80e..1cc55ee7f 100644 --- a/mesonbuild/wrap/wrap.py +++ b/mesonbuild/wrap/wrap.py @@ -29,10 +29,12 @@ import configparser import time import typing as T import textwrap +import json from base64 import b64encode from netrc import netrc from pathlib import Path + from . import WrapMode from .. import coredata from ..mesonlib import quiet_git, GIT, ProgressBar, MesonException, windows_proof_rmtree, Popen_safe @@ -262,8 +264,12 @@ class Resolver: self.netrc: T.Optional[netrc] = None self.provided_deps = {} # type: T.Dict[str, PackageDefinition] self.provided_programs = {} # type: T.Dict[str, PackageDefinition] + self.wrapdb: T.Dict[str, T.Any] = {} + self.wrapdb_provided_deps: T.Dict[str, str] = {} + self.wrapdb_provided_programs: T.Dict[str, str] = {} self.load_wraps() self.load_netrc() + self.load_wrapdb() def load_netrc(self) -> None: try: @@ -294,18 +300,48 @@ class Resolver: self.wraps[wrap.name] = wrap for wrap in self.wraps.values(): - for k in wrap.provided_deps.keys(): - if k in self.provided_deps: - prev_wrap = self.provided_deps[k] - m = f'Multiple wrap files provide {k!r} dependency: {wrap.basename} and {prev_wrap.basename}' - raise WrapException(m) - self.provided_deps[k] = wrap - for k in wrap.provided_programs: - if k in self.provided_programs: - prev_wrap = self.provided_programs[k] - m = f'Multiple wrap files provide {k!r} program: {wrap.basename} and {prev_wrap.basename}' - raise WrapException(m) - self.provided_programs[k] = wrap + self.add_wrap(wrap) + + def add_wrap(self, wrap: PackageDefinition) -> None: + for k in wrap.provided_deps.keys(): + if k in self.provided_deps: + prev_wrap = self.provided_deps[k] + m = f'Multiple wrap files provide {k!r} dependency: {wrap.basename} and {prev_wrap.basename}' + raise WrapException(m) + self.provided_deps[k] = wrap + for k in wrap.provided_programs: + if k in self.provided_programs: + prev_wrap = self.provided_programs[k] + m = f'Multiple wrap files provide {k!r} program: {wrap.basename} and {prev_wrap.basename}' + raise WrapException(m) + self.provided_programs[k] = wrap + + def load_wrapdb(self) -> None: + try: + with Path(self.subdir_root, 'wrapdb.json').open('r', encoding='utf-8') as f: + self.wrapdb = json.load(f) + except FileNotFoundError: + return + for name, info in self.wrapdb.items(): + self.wrapdb_provided_deps.update({i: name for i in info.get('dependency_names', [])}) + self.wrapdb_provided_programs.update({i: name for i in info.get('program_names', [])}) + + def get_from_wrapdb(self, subp_name: str) -> PackageDefinition: + info = self.wrapdb.get(subp_name) + if not info: + return None + self.check_can_download() + latest_version = info['versions'][0] + version, revision = latest_version.rsplit('-', 1) + url = urllib.request.urlopen(f'https://wrapdb.mesonbuild.com/v2/{subp_name}_{version}-{revision}/{subp_name}.wrap') + fname = Path(self.subdir_root, f'{subp_name}.wrap') + with fname.open('wb') as f: + f.write(url.read()) + mlog.log(f'Installed {subp_name} version {version} revision {revision}') + wrap = PackageDefinition(str(fname)) + self.wraps[wrap.name] = wrap + self.add_wrap(wrap) + return wrap def merge_wraps(self, other_resolver: 'Resolver') -> None: for k, v in other_resolver.wraps.items(): @@ -323,7 +359,8 @@ class Resolver: if wrap: dep_var = wrap.provided_deps.get(packagename) return wrap.name, dep_var - return None, None + wrap_name = self.wrapdb_provided_deps.get(packagename) + return wrap_name, None def get_varname(self, subp_name: str, depname: str) -> T.Optional[str]: wrap = self.wraps.get(subp_name) @@ -334,12 +371,17 @@ class Resolver: wrap = self.provided_programs.get(name) if wrap: return wrap.name + wrap_name = self.wrapdb_provided_programs.get(name) + if wrap_name: + return wrap_name return None def resolve(self, packagename: str, method: str) -> str: self.packagename = packagename self.directory = packagename self.wrap = self.wraps.get(packagename) + if not self.wrap: + self.wrap = self.get_from_wrapdb(packagename) if not self.wrap: m = f'Neither a subproject directory nor a {self.packagename}.wrap file was found.' raise WrapNotFoundException(m) -- cgit v1.2.1