|  | # 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) |