# SPDX-License-Identifier: Apache-2.0 # Copyright 2018 The Meson development team # This file contains the detection logic for external dependencies that # are UI-related. from __future__ import annotations import json import os from . import ExtensionModule, ModuleInfo from .. import mlog from ..dependencies import Dependency from ..dependencies.dub import DubDependency from ..interpreterbase import typed_pos_args from ..mesonlib import Popen_safe, MesonException, listify class DlangModule(ExtensionModule): class_dubbin = None init_dub = False INFO = ModuleInfo('dlang', '0.48.0') def __init__(self, interpreter): super().__init__(interpreter) self.methods.update({ 'generate_dub_file': self.generate_dub_file, }) def _init_dub(self, state): if DlangModule.class_dubbin is None and DubDependency.class_dubbin is not None: self.dubbin = DubDependency.class_dubbin[0] DlangModule.class_dubbin = self.dubbin else: self.dubbin = DlangModule.class_dubbin if DlangModule.class_dubbin is None: self.dubbin = self.check_dub(state) DlangModule.class_dubbin = self.dubbin else: self.dubbin = DlangModule.class_dubbin if not self.dubbin: if not self.dubbin: raise MesonException('DUB not found.') @typed_pos_args('dlang.generate_dub_file', str, str) def generate_dub_file(self, state, args, kwargs): if not DlangModule.init_dub: self._init_dub(state) config = { 'name': args[0] } config_path = os.path.join(args[1], 'dub.json') if os.path.exists(config_path): with open(config_path, encoding='utf-8') as ofile: try: config = json.load(ofile) except ValueError: mlog.warning('Failed to load the data in dub.json') warn_publishing = ['description', 'license'] for arg in warn_publishing: if arg not in kwargs and \ arg not in config: mlog.warning('Without', mlog.bold(arg), 'the DUB package can\'t be published') for key, value in kwargs.items(): if key == 'dependencies': values = listify(value, flatten=False) config[key] = {} for dep in values: if isinstance(dep, Dependency): name = dep.get_name() ret, res = self._call_dubbin(['describe', name]) if ret == 0: version = dep.get_version() if version is None: config[key][name] = '' else: config[key][name] = version else: config[key] = value with open(config_path, 'w', encoding='utf-8') as ofile: ofile.write(json.dumps(config, indent=4, ensure_ascii=False)) def _call_dubbin(self, args, env=None): p, out = Popen_safe(self.dubbin.get_command() + args, env=env)[0:2] return p.returncode, out.strip() def check_dub(self, state): dubbin = state.find_program('dub', silent=True) if dubbin.found(): try: p, out = Popen_safe(dubbin.get_command() + ['--version'])[0:2] if p.returncode != 0: mlog.warning('Found dub {!r} but couldn\'t run it' ''.format(' '.join(dubbin.get_command()))) # Set to False instead of None to signify that we've already # searched for it and not found it dubbin = False except (FileNotFoundError, PermissionError): dubbin = False else: dubbin = False if dubbin: mlog.log('Found DUB:', mlog.bold(dubbin.get_path()), '(%s)' % out.strip()) else: mlog.log('Found DUB:', mlog.red('NO')) return dubbin def initialize(*args, **kwargs): return DlangModule(*args, **kwargs)