Package portage :: Package package :: Package ebuild :: Package _config :: Module UseManager
[hide private]

Source Code for Module portage.package.ebuild._config.UseManager

  1  # Copyright 2010-2014 Gentoo Foundation 
  2  # Distributed under the terms of the GNU General Public License v2 
  3   
  4  __all__ = ( 
  5          'UseManager', 
  6  ) 
  7   
  8  from _emerge.Package import Package 
  9  from portage import os 
 10  from portage.dep import Atom, dep_getrepo, dep_getslot, ExtendedAtomDict, remove_slot, _get_useflag_re, _repo_separator 
 11  from portage.eapi import eapi_has_use_aliases, eapi_supports_stable_use_forcing_and_masking 
 12  from portage.exception import InvalidAtom 
 13  from portage.localization import _ 
 14  from portage.util import grabfile, grabdict, grabdict_package, read_corresponding_eapi_file, stack_lists, writemsg 
 15  from portage.versions import _pkg_str 
 16   
 17  from portage.package.ebuild._config.helper import ordered_by_atom_specificity 
 18   
19 -class UseManager(object):
20
21 - def __init__(self, repositories, profiles, abs_user_config, is_stable, 22 user_config=True):
23 # file variable 24 #-------------------------------- 25 # repositories 26 #-------------------------------- 27 # use.mask _repo_usemask_dict 28 # use.stable.mask _repo_usestablemask_dict 29 # use.force _repo_useforce_dict 30 # use.stable.force _repo_usestableforce_dict 31 # use.aliases _repo_usealiases_dict 32 # package.use.mask _repo_pusemask_dict 33 # package.use.stable.mask _repo_pusestablemask_dict 34 # package.use.force _repo_puseforce_dict 35 # package.use.stable.force _repo_pusestableforce_dict 36 # package.use.aliases _repo_pusealiases_dict 37 #-------------------------------- 38 # profiles 39 #-------------------------------- 40 # use.mask _usemask_list 41 # use.stable.mask _usestablemask_list 42 # use.force _useforce_list 43 # use.stable.force _usestableforce_list 44 # package.use.mask _pusemask_list 45 # package.use.stable.mask _pusestablemask_list 46 # package.use _pkgprofileuse 47 # package.use.force _puseforce_list 48 # package.use.stable.force _pusestableforce_list 49 #-------------------------------- 50 # user config 51 #-------------------------------- 52 # package.use _pusedict 53 54 # Dynamic variables tracked by the config class 55 #-------------------------------- 56 # profiles 57 #-------------------------------- 58 # usemask 59 # useforce 60 #-------------------------------- 61 # user config 62 #-------------------------------- 63 # puse 64 65 self._user_config = user_config 66 self._is_stable = is_stable 67 self._repo_usemask_dict = self._parse_repository_files_to_dict_of_tuples("use.mask", repositories) 68 self._repo_usestablemask_dict = \ 69 self._parse_repository_files_to_dict_of_tuples("use.stable.mask", 70 repositories, eapi_filter=eapi_supports_stable_use_forcing_and_masking) 71 self._repo_useforce_dict = self._parse_repository_files_to_dict_of_tuples("use.force", repositories) 72 self._repo_usestableforce_dict = \ 73 self._parse_repository_files_to_dict_of_tuples("use.stable.force", 74 repositories, eapi_filter=eapi_supports_stable_use_forcing_and_masking) 75 self._repo_pusemask_dict = self._parse_repository_files_to_dict_of_dicts("package.use.mask", repositories) 76 self._repo_pusestablemask_dict = \ 77 self._parse_repository_files_to_dict_of_dicts("package.use.stable.mask", 78 repositories, eapi_filter=eapi_supports_stable_use_forcing_and_masking) 79 self._repo_puseforce_dict = self._parse_repository_files_to_dict_of_dicts("package.use.force", repositories) 80 self._repo_pusestableforce_dict = \ 81 self._parse_repository_files_to_dict_of_dicts("package.use.stable.force", 82 repositories, eapi_filter=eapi_supports_stable_use_forcing_and_masking) 83 self._repo_puse_dict = self._parse_repository_files_to_dict_of_dicts("package.use", repositories) 84 85 self._usemask_list = self._parse_profile_files_to_tuple_of_tuples("use.mask", profiles) 86 self._usestablemask_list = \ 87 self._parse_profile_files_to_tuple_of_tuples("use.stable.mask", 88 profiles, eapi_filter=eapi_supports_stable_use_forcing_and_masking) 89 self._useforce_list = self._parse_profile_files_to_tuple_of_tuples("use.force", profiles) 90 self._usestableforce_list = \ 91 self._parse_profile_files_to_tuple_of_tuples("use.stable.force", 92 profiles, eapi_filter=eapi_supports_stable_use_forcing_and_masking) 93 self._pusemask_list = self._parse_profile_files_to_tuple_of_dicts("package.use.mask", profiles) 94 self._pusestablemask_list = \ 95 self._parse_profile_files_to_tuple_of_dicts("package.use.stable.mask", 96 profiles, eapi_filter=eapi_supports_stable_use_forcing_and_masking) 97 self._pkgprofileuse = self._parse_profile_files_to_tuple_of_dicts("package.use", profiles, juststrings=True) 98 self._puseforce_list = self._parse_profile_files_to_tuple_of_dicts("package.use.force", profiles) 99 self._pusestableforce_list = \ 100 self._parse_profile_files_to_tuple_of_dicts("package.use.stable.force", 101 profiles, eapi_filter=eapi_supports_stable_use_forcing_and_masking) 102 103 self._pusedict = self._parse_user_files_to_extatomdict("package.use", abs_user_config, user_config) 104 105 self._repo_usealiases_dict = self._parse_repository_usealiases(repositories) 106 self._repo_pusealiases_dict = self._parse_repository_packageusealiases(repositories) 107 108 self.repositories = repositories
109
110 - def _parse_file_to_tuple(self, file_name, recursive=True, eapi_filter=None):
111 ret = [] 112 lines = grabfile(file_name, recursive=recursive) 113 eapi = read_corresponding_eapi_file(file_name) 114 if eapi_filter is not None and not eapi_filter(eapi): 115 if lines: 116 writemsg(_("--- EAPI '%s' does not support '%s': '%s'\n") % 117 (eapi, os.path.basename(file_name), file_name), 118 noiselevel=-1) 119 return () 120 useflag_re = _get_useflag_re(eapi) 121 for prefixed_useflag in lines: 122 if prefixed_useflag[:1] == "-": 123 useflag = prefixed_useflag[1:] 124 else: 125 useflag = prefixed_useflag 126 if useflag_re.match(useflag) is None: 127 writemsg(_("--- Invalid USE flag in '%s': '%s'\n") % 128 (file_name, prefixed_useflag), noiselevel=-1) 129 else: 130 ret.append(prefixed_useflag) 131 return tuple(ret)
132
133 - def _parse_file_to_dict(self, file_name, juststrings=False, recursive=True, 134 eapi_filter=None, user_config=False):
135 ret = {} 136 location_dict = {} 137 eapi = read_corresponding_eapi_file(file_name, default=None) 138 if eapi is None and not user_config: 139 eapi = "0" 140 if eapi is None: 141 ret = ExtendedAtomDict(dict) 142 else: 143 ret = {} 144 file_dict = grabdict_package(file_name, recursive=recursive, 145 allow_wildcard=(eapi is None), allow_repo=(eapi is None), 146 verify_eapi=(eapi is not None)) 147 if eapi is not None and eapi_filter is not None and not eapi_filter(eapi): 148 if file_dict: 149 writemsg(_("--- EAPI '%s' does not support '%s': '%s'\n") % 150 (eapi, os.path.basename(file_name), file_name), 151 noiselevel=-1) 152 return ret 153 useflag_re = _get_useflag_re(eapi) 154 for k, v in file_dict.items(): 155 useflags = [] 156 for prefixed_useflag in v: 157 if prefixed_useflag[:1] == "-": 158 useflag = prefixed_useflag[1:] 159 else: 160 useflag = prefixed_useflag 161 if useflag_re.match(useflag) is None: 162 writemsg(_("--- Invalid USE flag for '%s' in '%s': '%s'\n") % 163 (k, file_name, prefixed_useflag), noiselevel=-1) 164 else: 165 useflags.append(prefixed_useflag) 166 location_dict.setdefault(k, []).extend(useflags) 167 for k, v in location_dict.items(): 168 if juststrings: 169 v = " ".join(v) 170 else: 171 v = tuple(v) 172 ret.setdefault(k.cp, {})[k] = v 173 return ret
174
175 - def _parse_user_files_to_extatomdict(self, file_name, location, user_config):
176 ret = ExtendedAtomDict(dict) 177 if user_config: 178 pusedict = grabdict_package( 179 os.path.join(location, file_name), recursive=1, allow_wildcard=True, allow_repo=True, verify_eapi=False) 180 for k, v in pusedict.items(): 181 ret.setdefault(k.cp, {})[k] = tuple(v) 182 183 return ret
184
185 - def _parse_repository_files_to_dict_of_tuples(self, file_name, repositories, eapi_filter=None):
186 ret = {} 187 for repo in repositories.repos_with_profiles(): 188 ret[repo.name] = self._parse_file_to_tuple(os.path.join(repo.location, "profiles", file_name), eapi_filter=eapi_filter) 189 return ret
190
191 - def _parse_repository_files_to_dict_of_dicts(self, file_name, repositories, eapi_filter=None):
192 ret = {} 193 for repo in repositories.repos_with_profiles(): 194 ret[repo.name] = self._parse_file_to_dict(os.path.join(repo.location, "profiles", file_name), eapi_filter=eapi_filter) 195 return ret
196
197 - def _parse_profile_files_to_tuple_of_tuples(self, file_name, locations, 198 eapi_filter=None):
199 return tuple(self._parse_file_to_tuple( 200 os.path.join(profile.location, file_name), 201 recursive=profile.portage1_directories, eapi_filter=eapi_filter) 202 for profile in locations)
203
204 - def _parse_profile_files_to_tuple_of_dicts(self, file_name, locations, 205 juststrings=False, eapi_filter=None):
206 return tuple(self._parse_file_to_dict( 207 os.path.join(profile.location, file_name), juststrings, 208 recursive=profile.portage1_directories, eapi_filter=eapi_filter, 209 user_config=profile.user_config) 210 for profile in locations)
211
212 - def _parse_repository_usealiases(self, repositories):
213 ret = {} 214 for repo in repositories.repos_with_profiles(): 215 file_name = os.path.join(repo.location, "profiles", "use.aliases") 216 eapi = read_corresponding_eapi_file(file_name) 217 useflag_re = _get_useflag_re(eapi) 218 raw_file_dict = grabdict(file_name, recursive=True) 219 file_dict = {} 220 for real_flag, aliases in raw_file_dict.items(): 221 if useflag_re.match(real_flag) is None: 222 writemsg(_("--- Invalid real USE flag in '%s': '%s'\n") % (file_name, real_flag), noiselevel=-1) 223 else: 224 for alias in aliases: 225 if useflag_re.match(alias) is None: 226 writemsg(_("--- Invalid USE flag alias for '%s' real USE flag in '%s': '%s'\n") % 227 (real_flag, file_name, alias), noiselevel=-1) 228 else: 229 if any(alias in v for k, v in file_dict.items() if k != real_flag): 230 writemsg(_("--- Duplicated USE flag alias in '%s': '%s'\n") % 231 (file_name, alias), noiselevel=-1) 232 else: 233 file_dict.setdefault(real_flag, []).append(alias) 234 ret[repo.name] = file_dict 235 return ret
236
237 - def _parse_repository_packageusealiases(self, repositories):
238 ret = {} 239 for repo in repositories.repos_with_profiles(): 240 file_name = os.path.join(repo.location, "profiles", "package.use.aliases") 241 eapi = read_corresponding_eapi_file(file_name) 242 useflag_re = _get_useflag_re(eapi) 243 lines = grabfile(file_name, recursive=True) 244 file_dict = {} 245 for line in lines: 246 elements = line.split() 247 atom = elements[0] 248 try: 249 atom = Atom(atom, eapi=eapi) 250 except InvalidAtom: 251 writemsg(_("--- Invalid atom in '%s': '%s'\n") % (file_name, atom)) 252 continue 253 if len(elements) == 1: 254 writemsg(_("--- Missing real USE flag for '%s' in '%s'\n") % (atom, file_name), noiselevel=-1) 255 continue 256 real_flag = elements[1] 257 if useflag_re.match(real_flag) is None: 258 writemsg(_("--- Invalid real USE flag for '%s' in '%s': '%s'\n") % (atom, file_name, real_flag), noiselevel=-1) 259 else: 260 for alias in elements[2:]: 261 if useflag_re.match(alias) is None: 262 writemsg(_("--- Invalid USE flag alias for '%s' real USE flag for '%s' in '%s': '%s'\n") % 263 (real_flag, atom, file_name, alias), noiselevel=-1) 264 else: 265 # Duplicated USE flag aliases in entries for different atoms 266 # matching the same package version are detected in getUseAliases(). 267 if any(alias in v for k, v in file_dict.get(atom.cp, {}).get(atom, {}).items() if k != real_flag): 268 writemsg(_("--- Duplicated USE flag alias for '%s' in '%s': '%s'\n") % 269 (atom, file_name, alias), noiselevel=-1) 270 else: 271 file_dict.setdefault(atom.cp, {}).setdefault(atom, {}).setdefault(real_flag, []).append(alias) 272 ret[repo.name] = file_dict 273 return ret
274
275 - def _isStable(self, pkg):
276 if self._user_config: 277 try: 278 return pkg.stable 279 except AttributeError: 280 # KEYWORDS is unavailable (prior to "depend" phase) 281 return False 282 283 try: 284 pkg._metadata 285 except AttributeError: 286 # KEYWORDS is unavailable (prior to "depend" phase) 287 return False 288 289 # Since repoman uses different config instances for 290 # different profiles, we have to be careful to do the 291 # stable check against the correct profile here. 292 return self._is_stable(pkg)
293
294 - def getUseMask(self, pkg=None, stable=None):
295 if pkg is None: 296 return frozenset(stack_lists( 297 self._usemask_list, incremental=True)) 298 299 slot = None 300 cp = getattr(pkg, "cp", None) 301 if cp is None: 302 slot = dep_getslot(pkg) 303 repo = dep_getrepo(pkg) 304 pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo) 305 cp = pkg.cp 306 307 if stable is None: 308 stable = self._isStable(pkg) 309 310 usemask = [] 311 312 if hasattr(pkg, "repo") and pkg.repo != Package.UNKNOWN_REPO: 313 repos = [] 314 try: 315 repos.extend(repo.name for repo in 316 self.repositories[pkg.repo].masters) 317 except KeyError: 318 pass 319 repos.append(pkg.repo) 320 for repo in repos: 321 usemask.append(self._repo_usemask_dict.get(repo, {})) 322 if stable: 323 usemask.append(self._repo_usestablemask_dict.get(repo, {})) 324 cpdict = self._repo_pusemask_dict.get(repo, {}).get(cp) 325 if cpdict: 326 pkg_usemask = ordered_by_atom_specificity(cpdict, pkg) 327 if pkg_usemask: 328 usemask.extend(pkg_usemask) 329 if stable: 330 cpdict = self._repo_pusestablemask_dict.get(repo, {}).get(cp) 331 if cpdict: 332 pkg_usemask = ordered_by_atom_specificity(cpdict, pkg) 333 if pkg_usemask: 334 usemask.extend(pkg_usemask) 335 336 for i, pusemask_dict in enumerate(self._pusemask_list): 337 if self._usemask_list[i]: 338 usemask.append(self._usemask_list[i]) 339 if stable and self._usestablemask_list[i]: 340 usemask.append(self._usestablemask_list[i]) 341 cpdict = pusemask_dict.get(cp) 342 if cpdict: 343 pkg_usemask = ordered_by_atom_specificity(cpdict, pkg) 344 if pkg_usemask: 345 usemask.extend(pkg_usemask) 346 if stable: 347 cpdict = self._pusestablemask_list[i].get(cp) 348 if cpdict: 349 pkg_usemask = ordered_by_atom_specificity(cpdict, pkg) 350 if pkg_usemask: 351 usemask.extend(pkg_usemask) 352 353 return frozenset(stack_lists(usemask, incremental=True))
354
355 - def getUseForce(self, pkg=None, stable=None):
356 if pkg is None: 357 return frozenset(stack_lists( 358 self._useforce_list, incremental=True)) 359 360 cp = getattr(pkg, "cp", None) 361 if cp is None: 362 slot = dep_getslot(pkg) 363 repo = dep_getrepo(pkg) 364 pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo) 365 cp = pkg.cp 366 367 if stable is None: 368 stable = self._isStable(pkg) 369 370 useforce = [] 371 372 if hasattr(pkg, "repo") and pkg.repo != Package.UNKNOWN_REPO: 373 repos = [] 374 try: 375 repos.extend(repo.name for repo in 376 self.repositories[pkg.repo].masters) 377 except KeyError: 378 pass 379 repos.append(pkg.repo) 380 for repo in repos: 381 useforce.append(self._repo_useforce_dict.get(repo, {})) 382 if stable: 383 useforce.append(self._repo_usestableforce_dict.get(repo, {})) 384 cpdict = self._repo_puseforce_dict.get(repo, {}).get(cp) 385 if cpdict: 386 pkg_useforce = ordered_by_atom_specificity(cpdict, pkg) 387 if pkg_useforce: 388 useforce.extend(pkg_useforce) 389 if stable: 390 cpdict = self._repo_pusestableforce_dict.get(repo, {}).get(cp) 391 if cpdict: 392 pkg_useforce = ordered_by_atom_specificity(cpdict, pkg) 393 if pkg_useforce: 394 useforce.extend(pkg_useforce) 395 396 for i, puseforce_dict in enumerate(self._puseforce_list): 397 if self._useforce_list[i]: 398 useforce.append(self._useforce_list[i]) 399 if stable and self._usestableforce_list[i]: 400 useforce.append(self._usestableforce_list[i]) 401 cpdict = puseforce_dict.get(cp) 402 if cpdict: 403 pkg_useforce = ordered_by_atom_specificity(cpdict, pkg) 404 if pkg_useforce: 405 useforce.extend(pkg_useforce) 406 if stable: 407 cpdict = self._pusestableforce_list[i].get(cp) 408 if cpdict: 409 pkg_useforce = ordered_by_atom_specificity(cpdict, pkg) 410 if pkg_useforce: 411 useforce.extend(pkg_useforce) 412 413 return frozenset(stack_lists(useforce, incremental=True))
414
415 - def getUseAliases(self, pkg):
416 if hasattr(pkg, "eapi") and not eapi_has_use_aliases(pkg.eapi): 417 return {} 418 419 cp = getattr(pkg, "cp", None) 420 if cp is None: 421 slot = dep_getslot(pkg) 422 repo = dep_getrepo(pkg) 423 pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo) 424 cp = pkg.cp 425 426 usealiases = {} 427 428 if hasattr(pkg, "repo") and pkg.repo != Package.UNKNOWN_REPO: 429 repos = [] 430 try: 431 repos.extend(repo.name for repo in 432 self.repositories[pkg.repo].masters) 433 except KeyError: 434 pass 435 repos.append(pkg.repo) 436 for repo in repos: 437 usealiases_dict = self._repo_usealiases_dict.get(repo, {}) 438 for real_flag, aliases in usealiases_dict.items(): 439 for alias in aliases: 440 if any(alias in v for k, v in usealiases.items() if k != real_flag): 441 writemsg(_("--- Duplicated USE flag alias for '%s%s%s': '%s'\n") % 442 (pkg.cpv, _repo_separator, pkg.repo, alias), noiselevel=-1) 443 else: 444 usealiases.setdefault(real_flag, []).append(alias) 445 cp_usealiases_dict = self._repo_pusealiases_dict.get(repo, {}).get(cp) 446 if cp_usealiases_dict: 447 usealiases_dict_list = ordered_by_atom_specificity(cp_usealiases_dict, pkg) 448 for usealiases_dict in usealiases_dict_list: 449 for real_flag, aliases in usealiases_dict.items(): 450 for alias in aliases: 451 if any(alias in v for k, v in usealiases.items() if k != real_flag): 452 writemsg(_("--- Duplicated USE flag alias for '%s%s%s': '%s'\n") % 453 (pkg.cpv, _repo_separator, pkg.repo, alias), noiselevel=-1) 454 else: 455 usealiases.setdefault(real_flag, []).append(alias) 456 457 return usealiases
458
459 - def getPUSE(self, pkg):
460 cp = getattr(pkg, "cp", None) 461 if cp is None: 462 slot = dep_getslot(pkg) 463 repo = dep_getrepo(pkg) 464 pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo) 465 cp = pkg.cp 466 ret = "" 467 cpdict = self._pusedict.get(cp) 468 if cpdict: 469 puse_matches = ordered_by_atom_specificity(cpdict, pkg) 470 if puse_matches: 471 puse_list = [] 472 for x in puse_matches: 473 puse_list.extend(x) 474 ret = " ".join(puse_list) 475 return ret
476
477 - def extract_global_USE_changes(self, old=""):
478 ret = old 479 cpdict = self._pusedict.get("*/*") 480 if cpdict is not None: 481 v = cpdict.pop("*/*", None) 482 if v is not None: 483 ret = " ".join(v) 484 if old: 485 ret = old + " " + ret 486 if not cpdict: 487 #No tokens left in atom_license_map, remove it. 488 del self._pusedict["*/*"] 489 return ret
490