1# Copyright 2018 The Meson development team 2 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6 7# http://www.apache.org/licenses/LICENSE-2.0 8 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15# This file contains the detection logic for external dependencies that 16# are UI-related. 17 18import json 19import os 20 21from . import ExtensionModule 22 23from .. import mlog 24 25from ..mesonlib import ( 26 Popen_safe, MesonException 27) 28 29from ..dependencies.base import ( 30 ExternalProgram, DubDependency 31) 32 33from ..interpreter import DependencyHolder 34 35class DlangModule(ExtensionModule): 36 class_dubbin = None 37 init_dub = False 38 39 def __init__(self, interpreter): 40 super().__init__(interpreter) 41 self.snippets.add('generate_dub_file') 42 43 def _init_dub(self): 44 if DlangModule.class_dubbin is None: 45 self.dubbin = DubDependency.class_dubbin 46 DlangModule.class_dubbin = self.dubbin 47 else: 48 self.dubbin = DlangModule.class_dubbin 49 50 if DlangModule.class_dubbin is None: 51 self.dubbin = self.check_dub() 52 DlangModule.class_dubbin = self.dubbin 53 else: 54 self.dubbin = DlangModule.class_dubbin 55 56 if not self.dubbin: 57 if not self.dubbin: 58 raise MesonException('DUB not found.') 59 60 def generate_dub_file(self, interpreter, state, args, kwargs): 61 if not DlangModule.init_dub: 62 self._init_dub() 63 64 if len(args) < 2: 65 raise MesonException('Missing arguments') 66 67 config = { 68 'name': args[0] 69 } 70 71 config_path = os.path.join(args[1], 'dub.json') 72 if os.path.exists(config_path): 73 with open(config_path, 'r', encoding='utf8') as ofile: 74 try: 75 config = json.load(ofile) 76 except ValueError: 77 mlog.warning('Failed to load the data in dub.json') 78 79 warn_publishing = ['description', 'license'] 80 for arg in warn_publishing: 81 if arg not in kwargs and \ 82 arg not in config: 83 mlog.warning('Without', mlog.bold(arg), 'the DUB package can\'t be published') 84 85 for key, value in kwargs.items(): 86 if key == 'dependencies': 87 config[key] = {} 88 if isinstance(value, list): 89 for dep in value: 90 if isinstance(dep, DependencyHolder): 91 name = dep.method_call('name', [], []) 92 ret, res = self._call_dubbin(['describe', name]) 93 if ret == 0: 94 version = dep.method_call('version', [], []) 95 if version is None: 96 config[key][name] = '' 97 else: 98 config[key][name] = version 99 elif isinstance(value, DependencyHolder): 100 name = value.method_call('name', [], []) 101 ret, res = self._call_dubbin(['describe', name]) 102 if ret == 0: 103 version = value.method_call('version', [], []) 104 if version is None: 105 config[key][name] = '' 106 else: 107 config[key][name] = version 108 else: 109 config[key] = value 110 111 with open(config_path, 'w', encoding='utf8') as ofile: 112 ofile.write(json.dumps(config, indent=4, ensure_ascii=False)) 113 114 def _call_dubbin(self, args, env=None): 115 p, out = Popen_safe(self.dubbin.get_command() + args, env=env)[0:2] 116 return p.returncode, out.strip() 117 118 def check_dub(self): 119 dubbin = ExternalProgram('dub', silent=True) 120 if dubbin.found(): 121 try: 122 p, out = Popen_safe(dubbin.get_command() + ['--version'])[0:2] 123 if p.returncode != 0: 124 mlog.warning('Found dub {!r} but couldn\'t run it' 125 ''.format(' '.join(dubbin.get_command()))) 126 # Set to False instead of None to signify that we've already 127 # searched for it and not found it 128 dubbin = False 129 except (FileNotFoundError, PermissionError): 130 dubbin = False 131 else: 132 dubbin = False 133 if dubbin: 134 mlog.log('Found DUB:', mlog.bold(dubbin.get_path()), 135 '(%s)' % out.strip()) 136 else: 137 mlog.log('Found DUB:', mlog.red('NO')) 138 return dubbin 139 140def initialize(*args, **kwargs): 141 return DlangModule(*args, **kwargs) 142