Package entropy :: Package spm :: Package plugins :: Package interfaces :: Package portage_plugin

Source Code for Package entropy.spm.plugins.interfaces.portage_plugin

   1  # -*- coding: utf-8 -*- 
   2  """ 
   3   
   4      @author: Fabio Erculiani <lxnay@sabayonlinux.org> 
   5      @contact: lxnay@sabayonlinux.org 
   6      @copyright: Fabio Erculiani 
   7      @license: GPL-2 
   8   
   9      B{Entropy Source Package Manager "Portage" Plugin}. 
  10   
  11  """ 
  12  import os 
  13  import bz2 
  14  import sys 
  15  import shutil 
  16  import tempfile 
  17  import subprocess 
  18  from entropy.const import etpConst, etpUi, const_get_stringtype, \ 
  19      const_convert_to_unicode, const_convert_to_rawstring 
  20  from entropy.exceptions import FileNotFound, SPMError, InvalidDependString, \ 
  21      InvalidData, InvalidAtom 
  22  from entropy.output import darkred, darkgreen, brown, darkblue, purple, red, \ 
  23      bold, blue 
  24  from entropy.i18n import _ 
  25  from entropy.core.settings.base import SystemSettings 
  26  from entropy.misc import LogFile 
  27  from entropy.spm.plugins.skel import SpmPlugin 
  28  import entropy.tools 
  29  from entropy.spm.plugins.interfaces.portage_plugin import xpak 
  30  from entropy.spm.plugins.interfaces.portage_plugin import xpaktools 
31 32 -class PortagePackageGroups(dict):
33 """ 34 Entropy Package categories group representation 35 """
36 - def __init__(self):
37 dict.__init__(self) 38 39 data = { 40 'office': { 41 'name': _("Office"), 42 'description': _("Applications used in office environments"), 43 'categories': ['app-office', 'app-pda', 'app-mobilephone', 44 'app-cdr', 'app-antivirus', 'app-laptop', 'mail-', 45 ], 46 }, 47 'development': { 48 'name': _("Development"), 49 'description': _("Applications or system libraries"), 50 'categories': ['dev-', 'sys-devel'], 51 }, 52 'system': { 53 'name': _("System"), 54 'description': _("System applications or libraries"), 55 'categories': ['sys-'], 56 }, 57 'games': { 58 'name': _("Games"), 59 'description': _("Games, enjoy your spare time"), 60 'categories': ['games-'], 61 }, 62 'gnome': { 63 'name': _("GNOME Desktop"), 64 'description': \ 65 _("Applications and libraries for the GNOME Desktop"), 66 'categories': ['gnome-'], 67 }, 68 'kde': { 69 'name': _("KDE Desktop"), 70 'description': \ 71 _("Applications and libraries for the KDE Desktop"), 72 'categories': ['kde-'], 73 }, 74 'xfce': { 75 'name': _("XFCE Desktop"), 76 'description': \ 77 _("Applications and libraries for the XFCE Desktop"), 78 'categories': ['xfce-'], 79 }, 80 'lxde': { 81 'name': _("LXDE Desktop"), 82 'description': \ 83 _("Applications and libraries for the LXDE Desktop"), 84 'categories': ['lxde-'], 85 }, 86 'multimedia': { 87 'name': _("Multimedia"), 88 'description': \ 89 _("Applications and libraries for Multimedia"), 90 'categories': ['media-'], 91 }, 92 'networking': { 93 'name': _("Networking"), 94 'description': \ 95 _("Applications and libraries for Networking"), 96 'categories': ['net-', 'www-'], 97 }, 98 'science': { 99 'name': _("Science"), 100 'description': \ 101 _("Scientific applications and libraries"), 102 'categories': ['sci-'], 103 }, 104 'x11': { 105 'name': _("X11"), 106 'description': \ 107 _("Applications and libraries for X11"), 108 'categories': ['x11-'], 109 }, 110 } 111 self.update(data)
112
113 114 -class PortageMetaphor:
115 116 """ 117 This class (will) contains Portage packages metaphor related functions. 118 It is intended for internal (plugin) use only. So, go away from here ;) 119 """ 120 121 # used to properly sort /usr/portage/profiles/updates files 122 @staticmethod
123 - def sort_update_files(update_list):
124 """ 125 docstring_title 126 127 @param update_list: 128 @type update_list: 129 @return: 130 @rtype: 131 """ 132 sort_dict = {} 133 # sort per year 134 for item in update_list: 135 # get year 136 year = item.split("-")[1] 137 if year in sort_dict: 138 sort_dict[year].append(item) 139 else: 140 sort_dict[year] = [] 141 sort_dict[year].append(item) 142 new_list = [] 143 keys = sorted(sort_dict.keys()) 144 for key in keys: 145 sort_dict[key].sort() 146 new_list += sort_dict[key] 147 del sort_dict 148 return new_list
149
150 151 -class PortagePlugin(SpmPlugin):
152 153 builtin_pkg_sets = [ 154 "system", "world", "installed", "module-rebuild", 155 "security", "preserved-rebuild", "live-rebuild", 156 "downgrade", "unavailable" 157 ] 158 159 xpak_entries = { 160 'description': "DESCRIPTION", 161 'homepage': "HOMEPAGE", 162 'chost': "CHOST", 163 'category': "CATEGORY", 164 'cflags': "CFLAGS", 165 'cxxflags': "CXXFLAGS", 166 'license': "LICENSE", 167 'src_uri': "SRC_URI", 168 'use': "USE", 169 'iuse': "IUSE", 170 'slot': "SLOT", 171 'provide': "PROVIDE", 172 'depend': "DEPEND", 173 'rdepend': "RDEPEND", 174 'pdepend': "PDEPEND", 175 'needed': "NEEDED", 176 'inherited': "INHERITED", 177 'keywords': "KEYWORDS", 178 'contents': "CONTENTS", 179 'counter': "COUNTER", 180 'defined_phases': "DEFINED_PHASES", 181 'repository': "repository", 182 'pf': "PF", 183 } 184 185 _ebuild_entries = { 186 'ebuild_pkg_tag_var': "ENTROPY_PROJECT_TAG", 187 } 188 189 _cmd_map = { 190 'env_update_cmd': "/usr/sbin/env-update", 191 'ask_cmd': "--ask", 192 'info_cmd': "--info", 193 'remove_cmd': "-C", 194 'nodeps_cmd': "--nodeps", 195 'fetchonly_cmd': "--fetchonly", 196 'buildonly_cmd': "--buildonly", 197 'oneshot_cmd': "--oneshot", 198 'pretend_cmd': "--pretend", 199 'verbose_cmd': "--verbose", 200 'nocolor_cmd': "--color=n", 201 'source_profile_cmd': ["source", "/etc/profile"], 202 'exec_cmd': "/usr/bin/emerge", 203 } 204 205 _package_phases_map = { 206 'setup': 'setup', 207 'preinstall': 'preinst', 208 'postinstall': 'postinst', 209 'preremove': 'prerm', 210 'postremove': 'postrm', 211 'configure': 'config', 212 } 213 214 _config_files_map = { 215 'global_make_conf': "/etc/make.conf", 216 'global_package_keywords': "/etc/portage/package.keywords", 217 'global_package_use': "/etc/portage/package.use", 218 'global_package_mask': "/etc/portage/package.mask", 219 'global_package_unmask': "/etc/portage/package.unmask", 220 'global_make_profile': "/etc/make.profile", 221 } 222 223 PLUGIN_API_VERSION = 3 224 225 SUPPORTED_MATCH_TYPES = [ 226 "bestmatch-visible", "cp-list", "list-visible", "match-all", 227 "match-visible", "minimum-all", "minimum-visible" 228 ] 229 230 CACHE = { 231 'vartree': {}, 232 'binarytree': {}, 233 'config': {}, 234 'portagetree': {}, 235 } 236 237 IS_DEFAULT = True 238 PLUGIN_NAME = 'portage' 239 ENV_FILE_COMP = "environment.bz2" 240 EBUILD_EXT = ".ebuild" 241 KERNEL_CATEGORY = "sys-kernel" 242 243 sys.path.append("/usr/lib/gentoolkit/pym") 244
245 - class paren_normalize(list):
246 """Take a dependency structure as returned by paren_reduce or use_reduce 247 and generate an equivalent structure that has no redundant lists."""
248 - def __init__(self, src):
249 list.__init__(self) 250 self._zap_parens(src, self)
251
252 - def _zap_parens(self, src, dest, disjunction=False):
253 if not src: 254 return dest 255 i = iter(src) 256 for x in i: 257 if isinstance(x, const_get_stringtype()): 258 if x == '||': 259 x = self._zap_parens(next(i), [], disjunction=True) 260 if len(x) == 1: 261 dest.append(x[0]) 262 else: 263 dest.append("||") 264 dest.append(x) 265 elif x.endswith("?"): 266 dest.append(x) 267 dest.append(self._zap_parens(next(i), [])) 268 else: 269 dest.append(x) 270 else: 271 if disjunction: 272 x = self._zap_parens(x, []) 273 if len(x) == 1: 274 dest.append(x[0]) 275 else: 276 dest.append(x) 277 else: 278 self._zap_parens(x, dest) 279 return dest
280
281 - def init_singleton(self, OutputInterface):
282 283 mytxt = _("OutputInterface does not have an updateProgress method") 284 if not hasattr(OutputInterface, 'updateProgress'): 285 raise AttributeError(mytxt) 286 elif not hasattr(OutputInterface.updateProgress, '__call__'): 287 raise AttributeError(mytxt) 288 289 # interface only needed OutputInterface functions 290 self.updateProgress = OutputInterface.updateProgress 291 self.askQuestion = OutputInterface.askQuestion 292 293 # importing portage stuff 294 import portage 295 self.portage = portage 296 self.EAPI = 1 297 try: 298 import portage.const as portage_const 299 except ImportError: 300 import portage_const 301 if hasattr(portage_const, "EAPI"): 302 self.EAPI = portage_const.EAPI 303 self.portage_const = portage_const 304 305 from portage.versions import best 306 self._portage_best = best 307 308 try: 309 import portage.util as portage_util 310 except ImportError: 311 import portage_util 312 self.portage_util = portage_util 313 314 try: 315 import portage.sets as portage_sets 316 self.portage_sets = portage_sets 317 except ImportError: 318 self.portage_sets = None 319 320 try: 321 import glsa 322 self.glsa = glsa 323 except ImportError: 324 self.glsa = None 325 326 self.__entropy_repository_treeupdate_digests = {}
327 328 @staticmethod
329 - def get_package_groups():
330 """ 331 Return package groups available metadata (Spm categories are grouped 332 into macro categories called "groups"). 333 """ 334 return PortagePackageGroups()
335
336 - def package_metadata_keys(self):
337 """ 338 Reimplemented from SpmPlugin class. 339 """ 340 # return what's inside vartree because it's more complete 341 dbapi = self._get_portage_vartree().dbapi 342 if hasattr(dbapi, '_aux_cache_keys'): 343 return list(dbapi._aux_cache_keys) 344 345 sys.stderr.write("PortagePlugin: missing vardb._aux_cache_keys !\n") 346 return ["CHOST", "COUNTER", "DEPEND", "DESCRIPTION", 347 "EAPI", "HOMEPAGE", "IUSE", "KEYWORDS", 348 "LICENSE", "PDEPEND", "PROPERTIES", "PROVIDE", "RDEPEND", 349 "repository", "RESTRICT", "SLOT", "USE" 350 ]
351
352 - def get_cache_directory(self, root = None):
353 """ 354 Reimplemented from SpmPlugin class. 355 """ 356 if root is None: 357 root = etpConst['systemroot'] + os.path.sep 358 cache_path = self.portage_const.CACHE_PATH.lstrip(os.path.sep) 359 return os.path.join(root, cache_path)
360
361 - def get_package_metadata(self, package, key):
362 """ 363 Reimplemented from SpmPlugin class. 364 """ 365 return self.portage.portdb.aux_get(package, [key])[0]
366
367 - def get_package_changelog(self, package):
368 """ 369 Reimplemented from SpmPlugin class. 370 """ 371 ebuild_path = self.get_package_build_script_path(package) 372 if isinstance(ebuild_path, const_get_stringtype()): 373 374 clog_path = os.path.join(os.path.dirname(ebuild_path), "ChangeLog") 375 if os.access(clog_path, os.R_OK) and os.path.isfile(clog_path): 376 with open(clog_path, "rb") as clog_f: 377 return clog_f.read()
378
379 - def get_package_build_script_path(self, package):
380 """ 381 Reimplemented from SpmPlugin class. 382 """ 383 return self.portage.portdb.findname(package)
384
385 - def get_installed_package_build_script_path(self, package, root = None):
386 """ 387 Reimplemented from SpmPlugin class. 388 """ 389 return os.path.join(self._get_vdb_path(root = root), package, 390 package.split("/")[-1] + PortagePlugin.EBUILD_EXT)
391
392 - def get_installed_package_metadata(self, package, key, root = None):
393 """ 394 Reimplemented from SpmPlugin class. 395 """ 396 if root is None: 397 root = etpConst['systemroot'] + os.path.sep 398 vartree = self._get_portage_vartree(root = root) 399 return vartree.dbapi.aux_get(package, [key])[0]
400
401 - def get_system_packages(self):
402 """ 403 Reimplemented from SpmPlugin class. 404 """ 405 system = [] 406 for package in self.portage.settings.packages: 407 pkgs = self.match_installed_package(package, match_all = True) 408 system.extend(pkgs) 409 return system
410
411 - def get_package_categories(self):
412 """ 413 Reimplemented from SpmPlugin class. 414 """ 415 return self._get_portage_config(os.path.sep, os.path.sep).categories
416
417 - def get_package_category_description_metadata(self, category):
418 """ 419 Reimplemented from SpmPlugin class. 420 """ 421 from xml.dom import minidom 422 data = {} 423 portdir = self.portage.settings['PORTDIR'] 424 myfile = os.path.join(portdir, category, "metadata.xml") 425 if os.access(myfile, os.R_OK) and os.path.isfile(myfile): 426 doc = minidom.parse(myfile) 427 longdescs = doc.getElementsByTagName("longdescription") 428 for longdesc in longdescs: 429 data[longdesc.getAttribute("lang").strip()] = \ 430 ' '.join([x.strip() for x in \ 431 longdesc.firstChild.data.strip().split("\n")]) 432 return data
433
434 - def get_security_packages(self, security_property):
435 """ 436 Reimplemented from SpmPlugin class. 437 """ 438 if not self.glsa: 439 return [] 440 if security_property not in ['new', 'all', 'affected']: 441 return [] 442 443 glsaconfig = self.glsa.checkconfig( 444 self.portage.config(clone=self.portage.settings)) 445 completelist = self.glsa.get_glsa_list( 446 glsaconfig["GLSA_DIR"], glsaconfig) 447 448 glsalist = [] 449 if security_property == "new": 450 451 checklist = [] 452 if os.access(glsaconfig["CHECKFILE"], os.R_OK) and \ 453 os.path.isfile(glsaconfig["CHECKFILE"]): 454 with open(glsaconfig["CHECKFILE"], "rb") as check_f: 455 checklist.extend([x.strip() for x in check_f.readlines()]) 456 glsalist = [x for x in completelist if x not in checklist] 457 458 elif security_property == "all": 459 glsalist = completelist 460 461 elif security_property == "affected": 462 463 # maybe this should be todolist instead 464 for glsa_item in completelist: 465 try: 466 myglsa = self.glsa.Glsa(glsa_item, glsaconfig) 467 except (self.glsa.GlsaTypeException, 468 self.glsa.GlsaFormatException,): 469 continue 470 471 if not myglsa.isVulnerable(): 472 continue 473 474 glsalist.append(glsa_item) 475 476 return glsalist
477
478 - def get_security_advisory_metadata(self, advisory_id):
479 """ 480 Reimplemented from SpmPlugin class. 481 """ 482 if not self.glsa: 483 return {} 484 485 glsaconfig = self.glsa.checkconfig( 486 self.portage.config(clone=self.portage.settings)) 487 try: 488 myglsa = self.glsa.Glsa(advisory_id, glsaconfig) 489 except (self.glsa.GlsaTypeException, self.glsa.GlsaFormatException): 490 return {} 491 492 mydict = { 493 'glsa_id': advisory_id, 494 'number': myglsa.nr, 495 'access': myglsa.access, 496 'title': myglsa.title, 497 'synopsis': myglsa.synopsis, 498 'announced': myglsa.announced, 499 'revised': myglsa.revised, 500 'bugs': myglsa.bugs, 501 'description': myglsa.description, 502 'resolution': myglsa.resolution, 503 'impact': myglsa.impact_text, 504 'impacttype': myglsa.impact_type, 505 'affected': myglsa.affected, 506 'background': myglsa.background, 507 'glsatype': myglsa.glsatype, 508 'packages': myglsa.packages, 509 'services': myglsa.services, 510 'product': myglsa.product, 511 'references': myglsa.references, 512 'workaround': myglsa.workaround, 513 } 514 515 status = "[U]" 516 if myglsa.isApplied(): 517 status = "[A]" 518 elif myglsa.isVulnerable(): 519 status = "[N]" 520 mydict['status'] = status 521 522 return mydict
523
524 - def get_setting(self, key):
525 """ 526 Reimplemented from SpmPlugin class. 527 """ 528 return self.portage.settings[key]
529
530 - def get_user_installed_packages_file(self, root = None):
531 """ 532 Reimplemented from SpmPlugin class. 533 """ 534 world_file = self.portage_const.WORLD_FILE 535 if root is None: 536 root = etpConst['systemroot'] + os.path.sep 537 return os.path.join(root, world_file)
538
539 - def get_merge_protected_paths(self):
540 """ 541 Reimplemented from SpmPlugin class. 542 """ 543 config_protect = self.portage.settings['CONFIG_PROTECT'] 544 return [os.path.expandvars(x) for x in config_protect.split()]
545
547 """ 548 Reimplemented from SpmPlugin class. 549 """ 550 config_protect = self.portage.settings['CONFIG_PROTECT_MASK'] 551 return [os.path.expandvars(x) for x in config_protect.split()]
552
553 - def get_download_mirrors(self, mirror_name):
554 """ 555 Reimplemented from SpmPlugin class. 556 """ 557 mirrors = [] 558 if mirror_name in self.portage.thirdpartymirrors: 559 mirrors.extend(self.portage.thirdpartymirrors[mirror_name]) 560 return mirrors
561
563 """ 564 Reimplemented from SpmPlugin class. 565 """ 566 root = etpConst['systemroot'] + os.path.sep 567 mydb = {} 568 mydb[root] = {} 569 mydb[root]['vartree'] = self._get_portage_vartree(root) 570 mydb[root]['porttree'] = self._get_portage_portagetree(root) 571 mydb[root]['bintree'] = self._get_portage_binarytree(root) 572 mydb[root]['virtuals'] = self.portage.settings.getvirtuals(root) 573 574 if etpUi['mute']: 575 pid = os.fork() 576 if pid > 0: 577 os.waitpid(pid, 0) 578 else: 579 log = LogFile( 580 level = etpConst['spmloglevel'], 581 filename = etpConst['spmlogfile'], 582 header = "[spm]" 583 ) 584 old_stdout = sys.stdout 585 old_stderr = sys.stderr 586 sys.stdout = log 587 sys.stderr = log 588 589 self.portage._global_updates(mydb, {}) 590 591 sys.stdout = old_stdout 592 sys.stderr = old_stderr 593 log.flush() 594 log.close() 595 os._exit(0) 596 else: 597 self.portage._global_updates(mydb, {}) # always force
598
599 - def match_package(self, package, match_type = None):
600 """ 601 Reimplemented from SpmPlugin class. 602 """ 603 if match_type is None: 604 match_type = "bestmatch-visible" 605 elif match_type not in PortagePlugin.SUPPORTED_MATCH_TYPES: 606 raise KeyError 607 try: 608 return self.portage.portdb.xmatch(match_type, package) 609 except self.portage.exception.PortageException: 610 raise InvalidAtom(package)
611
612 - def match_installed_package(self, package, match_all = False, root = None):
613 """ 614 Reimplemented from SpmPlugin class. 615 """ 616 if root is None: 617 root = etpConst['systemroot'] + os.path.sep 618 619 vartree = self._get_portage_vartree(root = root) 620 try: 621 matches = vartree.dep_match(package) or [] 622 except self.portage.exception.InvalidAtom as err: 623 raise InvalidAtom(str(err)) 624 625 if match_all: 626 return matches 627 elif matches: 628 return matches[-1] 629 return ''
630
631 - def generate_package(self, package, file_save_path):
632 """ 633 Reimplemented from SpmPlugin class. 634 """ 635 pkgcat, pkgname = package.split("/", 1) 636 if not os.path.isdir(file_save_path): 637 os.makedirs(file_save_path) 638 file_save_path += "/" + pkgname + etpConst['packagesext'] 639 dbdir = os.path.join(self._get_vdb_path(), pkgcat, pkgname) 640 641 import tarfile 642 import stat 643 trees = self.portage.db["/"] 644 vartree = trees["vartree"] 645 dblnk = self.portage.dblink(pkgcat, pkgname, "/", vartree.settings, 646 treetype="vartree", vartree=vartree) 647 if etpConst['uid'] == 0: 648 dblnk.lockdb() 649 tar = tarfile.open(file_save_path, "w:bz2") 650 651 contents = dblnk.getcontents() 652 paths = sorted(contents.keys()) 653 654 for path in paths: 655 try: 656 exist = os.lstat(path) 657 except OSError: 658 continue # skip file 659 ftype = contents[path][0] 660 lpath = path 661 arcname = path[1:] 662 if 'dir' == ftype and \ 663 not stat.S_ISDIR(exist.st_mode) and \ 664 os.path.isdir(lpath): 665 lpath = os.path.realpath(lpath) 666 tarinfo = tar.gettarinfo(lpath, arcname) 667 668 if stat.S_ISREG(exist.st_mode): 669 tarinfo.mode = stat.S_IMODE(exist.st_mode) 670 tarinfo.type = tarfile.REGTYPE 671 f = open(path, "rb") 672 try: 673 tar.addfile(tarinfo, f) 674 finally: 675 f.close() 676 else: 677 tar.addfile(tarinfo) 678 679 tar.close() 680 681 # appending xpak informations 682 tbz2 = xpak.tbz2(file_save_path) 683 tbz2.recompose(dbdir) 684 685 dblnk.unlockdb() 686 687 if os.path.isfile(file_save_path): 688 return file_save_path 689 690 raise SPMError("SPMError: Spm:generate_package %s: %s %s" % ( 691 _("error"), 692 file_save_path, 693 _("not found"), 694 ) 695 )
696
697 - def _add_kernel_dependency_to_pkg(self, pkg_data):
698 699 kmod_pfx = "/lib/modules" 700 content = [x for x in pkg_data['content'] if x.startswith(kmod_pfx)] 701 content = [x for x in content if x != kmod_pfx] 702 if not content: 703 return 704 content.sort() 705 706 for item in content: 707 708 k_base = os.path.basename(item) 709 if k_base.startswith("."): 710 continue # hidden file 711 # hope that is fine! 712 713 owners = self.search_paths_owners([item]) 714 if not owners: 715 continue 716 717 # MUST match SLOT (for triggers here, to be able to handle 718 # multiple packages correctly and set back slot). 719 pkg_data['versiontag'] = k_base 720 721 owner_data = None 722 for k_atom, k_slot in owners: 723 k_cat, k_name, k_ver, k_rev = entropy.tools.catpkgsplit(k_atom) 724 if k_cat == PortagePlugin.KERNEL_CATEGORY: 725 owner_data = (k_cat, k_name, k_ver, k_rev,) 726 break 727 728 # no kernel found 729 if owner_data is None: 730 continue 731 732 k_cat, k_name, k_ver, k_rev = owner_data 733 if k_rev != "r0": 734 k_ver += "-%s" % (k_rev,) 735 736 # overwrite slot, yeah 737 pkg_data['slot'] = k_base 738 kern_dep_key = "=%s~-1" % (k_atom,) 739 740 return kern_dep_key
741
742 - def _get_default_virtual_pkg(self, virtual_key):
743 defaults = self.portage.settings.getvirtuals()[virtual_key] 744 if defaults: 745 return defaults[0]
746
747 - def extract_package_metadata(self, package_file):
748 """ 749 Reimplemented from SpmPlugin class. 750 """ 751 data = {} 752 system_settings = SystemSettings() 753 754 # fill package name and version 755 data['digest'] = entropy.tools.md5sum(package_file) 756 data['signatures'] = { 757 'sha1': entropy.tools.sha1(package_file), 758 'sha256': entropy.tools.sha256(package_file), 759 'sha512': entropy.tools.sha512(package_file), 760 } 761 data['datecreation'] = str(entropy.tools.get_file_unix_mtime( 762 package_file)) 763 data['size'] = str(entropy.tools.get_file_size(package_file)) 764 765 tmp_dir = tempfile.mkdtemp() 766 meta_dir = os.path.join(tmp_dir, "portage") 767 pkg_dir = os.path.join(tmp_dir, "pkg") 768 os.mkdir(meta_dir) 769 os.mkdir(pkg_dir) 770 771 # extract stuff 772 xpaktools.extract_xpak(package_file, meta_dir) 773 entropy.tools.uncompress_tar_bz2(package_file, 774 extractPath = pkg_dir, catchEmpty = True) 775 776 # package injection status always false by default 777 # developer can change metadatum after this function 778 data['injected'] = False 779 data['branch'] = system_settings['repositories']['branch'] 780 781 portage_entries = self._extract_pkg_metadata_generate_extraction_dict() 782 for item in portage_entries: 783 784 value = '' 785 try: 786 787 item_path = os.path.join(meta_dir, portage_entries[item]['path']) 788 with open(item_path, "rb") as item_f: 789 value = item_f.readline().strip() 790 value = const_convert_to_unicode(value) 791 792 except IOError: 793 if portage_entries[item]['critical']: 794 raise 795 data[item] = value 796 797 if not data['spm_repository']: # make sure it's set to None 798 data['spm_repository'] = None 799 800 # workout pf 801 pf_atom = os.path.join(data['category'], data['pf']) 802 pkgcat, pkgname, pkgver, pkgrev = entropy.tools.catpkgsplit( 803 pf_atom) 804 if pkgrev != "r0": 805 pkgver += "-%s" % (pkgrev,) 806 data['name'] = pkgname 807 data['version'] = pkgver 808 # bye bye pf 809 del data['pf'] 810 811 # setup spm_phases properly 812 spm_defined_phases_path = os.path.join(meta_dir, 813 portage_entries['spm_phases']['path']) 814 if not os.path.isfile(spm_defined_phases_path): 815 # force to None, because metadatum can be '', which is valid 816 data['spm_phases'] = None 817 818 data['eclasses'] = set(data['eclasses'].split()) 819 try: 820 data['counter'] = int(data['counter']) 821 except ValueError: 822 # -2 values will be insterted as incremental 823 # negative values into the database 824 data['counter'] = -2 825 826 data['keywords'] = [x.strip() for x in data['keywords'].split() \ 827 if x.strip()] 828 if not data['keywords']: 829 # support for packages with no keywords 830 data['keywords'].insert(0, "") 831 832 data['keywords'] = set(data['keywords']) 833 needed_file = os.path.join(meta_dir, 834 PortagePlugin.xpak_entries['needed']) 835 836 data['needed'] = self._extract_pkg_metadata_needed(needed_file) 837 838 content_file = os.path.join(meta_dir, 839 PortagePlugin.xpak_entries['contents']) 840 data['content'] = self._extract_pkg_metadata_content(content_file, 841 package_file) 842 data['disksize'] = entropy.tools.sum_file_sizes(data['content']) 843 844 data['provided_libs'] = self._extract_pkg_metadata_provided_libs( 845 pkg_dir, data['content']) 846 847 # [][][] Kernel dependent packages hook [][][] 848 data['versiontag'] = '' 849 kern_dep_key = None 850 851 if data['category'] != PortagePlugin.KERNEL_CATEGORY: 852 kern_dep_key = self._add_kernel_dependency_to_pkg(data) 853 854 file_ext = PortagePlugin.EBUILD_EXT 855 ebuilds_in_path = [x for x in os.listdir(meta_dir) if \ 856 x.endswith(file_ext)] 857 858 if not data['versiontag'] and ebuilds_in_path: 859 # has the user specified a custom package tag inside the ebuild 860 ebuild_path = os.path.join(meta_dir, ebuilds_in_path[0]) 861 data['versiontag'] = self._extract_pkg_metadata_ebuild_entropy_tag( 862 ebuild_path) 863 864 data['download'] = etpConst['packagesrelativepath'] + data['branch'] \ 865 + "/" 866 data['download'] += entropy.tools.create_package_filename( 867 data['category'], data['name'], data['version'], data['versiontag']) 868 869 data['trigger'] = const_convert_to_rawstring("") 870 trigger_file = os.path.join(etpConst['triggersdir'], data['category'], 871 data['name'], etpConst['triggername']) 872 if os.access(trigger_file, os.R_OK) and os.path.isfile(trigger_file): 873 with open(trigger_file, "rb") as trig_f: 874 data['trigger'] = trig_f.read() 875 876 # Get Spm ChangeLog 877 pkgatom = "%s/%s-%s" % (data['category'], data['name'], 878 data['version'],) 879 try: 880 data['changelog'] = const_convert_to_unicode( 881 self.get_package_changelog(pkgatom)) 882 except (UnicodeEncodeError, UnicodeDecodeError,) as e: 883 sys.stderr.write("%s: %s, %s\n" % ( 884 "changelog string conversion error", e, 885 package_file,) 886 ) 887 data['changelog'] = None 888 except: 889 data['changelog'] = None 890 891 portage_metadata = self._calculate_dependencies( 892 data['iuse'], data['use'], data['license'], data['depend'], 893 data['rdepend'], data['pdepend'], data['provide'], data['sources'] 894 ) 895 896 data['provide'] = set(portage_metadata['PROVIDE'].split()) 897 data['license'] = portage_metadata['LICENSE'] 898 data['useflags'] = [] 899 for my_use in portage_metadata['USE']: 900 if my_use in portage_metadata['USE_MASK']: 901 continue 902 if my_use in portage_metadata['USE_FORCE']: 903 data['useflags'].append(my_use) 904 continue 905 if my_use in portage_metadata['ENABLED_USE']: 906 data['useflags'].append(my_use) 907 else: 908 data['useflags'].append("-"+my_use) 909 910 # useflags must be a set, as returned by entropy.db.getPackageData 911 data['useflags'] = set(data['useflags']) 912 # sources must be a set, as returned by entropy.db.getPackageData 913 data['sources'] = set(portage_metadata['SRC_URI'].split()) 914 data['dependencies'] = {} 915 916 for x in portage_metadata['RDEPEND'].split(): 917 if x.startswith("!") or (x in ("(", "||", ")", "")): 918 continue 919 data['dependencies'][x] = \ 920 etpConst['dependency_type_ids']['(r)depend_id'] 921 922 for x in portage_metadata['PDEPEND'].split(): 923 if x.startswith("!") or (x in ("(", "||", ")", "")): 924 continue 925 data['dependencies'][x] = \ 926 etpConst['dependency_type_ids']['pdepend_id'] 927 928 data['conflicts'] = [x.replace("!", "") for x in \ 929 portage_metadata['RDEPEND'].split() + \ 930 portage_metadata['PDEPEND'].split() if \ 931 x.startswith("!") and not x in ("(", "||", ")", "")] 932 933 if kern_dep_key is not None: 934 data['dependencies'][kern_dep_key] = \ 935 etpConst['dependency_type_ids']['(r)depend_id'] 936 937 # Conflicting tagged packages support 938 # Needs Entropy Client System Settings Plugin, 939 # but since entropy.server loads entropy.client, it's completely 940 # fine as of now. 941 key = data['category'] + "/" + data['name'] 942 plug_data = etpConst['system_settings_plugins_ids'] 943 client_sysset_plg_id = plug_data['client_plugin'] 944 client_data = system_settings.get(client_sysset_plg_id, {}) 945 confl_data = None 946 947 if client_data: 948 repo_data = client_data['repositories'] 949 confl_data = repo_data['conflicting_tagged_packages'].get(key) 950 951 if confl_data: 952 for conflict in confl_data: 953 data['conflicts'].append(conflict) 954 955 # conflicts must be a set, which is what is returned 956 # by entropy.db.getPackageData 957 data['conflicts'] = set(data['conflicts']) 958 959 # old-style virtual support, we need to check if this pkg provides 960 # PROVIDE metadatum which points to itself, if so, this is the 961 # default 962 provide_extended = set() 963 myself_provide_key = data['category'] + "/" + data['name'] 964 for provide_key in data['provide']: 965 is_provide_default = 0 966 try: 967 profile_default_provide = self._get_default_virtual_pkg( 968 provide_key) 969 except KeyError: 970 profile_default_provide = 1 # cant be this 971 972 if profile_default_provide == myself_provide_key: 973 is_provide_default = 1 974 975 provide_extended.add((provide_key, is_provide_default,)) 976 977 # this actually changes provide format 978 data['provide_extended'] = provide_extended 979 980 # Get License text if possible 981 licenses_dir = os.path.join(self.get_setting('PORTDIR'), 'licenses') 982 data['licensedata'] = self._extract_pkg_metadata_license_data( 983 licenses_dir, data['license']) 984 985 data['mirrorlinks'] = self._extract_pkg_metadata_mirror_links( 986 data['sources']) 987 988 # write only if it's a systempackage 989 data['systempackage'] = False 990 system_packages = [entropy.tools.dep_getkey(x) for x in \ 991 self.get_system_packages()] 992 if data['category'] + "/" + data['name'] in system_packages: 993 data['systempackage'] = True 994 995 # write only if it's a systempackage 996 data['config_protect'] = ' '.join(self.get_merge_protected_paths()) 997 data['config_protect_mask'] = ' '.join( 998 self.get_merge_protected_paths_mask()) 999 1000 log_dir = etpConst['logdir']+"/elog" 1001 if not os.path.isdir(log_dir): os.makedirs(log_dir) 1002 data['messages'] = self._extract_pkg_metadata_messages(log_dir, 1003 data['category'], data['name'], data['version']) 1004 1005 # etpapi must be int, as returned by entropy.db.getPackageData 1006 data['etpapi'] = int(etpConst['etpapi']) 1007 1008 # removing temporary directory 1009 shutil.rmtree(tmp_dir, True) 1010 1011 # clear unused metadata 1012 del data['use'], data['iuse'], data['depend'], data['pdepend'], \ 1013 data['rdepend'] 1014 1015 return data
1016
1017 - def enable_package_compile_options(self, package, options):
1018 """ 1019 Reimplemented from SpmPlugin class. 1020 """ 1021 result = self._unset_package_useflags(package, options) 1022 if not result: 1023 return False 1024 return self._handle_new_useflags(package, options, "")
1025
1026 - def disable_package_compile_options(self, package, options):
1027 """ 1028 Reimplemented from SpmPlugin class. 1029 """ 1030 result = self._unset_package_useflags(package, options) 1031 if not result: 1032 return False 1033 return self._handle_new_useflags(package, options, "-")
1034
1035 - def get_package_compile_options(self, package):
1036 """ 1037 Reimplemented from SpmPlugin class. 1038 """ 1039 matched_atom = self.match_package(package) 1040 if not matched_atom: 1041 return {} 1042 global_useflags = self._get_useflags() 1043 use_force = self._get_useflags_force() 1044 use_mask = self._get_useflags_mask() 1045 package_use_useflags = self._get_package_use_useflags(package) 1046 1047 data = {} 1048 data['use_force'] = use_force.copy() 1049 data['use_mask'] = use_mask.copy() 1050 data['global_use'] = global_useflags.split() 1051 1052 iuse = self.get_package_metadata(package, "IUSE") 1053 if not isinstance(iuse, const_get_stringtype()): 1054 iuse = '' 1055 data['iuse'] = iuse.split()[:] 1056 iuse = set() 1057 for myiuse in data['iuse']: 1058 if myiuse.startswith("+"): 1059 myiuse = myiuse[1:] 1060 iuse.add(myiuse) 1061 1062 use = [f for f in data['global_use'] + \ 1063 list(package_use_useflags['enabled']) if (f in iuse) \ 1064 and (f not in use_mask) and \ 1065 (f not in package_use_useflags['disabled'])] 1066 1067 use_disabled = [f for f in iuse if (f not in data['global_use']) \ 1068 and (f not in use_mask) and \ 1069 (f not in package_use_useflags['enabled'])] 1070 1071 data['use'] = use[:] 1072 data['use_disabled'] = use_disabled[:] 1073 1074 matched_slot = self.get_package_metadata(matched_atom, "SLOT") 1075 try: 1076 inst_key = "%s:%s" % ( 1077 entropy.tools.dep_getkey(package), 1078 matched_slot, 1079 ) 1080 installed_atom = self.match_installed_package(inst_key) 1081 except self.portage.exception.PortageException: 1082 installed_atom = '' 1083 1084 if installed_atom: 1085 1086 # get its useflags 1087 previous_iuse = self.get_installed_package_metadata(installed_atom, 1088 "IUSE").split() 1089 previous_use = self.get_installed_package_metadata(installed_atom, 1090 "USE").split() 1091 1092 new_previous_iuse = set() 1093 for myuse in previous_iuse: 1094 if myuse.startswith("+"): 1095 myuse = myuse[1:] 1096 new_previous_iuse.add(myuse) 1097 previous_iuse = list(new_previous_iuse) 1098 1099 inst_use = [f for f in previous_iuse if (f in previous_use) and \ 1100 (f not in use_mask)] 1101 #inst_use_disabled = [f for f in previous_use if \ 1102 # (f not in previous_iuse) and (f not in use_mask)] 1103 1104 # check removed use 1105 use_removed = [] 1106 for myuse in inst_use: 1107 if myuse not in use: 1108 use_removed.append(myuse) 1109 1110 # use not available 1111 use_not_avail = [] 1112 for myuse in previous_iuse: 1113 if (myuse not in iuse) and (myuse not in use_removed): 1114 use_not_avail.append(myuse) 1115 1116 # check new use 1117 t_use = [] 1118 for myuse in use: 1119 if myuse not in inst_use: 1120 myuse = "+%s*" % (myuse,) 1121 t_use.append(myuse) 1122 use = t_use 1123 1124 # check disabled use 1125 t_use_disabled = [] 1126 for myuse in use_disabled: 1127 if myuse in inst_use: 1128 if myuse in use_removed+use_not_avail: 1129 continue 1130 myuse = "-%s*" % (myuse,) 1131 else: 1132 myuse = "-%s" % (myuse,) 1133 t_use_disabled.append(myuse) 1134 use_disabled = t_use_disabled 1135 1136 for myuse in use_removed: 1137 use_disabled.append("(-%s*)" % (myuse,)) 1138 for myuse in use_not_avail: 1139 use_disabled.append("(-%s)" % (myuse,)) 1140 else: 1141 use_disabled = ["-"+x for x in use_disabled] 1142 1143 data['use_string'] = ' '.join(sorted(use)+sorted([x for x in \ 1144 use_disabled])) 1145 data['use_string_colored'] = ' '.join( 1146 sorted([darkred(x) for x in use if not x.startswith("+")] + \ 1147 [darkgreen(x) for x in use if x.startswith("+")]) + \ 1148 sorted([darkblue(x) for x in use_disabled if x.startswith("-")] + \ 1149 [brown(x) for x in use_disabled if x.startswith("(") and \ 1150 (x.find("*") == -1)] + \ 1151 [purple(x) for x in use_disabled if x.startswith("(") and \ 1152 (x.find("*") != -1)] 1153 ) 1154 ) 1155 1156 return data
1157
1158 - def get_installed_package_compile_options(self, package, root = None):
1159 """ 1160 Reimplemented from SpmPlugin class. 1161 """ 1162 matched_atom = self.match_installed_package(package, root = root) 1163 if not matched_atom: 1164 return {} 1165 1166 global_use = self.get_installed_package_metadata(matched_atom, "USE", 1167 root = root) 1168 use_mask = self._get_useflags_mask() 1169 1170 data = {} 1171 data['use_mask'] = use_mask.copy() 1172 data['global_use'] = global_use.split() 1173 1174 iuse = self.get_installed_package_metadata(matched_atom, "IUSE", 1175 root = root) 1176 if not isinstance(iuse, const_get_stringtype()): 1177 iuse = '' 1178 data['iuse'] = iuse.split()[:] 1179 iuse = set() 1180 for myiuse in data['iuse']: 1181 if myiuse.startswith("+"): 1182 myiuse = myiuse[1:] 1183 iuse.add(myiuse) 1184 1185 use = [f for f in data['global_use'] if (f in iuse) and \ 1186 (f not in use_mask)] 1187 use_disabled = [f for f in iuse if (f not in data['global_use']) and \ 1188 (f not in use_mask)] 1189 data['use'] = use[:] 1190 data['use_disabled'] = use_disabled[:] 1191 1192 data['use_string'] = ' '.join(sorted(use)+sorted([x for x in \ 1193 use_disabled])) 1194 data['use_string_colored'] = ' '.join( 1195 sorted([darkred(x) for x in use if not x.startswith("+")] + \ 1196 [darkgreen(x) for x in use if x.startswith("+")]) + \ 1197 sorted([darkblue(x) for x in use_disabled if x.startswith("-")] + \ 1198 [brown(x) for x in use_disabled if x.startswith("(") and \ 1199 (x.find("*") == -1)] + \ 1200 [purple(x) for x in use_disabled if x.startswith("(") and \ 1201 (x.find("*") != -1)] 1202 ) 1203 ) 1204 return data
1205
1206 - def get_installed_package_content(self, package, root = None):
1207 """ 1208 Reimplemented from SpmPlugin class. 1209 """ 1210 if root is None: 1211 root = etpConst['systemroot'] + os.path.sep 1212 mytree = self._get_portage_vartree(root) 1213 1214 cat, pkgv = package.split("/") 1215 return sorted(self.portage.dblink(cat, pkgv, root, 1216 self.portage.settings).getcontents())
1217
1218 - def get_packages(self, categories = None, filter_reinstalls = True):
1219 """ 1220 Reimplemented from SpmPlugin class. 1221 """ 1222 if categories is None: 1223 categories = [] 1224 1225 root = etpConst['systemroot'] + os.path.sep 1226 mysettings = self._get_portage_config(os.path.sep, root) 1227 portdb = self.portage.portdbapi(mysettings["PORTDIR"], 1228 mysettings = mysettings) 1229 1230 cps = portdb.cp_all() 1231 visibles = set() 1232 for cp in cps: 1233 if categories and cp.split("/")[0] not in categories: 1234 continue 1235 1236 # get slots 1237 slots = set() 1238 atoms = self.match_package(cp, match_type = "match-visible") 1239 if atoms: 1240 for atom in atoms: 1241 slots.add(portdb.aux_get(atom, ["SLOT"])[0]) 1242 for slot in slots: 1243 visibles.add(cp+":"+slot) 1244 1245 # now match visibles 1246 available = set() 1247 for visible in visibles: 1248 1249 match = self.match_package(visible) 1250 if not match: 1251 continue 1252 1253 if filter_reinstalls: 1254 installed = self.match_installed_package(visible) 1255 if installed != match: 1256 available.add(match) 1257 else: 1258 available.add(match) 1259 1260 return available
1261
1262 - def compile_packages(self, packages, stdin = None, stdout = None, 1263 stderr = None, environ = None, pid_write_func = None, 1264 pretend = False, verbose = False, fetch_only = False, 1265 build_only = False, no_dependencies = False, 1266 ask = False, coloured_output = False, oneshot = False):
1267 1268 cmd = [PortagePlugin._cmd_map['exec_cmd']] 1269 if pretend: 1270 cmd.append(PortagePlugin._cmd_map['pretend_cmd']) 1271 if verbose: 1272 cmd.append(PortagePlugin._cmd_map['verbose_cmd']) 1273 if ask: 1274 cmd.append(PortagePlugin._cmd_map['ask_cmd']) 1275 if oneshot: 1276 cmd.append(PortagePlugin._cmd_map['oneshot_cmd']) 1277 if not coloured_output: 1278 cmd.append(PortagePlugin._cmd_map['nocolor_cmd']) 1279 if fetch_only: 1280 cmd.append(PortagePlugin._cmd_map['fetchonly_cmd']) 1281 if build_only: 1282 cmd.append(PortagePlugin._cmd_map['buildonly_cmd']) 1283 if no_dependencies: 1284 cmd.append(PortagePlugin._cmd_map['nodeps_cmd']) 1285 1286 cmd.extend(packages) 1287 cmd_string = """\ 1288 %s && %s && %s 1289 """ % (PortagePlugin._cmd_map['env_update_cmd'], 1290 PortagePlugin._cmd_map['source_profile_cmd'], 1291 ' '.join(cmd) 1292 ) 1293 1294 env = os.environ.copy() 1295 if environ is not None: 1296 env.update(environ) 1297 1298 proc = subprocess.Popen(cmd_string, stdout = stdout, stderr = stderr, 1299 stdin = stdin, env = env, shell = True) 1300 if pid_write_func is not None: 1301 pid_write_func(proc.pid) 1302 return proc.wait()
1303
1304 - def remove_packages(self, packages, stdin = None, stdout = None, 1305 stderr = None, environ = None, pid_write_func = None, 1306 pretend = False, verbose = False, no_dependencies = False, ask = False, 1307 coloured_output = False):
1308 1309 cmd = [PortagePlugin._cmd_map['exec_cmd'], 1310 PortagePlugin._cmd_map['remove_cmd']] 1311 if pretend: 1312 cmd.append(PortagePlugin._cmd_map['pretend_cmd']) 1313 if verbose: 1314 cmd.append(PortagePlugin._cmd_map['verbose_cmd']) 1315 if ask: 1316 cmd.append(PortagePlugin._cmd_map['ask_cmd']) 1317 if not coloured_output: 1318 cmd.append(PortagePlugin._cmd_map['nocolor_cmd']) 1319 if no_dependencies: 1320 cmd.append(PortagePlugin._cmd_map['nodeps_cmd']) 1321 1322 cmd.extend(packages) 1323 cmd_string = """\ 1324 %s && %s && %s 1325 """ % (PortagePlugin._cmd_map['env_update_cmd'], 1326 PortagePlugin._cmd_map['source_profile_cmd'], 1327 ' '.join(cmd) 1328 ) 1329 1330 env = os.environ.copy() 1331 if environ is not None: 1332 env.update(environ) 1333 1334 proc = subprocess.Popen(cmd_string, stdout = stdout, stderr = stderr, 1335 stdin = stdin, env = env, shell = True) 1336 if pid_write_func is not None: 1337 pid_write_func(proc.pid) 1338 return proc.wait()
1339
1340 - def environment_update(self, stdout = None, stderr = None):
1341 kwargs = {} 1342 if etpUi['mute']: 1343 kwargs['stdout'] = stdout 1344 kwargs['stderr'] = stderr 1345 args = (PortagePlugin._cmd_map['env_update_cmd'],) 1346 proc = subprocess.Popen(args, **kwargs) 1347 proc.wait()
1348
1349 - def print_build_environment_info(self, stdin = None, stdout = None, 1350 stderr = None, environ = None, pid_write_func = None, 1351 coloured_output = False):
1352 1353 cmd = [PortagePlugin._cmd_map['exec_cmd'], 1354 PortagePlugin._cmd_map['info_cmd']] 1355 if not coloured_output: 1356 cmd.append(PortagePlugin._cmd_map['nocolor_cmd']) 1357 1358 cmd_string = """\ 1359 %s && %s && %s 1360 """ % (PortagePlugin._cmd_map['env_update_cmd'], 1361 PortagePlugin._cmd_map['source_profile_cmd'], 1362 ' '.join(cmd) 1363 ) 1364 1365 env = os.environ.copy() 1366 if environ is not None: 1367 env.update(environ) 1368 1369 proc = subprocess.Popen(cmd_string, stdout = stdout, stderr = stderr, 1370 stdin = stdin, env = env, shell = True) 1371 if pid_write_func is not None: 1372 pid_write_func(proc.pid) 1373 return proc.wait()
1374
1375 - def get_installed_packages(self, categories = None, root = None):
1376 """ 1377 Reimplemented from SpmPlugin class. 1378 """ 1379 vartree = self._get_portage_vartree(root = root) 1380 packages = vartree.dbapi.cpv_all() 1381 if not categories: 1382 return packages 1383 1384 def catfilter(pkg): 1385 if pkg.split("/", 1)[0] in categories: 1386 return True 1387 return False
1388 1389 return list(filter(catfilter, packages))
1390
1391 - def get_package_sets(self, builtin_sets):
1392 """ 1393 Reimplemented from SpmPlugin class. 1394 """ 1395 config = self._get_set_config() 1396 if config == None: 1397 return {} 1398 1399 mysets = config.getSets() 1400 if not builtin_sets: 1401 builtin_pkg_sets = [x for x in PortagePlugin.builtin_pkg_sets if \ 1402 x in mysets] 1403 for pkg_set in builtin_pkg_sets: 1404 mysets.pop(pkg_set) 1405 1406 return dict((x, y.getAtoms(),) for x, y in list(mysets.items()))
1407
1408 - def convert_from_entropy_package_name(self, entropy_package_name):
1409 """ 1410 Reimplemented from SpmPlugin class. 1411 """ 1412 spm_name = entropy.tools.remove_tag(entropy_package_name) 1413 spm_name = entropy.tools.remove_entropy_revision(spm_name) 1414 return spm_name
1415
1416 - def assign_uid_to_installed_package(self, package, root = None):
1417 """ 1418 Reimplemented from SpmPlugin class. 1419 """ 1420 if root is None: 1421 root = etpConst['systemroot'] + os.path.sep 1422 1423 vartree = self._get_portage_vartree(root) 1424 dbbuild = self.get_installed_package_build_script_path(package, 1425 root = root) 1426 1427 counter_dir = os.path.dirname(dbbuild) 1428 counter_name = PortagePlugin.xpak_entries['counter'] 1429 counter_path = os.path.join(counter_dir, counter_name) 1430 1431 if not os.access(counter_dir, os.W_OK): 1432 raise SPMError("SPM package directory not found") 1433 1434 with open(counter_path, "wb") as count_f: 1435 new_counter = vartree.dbapi.counter_tick(root, mycpv = package) 1436 count_f.write(const_convert_to_rawstring(new_counter)) 1437 count_f.flush() 1438 1439 return new_counter
1440
1441 - def resolve_package_uid(self, entropy_repository, 1442 entropy_repository_package_id):
1443 """ 1444 Reimplemented from SpmPlugin class. 1445 """ 1446 counter_path = PortagePlugin.xpak_entries['counter'] 1447 entropy_atom = entropy_repository.retrieveAtom( 1448 entropy_repository_package_id) 1449 1450 spm_name = self.convert_from_entropy_package_name(entropy_atom) 1451 build_path = self.get_installed_package_build_script_path(spm_name) 1452 atom_counter_path = os.path.join(os.path.dirname(build_path), 1453 counter_path) 1454 1455 if not (os.access(atom_counter_path, os.R_OK) and \ 1456 os.path.isfile(atom_counter_path)): 1457 return None # not found 1458 1459 try: 1460 with open(atom_counter_path, "r") as f: 1461 counter = int(f.readline().strip()) 1462 except ValueError: 1463 raise SPMError("invalid Unique Identifier found") 1464 except Exception as e: 1465 raise SPMError("General SPM Error: %s" % (e,)) 1466 1467 return counter
1468
1469 - def search_paths_owners(self, paths, exact_match = True):
1470 """ 1471 Reimplemented from SpmPlugin class. 1472 """ 1473 if not isinstance(paths, (list, set, frozenset, dict, tuple)): 1474 raise AttributeError("iterable needed") 1475 root = etpConst['systemroot'] + os.path.sep 1476 mytree = self._get_portage_vartree(root) 1477 packages = mytree.dbapi.cpv_all() 1478 matches = {} 1479 1480 for package in packages: 1481 cat, pkgv = package.split("/") 1482 content = self.portage.dblink(cat, pkgv, root, 1483 self.portage.settings).getcontents() 1484 1485 if exact_match: 1486 for filename in paths: 1487 if filename in content: 1488 myslot = self.get_installed_package_metadata(package, 1489 "SLOT") 1490 obj = matches.setdefault((package, myslot,), set()) 1491 obj.add(filename) 1492 else: 1493 for filename in paths: 1494 for myfile in content: 1495 if myfile.find(filename) == -1: 1496 continue 1497 myslot = self.get_installed_package_metadata(package, 1498 "SLOT") 1499 obj = matches.setdefault((package, myslot,), set()) 1500 obj.add(filename) 1501 1502 return matches
1503
1504 - def _portage_doebuild(self, myebuild, mydo, tree, cpv, 1505 portage_tmpdir = None, licenses = None):
1506 1507 # myebuild = path/to/ebuild.ebuild with a valid unpacked xpak metadata 1508 # tree = "bintree" 1509 # cpv = atom 1510 # mydbapi = portage.fakedbapi(settings=portage.settings) 1511 # vartree = portage.vartree(root=myroot) 1512 1513 if licenses is None: 1514 licenses = [] 1515 1516 oldsystderr = sys.stderr 1517 dev_null = open("/dev/null", "w") 1518 if not etpUi['debug']: 1519 sys.stderr = dev_null 1520 1521 ### SETUP ENVIRONMENT 1522 # if mute, supress portage output 1523 domute = False 1524 if etpUi['mute']: 1525 domute = True 1526 oldsysstdout = sys.stdout 1527 sys.stdout = dev_null 1528 1529 root = etpConst['systemroot'] + os.path.sep 1530 1531 # old way to avoid loop of deaths for entropy portage hooks 1532 os.environ["SKIP_EQUO_SYNC"] = "1" 1533 1534 # load metadata 1535 myebuilddir = os.path.dirname(myebuild) 1536 keys = self.portage.auxdbkeys 1537 metadata = {} 1538 1539 for key in keys: 1540 mykeypath = os.path.join(myebuilddir, key) 1541 if os.path.isfile(mykeypath) and os.access(mykeypath, os.R_OK): 1542 if sys.hexversion >= 0x3000000: 1543 f = open(mykeypath, "r", encoding = "raw_unicode_escape") 1544 else: 1545 f = open(mykeypath, "rb") 1546 metadata[key] = f.readline().strip() 1547 f.close() 1548 1549 ### END SETUP ENVIRONMENT 1550 1551 # find config 1552 mysettings = self._get_portage_config(os.path.sep, root) 1553 mysettings['EBUILD_PHASE'] = mydo 1554 1555 # crappy, broken, ebuilds, put accept_license eutils call 1556 # in pkg_setup, when environment variables are not setup yet 1557 # WARNING WARNING WARNING: 1558 # if some other hook fails for other reasons, it's because 1559 # it may miss env variable here. 1560 mysettings['LICENSE'] = str(' '.join(licenses)) 1561 if licenses: 1562 # we already do this early 1563 mysettings["ACCEPT_LICENSE"] = mysettings['LICENSE'] 1564 mysettings.backup_changes("ACCEPT_LICENSE") 1565 1566 mysettings['EAPI'] = "0" 1567 if 'EAPI' in metadata: 1568 mysettings['EAPI'] = metadata['EAPI'] 1569 1570 # workaround for scripts asking for user intervention 1571 mysettings['ROOT'] = root 1572 mysettings['CD_ROOT'] = "/tmp" 1573 1574 mysettings.backup_changes("EAPI") 1575 mysettings.backup_changes("LICENSE") 1576 mysettings.backup_changes("EBUILD_PHASE") 1577 mysettings.backup_changes("ROOT") 1578 mysettings.backup_changes("CD_ROOT") 1579 1580 try: # this is a >portage-2.1.4_rc11 feature 1581 mysettings._environ_whitelist = set(mysettings._environ_whitelist) 1582 # put our vars into whitelist 1583 mysettings._environ_whitelist.add("SKIP_EQUO_SYNC") 1584 mysettings._environ_whitelist.add("ACCEPT_LICENSE") 1585 mysettings._environ_whitelist.add("CD_ROOT") 1586 mysettings._environ_whitelist.add("ROOT") 1587 mysettings._environ_whitelist = frozenset(mysettings._environ_whitelist) 1588 except (AttributeError,): 1589 self.log_message(entropy.tools.get_traceback()) 1590 1591 portage_tmpdir_created = False # for pkg_postrm, pkg_prerm 1592 1593 if portage_tmpdir is None: 1594 portage_tmpdir = entropy.tools.get_random_temp_file() 1595 1596 if portage_tmpdir: 1597 if not os.path.isdir(portage_tmpdir): 1598 os.makedirs(portage_tmpdir) 1599 portage_tmpdir_created = True 1600 mysettings['PORTAGE_TMPDIR'] = str(portage_tmpdir) 1601 mysettings.backup_changes("PORTAGE_TMPDIR") 1602 1603 # create FAKE ${PORTDIR} directory and licenses subdir 1604 portdir = os.path.join(portage_tmpdir, "portdir") 1605 portdir_lic = os.path.join(portdir, "licenses") 1606 if not os.path.isdir(portdir): 1607 os.mkdir(portdir) # portage_tmpdir must be available! 1608 # create licenses subdir 1609 if not os.path.isdir(portdir_lic): 1610 os.mkdir(portdir_lic) 1611 1612 # set fake PORTDIR 1613 old_portdir = mysettings["PORTDIR"][:] 1614 mysettings["PORTDIR"] = portdir 1615 mysettings.backup_changes("PORTDIR") 1616 1617 ### WORKAROUND for buggy check_license() in eutils.eclass 1618 ### that looks for file availability before considering 1619 ### ACCEPT_LICENSE 1620 for lic in licenses: 1621 lic_path = os.path.join(portdir_lic, lic) 1622 if os.access(portdir_lic, os.W_OK | os.R_OK): 1623 lic_f = open(lic_path, "wb") 1624 lic_f.close() 1625 1626 cpv = str(cpv) 1627 mydbapi = self.portage.fakedbapi(settings=mysettings) 1628 mydbapi.cpv_inject(cpv, metadata = metadata) 1629 mysettings.setcpv(cpv, mydb = mydbapi) 1630 1631 # cached vartree class 1632 vartree = self._get_portage_vartree(root = root) 1633 1634 try: 1635 rc = self.portage.doebuild( 1636 myebuild = str(myebuild), 1637 mydo = str(mydo), 1638 myroot = root, 1639 tree = tree, 1640 mysettings = mysettings, 1641 mydbapi = mydbapi, 1642 vartree = vartree, 1643 use_cache = 0 1644 ) 1645 except: 1646 self.log_message(entropy.tools.get_traceback()) 1647 raise 1648 1649 # if mute, restore old stdout/stderr 1650 if domute: 1651 sys.stdout = oldsysstdout 1652 1653 sys.stderr = oldsystderr 1654 dev_null.close() 1655 1656 if portage_tmpdir_created: 1657 shutil.rmtree(portage_tmpdir, True) 1658 1659 # reset PORTDIR back to its old path 1660 # for security ! 1661 mysettings["PORTDIR"] = old_portdir 1662 mysettings.backup_changes("PORTDIR") 1663 1664 del mydbapi 1665 del metadata 1666 del keys 1667 return rc
1668 1669 @staticmethod
1670 - def _pkg_compose_atom(package_metadata):
1671 return package_metadata['category'] + "/" + \ 1672 package_metadata['name'] + "-" + package_metadata['version']
1673 1674 @staticmethod
1675 - def _pkg_compose_xpak_ebuild(package_metadata):
1676 package = PortagePlugin._pkg_compose_atom(package_metadata) 1677 return os.path.join(package_metadata['xpakdir'], 1678 os.path.basename(package) + PortagePlugin.EBUILD_EXT)
1679
1680 - def _pkg_remove_overlayed_ebuild(self, moved_ebuild):
1681 1682 mydir = os.path.dirname(moved_ebuild) 1683 shutil.rmtree(mydir, True) 1684 mydir = os.path.dirname(mydir) 1685 content = os.listdir(mydir) 1686 while not content: 1687 os.rmdir(mydir) 1688 mydir = os.path.dirname(mydir) 1689 content = os.listdir(mydir)
1690
1691 - def _pkg_remove_ebuild_env_setup_hook(self, ebuild):
1692 1693 ebuild_path = os.path.dirname(ebuild) 1694 1695 myroot = os.path.sep 1696 if etpConst['systemroot']: 1697 myroot = etpConst['systemroot'] + os.path.sep 1698 1699 # we need to fix ROOT= if it's set inside environment 1700 bz2envfile = os.path.join(ebuild_path, PortagePlugin.ENV_FILE_COMP) 1701 if os.path.isfile(bz2envfile) and os.path.isdir(myroot): 1702 envfile = entropy.tools.unpack_bzip2(bz2envfile) 1703 bzf = bz2.BZ2File(bz2envfile, "w") 1704 f = open(envfile, "rb") 1705 line = f.readline() 1706 while line: 1707 if sys.hexversion >= 0x3000000: 1708 if line.startswith(b"ROOT="): 1709 line = b"ROOT=%s\n" % (myroot,) 1710 else: 1711 if line.startswith("ROOT="): 1712 line = "ROOT=%s\n" % (myroot,) 1713 bzf.write(line) 1714 line = f.readline() 1715 1716 f.close() 1717 bzf.close() 1718 os.remove(envfile)
1719
1720 - def _pkg_remove_setup_ebuild_env(self, myebuild, portage_atom):
1721 1722 ebuild_dir = os.path.dirname(myebuild) 1723 ebuild_file = os.path.basename(myebuild) 1724 moved_ebuild = None 1725 1726 # copy the whole directory in a safe place 1727 dest_dir = os.path.join(etpConst['entropyunpackdir'], 1728 "vardb/" + portage_atom) 1729 if os.path.exists(dest_dir): 1730 if os.path.isdir(dest_dir): 1731 shutil.rmtree(dest_dir, True) 1732 elif os.path.isfile(dest_dir) or os.path.islink(dest_dir): 1733 os.remove(dest_dir) 1734 1735 os.makedirs(dest_dir) 1736 items = os.listdir(ebuild_dir) 1737 for item in items: 1738 myfrom = os.path.join(ebuild_dir, item) 1739 myto = os.path.join(dest_dir, item) 1740 shutil.copy2(myfrom, myto) 1741 1742 newmyebuild = os.path.join(dest_dir, ebuild_file) 1743 if os.path.isfile(newmyebuild): 1744 myebuild = newmyebuild 1745 moved_ebuild = myebuild 1746 self._pkg_remove_ebuild_env_setup_hook(myebuild) 1747 1748 return myebuild, moved_ebuild
1749
1750 - def _pkg_setup(self, package_metadata, skip_if_found = False):
1751 1752 package = PortagePlugin._pkg_compose_atom(package_metadata) 1753 env_file = os.path.join(package_metadata['unpackdir'], "portage", 1754 package, "temp/environment") 1755 1756 if os.path.isfile(env_file) and skip_if_found: 1757 return 0 1758 1759 # FIXME: please remove as soon as upstream fixes it 1760 # FIXME: workaround for buggy linux-info.eclass not being 1761 # ported to EAPI=2 yet. 1762 # It is required to make depmod running properly for the 1763 # kernel modules inside this ebuild 1764 # fix KV_OUT_DIR= inside environment 1765 bz2envfile = os.path.join(package_metadata['xpakdir'], 1766 PortagePlugin.ENV_FILE_COMP) 1767 1768 if "linux-info" in package_metadata['eclasses'] and \ 1769 os.path.isfile(bz2envfile) and package_metadata['versiontag']: 1770 1771 envfile = entropy.tools.unpack_bzip2(bz2envfile) 1772 bzf = bz2.BZ2File(bz2envfile, "w") 1773 f = open(envfile, "rb") 1774 line = f.readline() 1775 while line: 1776 1777 if sys.hexversion >= 0x3000000: 1778 if line == b"KV_OUT_DIR=/usr/src/linux\n": 1779 line = b"KV_OUT_DIR=/lib/modules/" 1780 line += const_convert_to_rawstring( 1781 package_metadata['versiontag']) 1782 line += "/build\n" 1783 else: 1784 if line == "KV_OUT_DIR=/usr/src/linux\n": 1785 line = "KV_OUT_DIR=/lib/modules/%s/build\n" % ( 1786 package_metadata['versiontag'],) 1787 bzf.write(line) 1788 line = f.readline() 1789 f.close() 1790 bzf.close() 1791 os.remove(envfile) 1792 1793 ebuild = PortagePlugin._pkg_compose_xpak_ebuild(package_metadata) 1794 rc = self._portage_doebuild(ebuild, "setup", 1795 "bintree", package, portage_tmpdir = package_metadata['unpackdir'], 1796 licenses = package_metadata.get('accept_license')) 1797 1798 if rc == 1: 1799 self.log_message( 1800 "[POST] ATTENTION Cannot properly run Source Package Manager" 1801 " setup phase for %s Something bad happened." % (package,) 1802 ) 1803 1804 return rc
1805
1806 - def _pkg_fooinst(self, package_metadata, phase):
1807 1808 tmp_file = tempfile.mktemp() 1809 stdfile = open(tmp_file, "wb") 1810 oldstderr = sys.stderr 1811 oldstdout = sys.stdout 1812 sys.stderr = stdfile 1813 1814 package = PortagePlugin._pkg_compose_atom(package_metadata) 1815 ebuild = PortagePlugin._pkg_compose_xpak_ebuild(package_metadata) 1816 rc = 0 1817 remove_tmp = True 1818 1819 try: 1820 # is ebuild available 1821 if not (os.path.isfile(ebuild) and os.access(ebuild, os.R_OK)): 1822 return rc 1823 1824 try: 1825 1826 if not etpUi['debug']: 1827 sys.stdout = stdfile 1828 self._pkg_setup(package_metadata, skip_if_found = True) 1829 if not etpUi['debug']: 1830 sys.stdout = oldstdout 1831 1832 rc = self._portage_doebuild(ebuild, phase, "bintree", 1833 package, portage_tmpdir = package_metadata['unpackdir'], 1834 licenses = package_metadata.get('accept_license')) 1835 1836 if rc != 0: 1837 self.log_message( 1838 "[PRE] ATTENTION Cannot properly run SPM %s" 1839 " phase for %s. Something bad happened." % ( 1840 phase, package,) 1841 ) 1842 1843 except Exception as e: 1844 1845 stdfile.flush() 1846 sys.stdout = oldstdout 1847 entropy.tools.print_traceback() 1848 1849 self.log_message( 1850 "[PRE] ATTENTION Cannot properly run SPM %s" 1851 " phase for %s. Something bad happened." 1852 " Exception %s [%s]" % ( 1853 phase, package, Exception, e,) 1854 ) 1855 1856 mytxt = "%s: %s %s." % ( 1857 bold(_("QA")), 1858 brown(_("Cannot run Source Package Manager trigger for")), 1859 bold(str(package)), 1860 ) 1861 self.updateProgress( 1862 mytxt, 1863 importance = 0, 1864 header = red(" ## ") 1865 ) 1866 mytxt = "%s. %s: %s + %s [%s]" % ( 1867 brown(_("Please report it")), 1868 bold(_("Attach this")), 1869 darkred(etpConst['spmlogfile']), 1870 darkred(tmp_file), 1871 brown(phase), 1872 ) 1873 self.updateProgress( 1874 mytxt, 1875 importance = 0, 1876 header = red(" ## ") 1877 ) 1878 remove_tmp = False 1879 1880 return rc 1881 1882 finally: 1883 1884 sys.stderr = oldstderr 1885 sys.stdout = oldstdout 1886 stdfile.flush() 1887 stdfile.close() 1888 1889 if (rc == 0) and remove_tmp: 1890 try: 1891 os.remove(tmp_file) 1892 except OSError: 1893 pass
1894
1895 - def _pkg_foorm(self, package_metadata, phase):
1896 1897 tmp_file = tempfile.mktemp() 1898 stdfile = open(tmp_file, "wb") 1899 oldstderr = sys.stderr 1900 oldstdout = sys.stdout 1901 sys.stderr = stdfile 1902 1903 rc = 0 1904 remove_tmp = True 1905 moved_ebuild = None 1906 package = PortagePlugin._pkg_compose_atom(package_metadata) 1907 ebuild = self.get_installed_package_build_script_path(package) 1908 1909 try: 1910 1911 if not os.path.isfile(ebuild): 1912 return 0 1913 1914 try: 1915 ebuild, moved_ebuild = self._pkg_remove_setup_ebuild_env( 1916 ebuild, package) 1917 1918 except EOFError as e: 1919 sys.stderr = oldstderr 1920 # stuff on system is broken, ignore it 1921 self.updateProgress( 1922 darkred("!!! Ebuild: pkg_" + phase + "() failed, EOFError: ") + \ 1923 str(e) + darkred(" - ignoring"), 1924 importance = 1, 1925 type = "warning", 1926 header = red(" ## ") 1927 ) 1928 return 0 1929 1930 except ImportError as e: 1931 sys.stderr = oldstderr 1932 # stuff on system is broken, ignore it 1933 self.updateProgress( 1934 darkred("!!! Ebuild: pkg_" + phase + "() failed, ImportError: ") + \ 1935 str(e) + darkred(" - ignoring"), 1936 importance = 1, 1937 type = "warning", 1938 header = red(" ## ") 1939 ) 1940 return 0 1941 1942 try: 1943 1944 work_dir = os.path.join(etpConst['entropyunpackdir'], package) 1945 1946 rc = self._portage_doebuild(ebuild, phase, "bintree", 1947 package, portage_tmpdir = work_dir, 1948 licenses = package_metadata.get('accept_license')) 1949 1950 if rc != 1: 1951 self.log_message( 1952 "[PRE] ATTENTION Cannot properly run SPM %s trigger " 1953 "for %s. Something bad happened." % (phase, package,) 1954 ) 1955 1956 except Exception as e: 1957 1958 stdfile.flush() 1959 sys.stdout = oldstdout 1960 entropy.tools.print_traceback() 1961 1962 self.log_message( 1963 "[PRE] ATTENTION Cannot properly run SPM %s" 1964 " phase for %s. Something bad happened." 1965 " Exception %s [%s]" % (phase, package, Exception, e,) 1966 ) 1967 1968 mytxt = "%s: %s %s." % ( 1969 bold(_("QA")), 1970 brown(_("Cannot run Source Package Manager trigger for")), 1971 bold(str(package)), 1972 ) 1973 self.updateProgress( 1974 mytxt, 1975 importance = 0, 1976 header = red(" ## ") 1977 ) 1978 mytxt = "%s. %s: %s + %s [%s]" % ( 1979 brown(_("Please report it")), 1980 bold(_("Attach this")), 1981 darkred(etpConst['spmlogfile']), 1982 darkred(tmp_file), 1983 brown(phase), 1984 ) 1985 self.updateProgress( 1986 mytxt, 1987 importance = 0, 1988 header = red(" ## ") 1989 ) 1990 remove_tmp = False 1991 1992 if moved_ebuild is not None: 1993 if os.path.isfile(moved_ebuild): 1994 self._pkg_remove_overlayed_ebuild(moved_ebuild) 1995 1996 return rc 1997 1998 finally: 1999 2000 sys.stderr = oldstderr 2001 sys.stdout = oldstdout 2002 stdfile.flush() 2003 stdfile.close() 2004 2005 if (rc == 0) and remove_tmp: 2006 try: 2007 os.remove(tmp_file) 2008 except OSError: 2009 pass
2010
2011 - def _pkg_preinst(self, package_metadata):
2012 return self._pkg_fooinst(package_metadata, "preinst")
2013
2014 - def _pkg_postinst(self, package_metadata):
2015 return self._pkg_fooinst(package_metadata, "postinst")
2016
2017 - def _pkg_prerm(self, package_metadata):
2018 return self._pkg_foorm(package_metadata, "prerm")
2019
2020 - def _pkg_postrm(self, package_metadata):
2021 return self._pkg_foorm(package_metadata, "postrm")
2022
2023 - def _pkg_config(self, package_metadata):
2024 2025 package = PortagePlugin._pkg_compose_atom(package_metadata) 2026 ebuild = self.get_installed_package_build_script_path(package) 2027 if not os.path.isfile(ebuild): 2028 return 2 2029 2030 try: 2031 2032 rc = self._portage_doebuild(ebuild, "config", "bintree", 2033 package, licenses = package_metadata.get('accept_license')) 2034 2035 if rc != 0: 2036 return 3 2037 2038 except Exception as err: 2039 2040 entropy.tools.print_traceback() 2041 mytxt = "%s: %s %s." % ( 2042 bold(_("QA")), 2043 brown(_("Cannot run SPM configure phase for")), 2044 bold(str(package)), 2045 ) 2046 mytxt2 = "%s: %s, %s" % ( 2047 bold(_("Error")), 2048 type(Exception), 2049 err, 2050 ) 2051 for txt in (mytxt, mytxt2,): 2052 self.updateProgress( 2053 txt, 2054 importance = 0, 2055 header = red(" ## ") 2056 ) 2057 return 1 2058 2059 return 0
2060
2061 - def append_metadata_to_package(self, entropy_package_name, package_path):
2062 """ 2063 Reimplemented from SpmPlugin class. 2064 """ 2065 spm_name = self.convert_from_entropy_package_name(entropy_package_name) 2066 dbbuild = self.get_installed_package_build_script_path(spm_name) 2067 dbdir = os.path.dirname(dbbuild) 2068 2069 if os.path.isdir(dbdir): 2070 tbz2 = xpak.tbz2(package_path) 2071 tbz2.recompose(dbdir) 2072 return True 2073 return False
2074
2075 - def __run_pkg_sync_quickpkg(self, entropy_server, atoms, repo_db, repo):
2076 """ 2077 Executes packages regeneration for given atoms. 2078 """ 2079 package_paths = set() 2080 runatoms = set() 2081 for myatom in atoms: 2082 mymatch = repo_db.atomMatch(myatom) 2083 if mymatch[0] == -1: 2084 continue 2085 myatom = repo_db.retrieveAtom(mymatch[0]) 2086 myatom = entropy.tools.remove_tag(myatom) 2087 runatoms.add(myatom) 2088 2089 for myatom in runatoms: 2090 2091 self.updateProgress( 2092 red("%s: " % (_("repackaging"),) )+blue(myatom), 2093 importance = 1, 2094 type = "warning", 2095 header = blue(" # ") 2096 ) 2097 mydest = entropy_server.get_local_store_directory(repo = repo) 2098 try: 2099 mypath = self.generate_package(myatom, mydest) 2100 except: 2101 # remove broken bin before raising 2102 mypath = os.path.join(mydest, 2103 os.path.basename(myatom) + etpConst['packagesext']) 2104 if os.path.isfile(mypath): 2105 os.remove(mypath) 2106 entropy.tools.print_traceback() 2107 mytxt = "%s: %s: %s, %s." % ( 2108 bold(_("WARNING")), 2109 red(_("Cannot complete quickpkg for atom")), 2110 blue(myatom), 2111 _("do it manually"), 2112 ) 2113 self.updateProgress( 2114 mytxt, 2115 importance = 1, 2116 type = "warning", 2117 header = darkred(" * ") 2118 ) 2119 continue 2120 package_paths.add(mypath) 2121 packages_data = [(x, False,) for x in package_paths] 2122 idpackages = entropy_server.add_packages_to_repository(packages_data, 2123 repo = repo) 2124 2125 if not idpackages: 2126 2127 mytxt = "%s: %s. %s." % ( 2128 bold(_("ATTENTION")), 2129 red(_("package files rebuild did not run properly")), 2130 red(_("Please update packages manually")), 2131 ) 2132 self.updateProgress( 2133 mytxt, 2134 importance = 1, 2135 type = "warning", 2136 header = darkred(" * ") 2137 )
2138
2139 - def package_names_update(self, entropy_repository, entropy_repository_id, 2140 entropy_server, entropy_branch):
2141 2142 # TODO: remove this 2143 from entropy.server.interfaces.main import ServerEntropyRepositoryPlugin 2144 2145 repo_updates_file = entropy_server.get_local_database_treeupdates_file( 2146 entropy_repository_id) 2147 do_rescan = False 2148 2149 stored_digest = entropy_repository.retrieveRepositoryUpdatesDigest( 2150 entropy_repository_id) 2151 if stored_digest == -1: 2152 do_rescan = True 2153 2154 # check portage files for changes if do_rescan is still false 2155 portage_dirs_digest = "0" 2156 if not do_rescan: 2157 2158 if entropy_repository_id in \ 2159 self.__entropy_repository_treeupdate_digests: 2160 2161 portage_dirs_digest = \ 2162 self.__entropy_repository_treeupdate_digests.get( 2163 entropy_repository_id) 2164 else: 2165 2166 # grab portdir 2167 updates_dir = etpConst['systemroot'] + \ 2168 self.get_setting("PORTDIR") + "/profiles/updates" 2169 if os.path.isdir(updates_dir): 2170 # get checksum 2171 mdigest = entropy.tools.md5obj_directory(updates_dir) 2172 # also checksum etpConst['etpdatabaseupdatefile'] 2173 if os.path.isfile(repo_updates_file): 2174 f = open(repo_updates_file) 2175 block = f.read(1024) 2176 while block: 2177 mdigest.update(block) 2178 block = f.read(1024) 2179 f.close() 2180 portage_dirs_digest = mdigest.hexdigest() 2181 self.__entropy_repository_treeupdate_digests[entropy_repository_id] = \ 2182 portage_dirs_digest 2183 2184 if do_rescan or (str(stored_digest) != str(portage_dirs_digest)): 2185 2186 # force parameters 2187 entropy_repository.readOnly = False 2188 # disable upload trigger 2189 entropy_repository.set_plugin_metadata( 2190 ServerEntropyRepositoryPlugin.PLUGIN_ID, "no_upload", True) 2191 2192 # reset database tables 2193 entropy_repository.clearTreeupdatesEntries(entropy_repository_id) 2194 2195 updates_dir = etpConst['systemroot'] + \ 2196 self.get_setting("PORTDIR") + "/profiles/updates" 2197 update_files = PortageMetaphor.sort_update_files( 2198 os.listdir(updates_dir)) 2199 update_files = [os.path.join(updates_dir, x) for x in update_files] 2200 # now load actions from files 2201 update_actions = [] 2202 for update_file in update_files: 2203 f = open(update_file, "r") 2204 mycontent = f.readlines() 2205 f.close() 2206 lines = [x.strip() for x in mycontent if x.strip()] 2207 update_actions.extend(lines) 2208 2209 # add entropy packages.db.repo_updates content 2210 if os.path.isfile(repo_updates_file): 2211 f = open(repo_updates_file, "r") 2212 mycontent = f.readlines() 2213 f.close() 2214 lines = [x.strip() for x in mycontent if x.strip() and \ 2215 not x.strip().startswith("#")] 2216 update_actions.extend(lines) 2217 # now filter the required actions 2218 update_actions = entropy_repository.filterTreeUpdatesActions( 2219 update_actions) 2220 if update_actions: 2221 2222 mytxt = "%s: %s. %s %s" % ( 2223 bold(_("ATTENTION")), 2224 red(_("forcing package updates")), 2225 red(_("Syncing with")), 2226 blue(updates_dir), 2227 ) 2228 self.updateProgress( 2229 mytxt, 2230 importance = 1, 2231 type = "info", 2232 header = brown(" * ") 2233 ) 2234 # lock database 2235 if entropy_repository.get_plugins_metadata().get("lock_remote"): 2236 no_upload = entropy_repository.get_plugins_metadata().get( 2237 "no_upload") 2238 entropy_server.do_server_repository_sync_lock( 2239 entropy_repository_id, no_upload) 2240 # now run queue 2241 try: 2242 quickpkg_list = entropy_repository.runTreeUpdatesActions( 2243 update_actions) 2244 except: 2245 # destroy digest 2246 entropy_repository.setRepositoryUpdatesDigest( 2247 entropy_repository_id, "-1") 2248 raise 2249 2250 if quickpkg_list: 2251 # quickpkg package and packages owning it as a dependency 2252 try: 2253 self.__run_pkg_sync_quickpkg( 2254 entropy_server, 2255 quickpkg_list, entropy_repository, 2256 entropy_repository_id) 2257 except: 2258 entropy.tools.print_traceback() 2259 mytxt = "%s: %s: %s, %s." % ( 2260 bold(_("WARNING")), 2261 red(_("Cannot complete quickpkg for atoms")), 2262 blue(str(sorted(quickpkg_list))), 2263 _("do it manually"), 2264 ) 2265 self.updateProgress( 2266 mytxt, 2267 importance = 1, 2268 type = "warning", 2269 header = darkred(" * ") 2270 ) 2271 entropy_repository.commitChanges() 2272 2273 # store new actions 2274 entropy_repository.addRepositoryUpdatesActions( 2275 entropy_repository_id, update_actions, entropy_branch) 2276 2277 # store new digest into database 2278 entropy_repository.setRepositoryUpdatesDigest( 2279 entropy_repository_id, portage_dirs_digest) 2280 entropy_repository.commitChanges()
2281 2282 @staticmethod
2283 - def package_phases_map():
2284 """ 2285 Reimplemented from SpmPlugin class. 2286 """ 2287 return PortagePlugin._package_phases_map.copy()
2288 2289 @staticmethod
2290 - def config_files_map():
2291 """ 2292 Reimplemented from SpmPlugin class. 2293 """ 2294 return PortagePlugin._config_files_map.copy()
2295
2296 - def execute_package_phase(self, package_metadata, phase_name):
2297 """ 2298 Reimplemented from SpmPlugin class. 2299 """ 2300 portage_phase = PortagePlugin._package_phases_map[phase_name] 2301 phase_calls = { 2302 'setup': self._pkg_setup, 2303 'preinst': self._pkg_preinst, 2304 'postinst': self._pkg_postinst, 2305 'prerm': self._pkg_prerm, 2306 'postrm': self._pkg_postrm, 2307 'config': self._pkg_config, 2308 } 2309 return phase_calls[portage_phase](package_metadata)
2310
2311 - def add_installed_package(self, package_metadata):
2312 """ 2313 Reimplemented from SpmPlugin class. 2314 """ 2315 atomsfound = set() 2316 spm_package = PortagePlugin._pkg_compose_atom(package_metadata) 2317 key = entropy.tools.dep_getkey(spm_package) 2318 category = key.split("/")[0] 2319 2320 build = self.get_installed_package_build_script_path(spm_package) 2321 pkg_dir = package_metadata.get('unittest_root', '') + \ 2322 os.path.dirname(build) 2323 cat_dir = os.path.dirname(pkg_dir) 2324 2325 if os.path.isdir(cat_dir): 2326 my_findings = [os.path.join(category, x) for x in \ 2327 os.listdir(cat_dir)] 2328 # filter by key 2329 real_findings = [x for x in my_findings if \ 2330 key == entropy.tools.dep_getkey(x)] 2331 atomsfound.update(real_findings) 2332 2333 myslot = package_metadata['slot'] 2334 for xatom in atomsfound: 2335 2336 try: 2337 if self.get_installed_package_metadata(xatom, "SLOT") != myslot: 2338 continue 2339 except KeyError: # package not found?? 2340 continue 2341 2342 mybuild = self.get_installed_package_build_script_path(xatom) 2343 remove_path = os.path.dirname(mybuild) 2344 shutil.rmtree(remove_path, True) 2345 2346 # we now install it 2347 xpak_rel_path = etpConst['entropyxpakdatarelativepath'] 2348 proposed_xpak_dir = os.path.join(package_metadata['xpakpath'], 2349 xpak_rel_path) 2350 2351 counter = -1 2352 if (package_metadata['xpakstatus'] != None) and \ 2353 os.path.isdir(proposed_xpak_dir) or package_metadata['merge_from']: 2354 2355 copypath = proposed_xpak_dir 2356 if package_metadata['merge_from']: 2357 copypath = package_metadata['xpakdir'] 2358 if not os.path.isdir(copypath): 2359 return 0 2360 2361 if not os.path.isdir(cat_dir): 2362 os.makedirs(cat_dir, 0o755) 2363 if os.path.isdir(pkg_dir): 2364 shutil.rmtree(pkg_dir) 2365 2366 try: 2367 shutil.copytree(copypath, pkg_dir) 2368 except (IOError,) as e: 2369 mytxt = "%s: %s: %s: %s" % (red(_("QA")), 2370 brown(_("Cannot update Portage database to destination")), 2371 purple(pkg_dir), e,) 2372 self.updateProgress( 2373 mytxt, 2374 importance = 1, 2375 type = "warning", 2376 header = darkred(" ## ") 2377 ) 2378 2379 # this is a Unit Testing setting, so it's always not available 2380 # unless in unit testing code 2381 if not package_metadata.get('unittest_root'): 2382 try: 2383 counter = self.assign_uid_to_installed_package(spm_package) 2384 except SPMError as err: 2385 mytxt = "%s: %s [%s]" % ( 2386 brown(_("SPM uid update error")), pkg_dir, err, 2387 ) 2388 self.updateProgress( 2389 red("QA: ") + mytxt, 2390 importance = 1, 2391 type = "warning", 2392 header = darkred(" ## ") 2393 ) 2394 counter = -1 2395 2396 user_inst_source = etpConst['install_sources']['user'] 2397 if package_metadata['install_source'] != user_inst_source: 2398 # only user selected packages in Portage world file 2399 return counter 2400 2401 myslot = package_metadata['slot'][:] 2402 if (package_metadata['versiontag'] == package_metadata['slot']) \ 2403 and package_metadata['versiontag']: 2404 # usually kernel packages 2405 myslot = "0" 2406 2407 keyslot = const_convert_to_rawstring(key+":"+myslot) 2408 key = const_convert_to_rawstring(key) 2409 world_file = self.get_user_installed_packages_file() 2410 world_dir = os.path.dirname(world_file) 2411 world_atoms = set() 2412 2413 if os.access(world_file, os.R_OK) and os.path.isfile(world_file): 2414 with open(world_file, "rb") as world_f: 2415 world_atoms |= set((x.strip() for x in world_f.readlines() if \ 2416 x.strip())) 2417 2418 try: 2419 2420 if keyslot not in world_atoms and \ 2421 os.access(world_dir, os.W_OK) and \ 2422 entropy.tools.istextfile(world_file): 2423 2424 world_atoms.discard(key) 2425 world_atoms.add(keyslot) 2426 world_file_tmp = world_file+".entropy_inst" 2427 2428 newline = const_convert_to_rawstring("\n") 2429 with open(world_file_tmp, "wb") as world_f: 2430 for item in sorted(world_atoms): 2431 world_f.write( 2432 const_convert_to_rawstring(item + newline)) 2433 world_f.flush() 2434 2435 os.rename(world_file_tmp, world_file) 2436 2437 except (UnicodeDecodeError, UnicodeEncodeError,) as e: 2438 2439 mytxt = "%s: %s" % ( 2440 brown(_("Cannot update SPM installed pkgs file")), world_file, 2441 ) 2442 self.updateProgress( 2443 red("QA: ") + mytxt + ": " + repr(e), 2444 importance = 1, 2445 type = "warning", 2446 header = darkred(" ## ") 2447 ) 2448 2449 return counter
2450
2451 - def remove_installed_package(self, package_metadata):
2452 """ 2453 Reimplemented from SpmPlugin class. 2454 """ 2455 atom = entropy.tools.remove_tag(package_metadata['removeatom']) 2456 remove_build = self.get_installed_package_build_script_path(atom) 2457 remove_path = os.path.dirname(remove_build) 2458 key = entropy.tools.dep_getkey(atom) 2459 2460 others_installed = self.match_installed_package(key, match_all = True) 2461 2462 # Support for tagged packages 2463 slot = package_metadata['slot'] 2464 tag = package_metadata['versiontag'] 2465 if (tag == slot) and tag: 2466 slot = "0" 2467 2468 def do_rm_path_atomic(xpath): 2469 for my_el in os.listdir(xpath): 2470 my_el = os.path.join(xpath, my_el) 2471 try: 2472 os.remove(my_el) 2473 except OSError: 2474 pass 2475 try: 2476 os.rmdir(xpath) 2477 except OSError: 2478 pass
2479 2480 if os.path.isdir(remove_path): 2481 do_rm_path_atomic(remove_path) 2482 2483 # also remove parent directory if empty 2484 category_path = os.path.dirname(remove_path) 2485 if os.path.isdir(category_path): 2486 if not os.listdir(category_path): 2487 try: 2488 os.rmdir(category_path) 2489 except OSError: 2490 pass 2491 2492 if isinstance(others_installed, (list, set, tuple)): 2493 2494 for myatom in others_installed: 2495 2496 if myatom == atom: 2497 # do not remove self 2498 continue 2499 2500 try: 2501 myslot = self.get_installed_package_metadata(myatom, "SLOT") 2502 except KeyError: 2503 # package got removed or not available or broken 2504 continue 2505 2506 if myslot != slot: 2507 continue 2508 mybuild = self.get_installed_package_build_script_path(myatom) 2509 mydir = os.path.dirname(mybuild) 2510 if not os.path.isdir(mydir): 2511 continue 2512 do_rm_path_atomic(mydir) 2513 2514 return 0 2515 2516 # otherwise update Portage world file 2517 world_file = self.get_user_installed_packages_file() 2518 world_file_tmp = world_file + ".entropy.tmp" 2519 if os.access(world_file, os.W_OK) and os.path.isfile(world_file): 2520 2521 new = open(world_file_tmp, "wb") 2522 old = open(world_file, "rb") 2523 line = old.readline() 2524 key = const_convert_to_rawstring(key) 2525 keyslot = const_convert_to_rawstring(key+":"+slot) 2526 2527 while line: 2528 2529 if line.find(key) != -1: 2530 line = old.readline() 2531 continue 2532 if line.find(keyslot) != -1: 2533 line = old.readline() 2534 continue 2535 new.write(line) 2536 line = old.readline() 2537 2538 new.flush() 2539 new.close() 2540 old.close() 2541 os.rename(world_file_tmp, world_file) 2542 2543 return 0 2544 2545 @staticmethod
2546 - def execute_qa_tests(package_path):
2547 """ 2548 Reimplemented from SpmPlugin class. 2549 """ 2550 tests = [PortagePlugin._test_environment_bz2] 2551 msg = None 2552 exec_rc = 0 2553 for test in tests: 2554 exec_rc, msg = test(package_path) 2555 if exec_rc != 0: 2556 break 2557 return exec_rc, msg
2558 2559 @staticmethod
2560 - def _test_environment_bz2(package_path):
2561 2562 tmp_path = tempfile.mkdtemp() 2563 xpaktools.extract_xpak(package_path, tmpdir = tmp_path) 2564 if not os.listdir(tmp_path): 2565 shutil.rmtree(tmp_path) 2566 return 1, "unable to extract xpak metadata" 2567 2568 # make sure we have the environment.bz2 file to check 2569 env_file = os.path.join(tmp_path, PortagePlugin.ENV_FILE_COMP) 2570 if not (os.path.isfile(env_file) and os.access(env_file, os.R_OK)): 2571 shutil.rmtree(tmp_path) 2572 return 2, "unable to locate %s file" % ( 2573 PortagePlugin.ENV_FILE_COMP,) 2574 2575 # check if we have an alternate setting for LC* 2576 sys_settings = SystemSettings() 2577 srv_plug_id = etpConst['system_settings_plugins_ids']['server_plugin'] 2578 try: 2579 qa_langs = sys_settings[srv_plug_id]['server']['qa_langs'] 2580 except KeyError: 2581 qa_langs = ["en_US", "C"] 2582 2583 qa_rlangs = [const_convert_to_rawstring("LC_ALL="+x) for x in qa_langs] 2584 2585 # read env file 2586 bz_f = bz2.BZ2File(env_file, "r") 2587 valid_lc_all = False 2588 lc_found = False 2589 msg = None 2590 lc_all_str = const_convert_to_rawstring("LC_ALL") 2591 found_lang = None 2592 try: 2593 for line in bz_f.readlines(): 2594 if not line.startswith(lc_all_str): 2595 continue 2596 lc_found = True 2597 found_lang = line.strip() 2598 for lang in qa_rlangs: 2599 if line.startswith(lang): 2600 valid_lc_all = True 2601 break 2602 finally: 2603 bz_f.close() 2604 2605 env_rc = 0 2606 if lc_found and (not valid_lc_all): 2607 msg = "LC_ALL not set to => %s (but: %s)" % (qa_langs, found_lang,) 2608 env_rc = 1 2609 shutil.rmtree(tmp_path) 2610 2611 return env_rc, msg
2612 2613 @staticmethod
2614 - def _config_updates_make_conf(entropy_client, repo):
2615 2616 ## WARNING: it doesn't handle multi-line variables, yet. remember this. 2617 system_make_conf = PortagePlugin._config_files_map['global_make_conf'] 2618 2619 avail_data = entropy_client.SystemSettings['repositories']['available'] 2620 repo_dbpath = avail_data[repo]['dbpath'] 2621 repo_make_conf = os.path.join(repo_dbpath, 2622 os.path.basename(system_make_conf)) 2623 2624 if not (os.path.isfile(repo_make_conf) and \ 2625 os.access(repo_make_conf, os.R_OK)): 2626 return 2627 2628 make_conf_variables_check = ["CHOST"] 2629 2630 if not os.path.isfile(system_make_conf): 2631 entropy_client.updateProgress( 2632 "%s %s. %s." % ( 2633 red(system_make_conf), 2634 blue(_("does not exist")), blue(_("Overwriting")), 2635 ), 2636 importance = 1, 2637 type = "info", 2638 header = blue(" @@ ") 2639 ) 2640 if os.path.lexists(system_make_conf): 2641 shutil.move( 2642 system_make_conf, 2643 "%s.backup_%s" % (system_make_conf, 2644 entropy.tools.get_random_number(),) 2645 ) 2646 shutil.copy2(repo_make_conf, system_make_conf) 2647 2648 elif os.access(system_make_conf, os.W_OK): 2649 2650 repo_f = open(repo_make_conf, "r") 2651 sys_f = open(system_make_conf, "r") 2652 repo_make_c = [x.strip() for x in repo_f.readlines()] 2653 sys_make_c = [x.strip() for x in sys_f.readlines()] 2654 repo_f.close() 2655 sys_f.close() 2656 2657 # read repository settings 2658 repo_data = {} 2659 for setting in make_conf_variables_check: 2660 for line in repo_make_c: 2661 if line.startswith(setting+"="): 2662 # there can't be bash vars with a space 2663 # after its name on declaration 2664 repo_data[setting] = line 2665 # I don't break, because there might be 2666 # other overlapping settings 2667 2668 differences = {} 2669 # update make.conf data in memory 2670 for setting in repo_data: 2671 for idx in range(len(sys_make_c)): 2672 line = sys_make_c[idx] 2673 2674 if line.startswith(setting+"=") and \ 2675 (line != repo_data[setting]): 2676 2677 # there can't be bash vars with a 2678 # space after its name on declaration 2679 entropy_client.updateProgress( 2680 "%s: %s %s. %s." % ( 2681 red(system_make_conf), bold(repr(setting)), 2682 blue(_("variable differs")), red(_("Updating")), 2683 ), 2684 importance = 1, 2685 type = "info", 2686 header = blue(" @@ ") 2687 ) 2688 differences[setting] = repo_data[setting] 2689 line = repo_data[setting] 2690 sys_make_c[idx] = line 2691 2692 if differences: 2693 2694 entropy_client.updateProgress( 2695 "%s: %s." % ( 2696 red(system_make_conf), 2697 blue(_("updating critical variables")), 2698 ), 2699 importance = 1, 2700 type = "info", 2701 header = blue(" @@ ") 2702 ) 2703 # backup user make.conf 2704 shutil.copy2(system_make_conf, 2705 "%s.entropy_backup" % (system_make_conf,)) 2706 2707 entropy_client.updateProgress( 2708 "%s: %s." % ( 2709 red(system_make_conf), 2710 darkgreen("writing changes to disk"), 2711 ), 2712 importance = 1, 2713 type = "info", 2714 header = blue(" @@ ") 2715 ) 2716 # write to disk, safely 2717 tmp_make_conf = "%s.entropy_write" % (system_make_conf,) 2718 f = open(tmp_make_conf, "w") 2719 for line in sys_make_c: 2720 f.write(line+"\n") 2721 f.flush() 2722 f.close() 2723 shutil.move(tmp_make_conf, system_make_conf) 2724 2725 # update environment 2726 for var in differences: 2727 try: 2728 myval = '='.join(differences[var].strip().split("=")[1:]) 2729 if myval: 2730 if myval[0] in ("'", '"',): myval = myval[1:] 2731 if myval[-1] in ("'", '"',): myval = myval[:-1] 2732 except IndexError: 2733 myval = '' 2734 os.environ[var] = myval
2735 2736 @staticmethod
2737 - def _config_updates_make_profile(entropy_client, repo):
2738 2739 avail_data = entropy_client.SystemSettings['repositories']['available'] 2740 repo_dbpath = avail_data[repo]['dbpath'] 2741 profile_link = PortagePlugin._config_files_map['global_make_profile'] 2742 profile_link_name = os.path.basename(profile_link) 2743 2744 repo_make_profile = os.path.join(repo_dbpath, profile_link_name) 2745 2746 if not (os.path.isfile(repo_make_profile) and \ 2747 os.access(repo_make_profile, os.R_OK)): 2748 return 2749 2750 system_make_profile = \ 2751 PortagePlugin._config_files_map['global_make_profile'] 2752 2753 f = open(repo_make_profile, "r") 2754 repo_profile_link_data = f.readline().strip() 2755 f.close() 2756 current_profile_link = '' 2757 if os.path.islink(system_make_profile) and \ 2758 os.access(system_make_profile, os.R_OK): 2759 2760 current_profile_link = os.readlink(system_make_profile) 2761 2762 if (repo_profile_link_data != current_profile_link) and \ 2763 repo_profile_link_data: 2764 2765 entropy_client.updateProgress( 2766 "%s: %s %s. %s." % ( 2767 red(system_make_profile), blue("link"), 2768 blue(_("differs")), red(_("Updating")), 2769 ), 2770 importance = 1, 2771 type = "info", 2772 header = blue(" @@ ") 2773 ) 2774 merge_sfx = ".entropy_merge" 2775 os.symlink(repo_profile_link_data, system_make_profile+merge_sfx) 2776 if entropy.tools.is_valid_path(system_make_profile+merge_sfx): 2777 os.rename(system_make_profile+merge_sfx, system_make_profile) 2778 else: 2779 # revert change, link does not exist yet 2780 entropy_client.updateProgress( 2781 "%s: %s %s. %s." % ( 2782 red(system_make_profile), blue("new link"), 2783 blue(_("does not exist")), red(_("Reverting")), 2784 ), 2785 importance = 1, 2786 type = "info", 2787 header = blue(" @@ ") 2788 ) 2789 os.remove(system_make_profile+merge_sfx)
2790 2791 @staticmethod
2792 - def entropy_client_post_repository_update_hook(entropy_client, 2793 entropy_repository_id):
2794 2795 # are we root? 2796 if etpConst['uid'] != 0: 2797 entropy_client.updateProgress( 2798 brown(_("Skipping configuration files update, you are not root.")), 2799 importance = 1, 2800 type = "info", 2801 header = blue(" @@ ") 2802 ) 2803 return 0 2804 2805 default_repo = \ 2806 entropy_client.SystemSettings['repositories']['default_repository'] 2807 2808 if default_repo == entropy_repository_id: 2809 PortagePlugin._config_updates_make_conf(entropy_client, 2810 entropy_repository_id) 2811 PortagePlugin._config_updates_make_profile(entropy_client, 2812 entropy_repository_id) 2813 2814 return 0
2815 2816 @staticmethod
2817 - def entropy_install_setup_hook(entropy_client, package_metadata):
2818 """ 2819 Reimplemented from SpmPlugin class. 2820 """ 2821 package_metadata['xpakpath'] = etpConst['entropyunpackdir'] + \ 2822 os.path.sep + package_metadata['download'] + os.path.sep + \ 2823 etpConst['entropyxpakrelativepath'] 2824 2825 if not package_metadata['merge_from']: 2826 2827 package_metadata['xpakstatus'] = None 2828 package_metadata['xpakdir'] = package_metadata['xpakpath'] + \ 2829 os.path.sep + etpConst['entropyxpakdatarelativepath'] 2830 2831 else: 2832 2833 package_metadata['xpakstatus'] = True 2834 2835 try: 2836 try: 2837 import portage.const as pc 2838 except ImportError: 2839 import portage_const as pc 2840 portdbdir = pc.VDB_PATH 2841 except ImportError: 2842 portdbdir = 'var/db/pkg' 2843 2844 portdbdir = os.path.join(package_metadata['merge_from'], portdbdir) 2845 portdbdir = os.path.join(portdbdir, 2846 PortagePlugin._pkg_compose_atom(package_metadata)) 2847 2848 package_metadata['xpakdir'] = portdbdir 2849 2850 package_metadata['triggers']['install']['xpakdir'] = \ 2851 package_metadata['xpakdir'] 2852 2853 return 0
2854 2855 @staticmethod
2856 - def entropy_install_unpack_hook(entropy_client, package_metadata):
2857 """ 2858 Reimplemented from SpmPlugin class. 2859 """ 2860 # unpack xpak ? 2861 if os.path.isdir(package_metadata['xpakpath']): 2862 shutil.rmtree(package_metadata['xpakpath'], True) 2863 2864 # create data dir where we'll unpack the xpak 2865 xpak_dir = package_metadata['xpakpath'] + os.path.sep + \ 2866 etpConst['entropyxpakdatarelativepath'] 2867 2868 os.makedirs(xpak_dir, 0o755) 2869 2870 xpak_path = package_metadata['xpakpath'] + os.path.sep + \ 2871 etpConst['entropyxpakfilename'] 2872 2873 if not package_metadata['merge_from']: 2874 2875 if package_metadata['smartpackage']: 2876 2877 # we need to get the .xpak from database 2878 xdbconn = entropy_client.open_repository( 2879 package_metadata['repository']) 2880 xpakdata = xdbconn.retrieveXpakMetadata( 2881 package_metadata['idpackage']) 2882 if xpakdata: 2883 # save into a file 2884 with open(xpak_path, "wb") as xpak_f: 2885 xpak_f.write(xpakdata) 2886 xpak_f.flush() 2887 package_metadata['xpakstatus'] = \ 2888 xpaktools.unpack_xpak( 2889 xpak_path, 2890 xpak_dir 2891 ) 2892 else: 2893 package_metadata['xpakstatus'] = None 2894 del xpakdata 2895 2896 else: 2897 package_metadata['xpakstatus'] = xpaktools.extract_xpak( 2898 package_metadata['pkgpath'], 2899 xpak_dir 2900 ) 2901 2902 else: # merge_from 2903 2904 tolink_dir = xpak_dir 2905 if os.path.isdir(tolink_dir): 2906 shutil.rmtree(tolink_dir, True) 2907 # now link 2908 os.symlink(package_metadata['xpakdir'], tolink_dir) 2909 2910 # create fake portage ${D} linking it to imagedir 2911 portage_cpv = PortagePlugin._pkg_compose_atom(package_metadata) 2912 2913 portage_db_fakedir = os.path.join( 2914 package_metadata['unpackdir'], 2915 "portage/" + portage_cpv 2916 ) 2917 2918 os.makedirs(portage_db_fakedir, 0o755) 2919 # now link it to package_metadata['imagedir'] 2920 os.symlink(package_metadata['imagedir'], 2921 os.path.join(portage_db_fakedir, "image")) 2922 2923 return 0
2924
2925 - def _extract_elog(self, logfile):
2926 """ 2927 Extract Portage package merge log file information. 2928 2929 @param logfile: path to log file 2930 @type logfile: string 2931 @return: content of the log file 2932 @rtype: string 2933 """ 2934 2935 logline = False 2936 logoutput = [] 2937 f = open(logfile, "r") 2938 reallog = f.readlines() 2939 f.close() 2940 2941 for line in reallog: 2942 if line.startswith("INFO: postinst") or \ 2943 line.startswith("LOG: postinst"): 2944 logline = True 2945 continue 2946 # disable all the others 2947 elif line.startswith("LOG:"): 2948 logline = False 2949 continue 2950 if (logline) and (line.strip()): 2951 # trap ! 2952 logoutput.append(line.strip()) 2953 return logoutput
2954
2955 - def _get_portage_vartree(self, root = None):
2956 2957 if root is None: 2958 root = etpConst['systemroot'] + os.path.sep 2959 2960 cached = PortagePlugin.CACHE['vartree'].get(root) 2961 if cached is not None: 2962 return cached 2963 2964 try: 2965 mytree = self.portage.vartree(root=root) 2966 except Exception as e: 2967 raise SPMError("SPMError: %s: %s" % (Exception, e,)) 2968 PortagePlugin.CACHE['vartree'][root] = mytree 2969 return mytree
2970
2971 - def _get_portage_portagetree(self, root):
2972 2973 cached = PortagePlugin.CACHE['portagetree'].get(root) 2974 if cached is not None: 2975 return cached 2976 2977 try: 2978 mytree = self.portage.portagetree(root=root) 2979 except Exception as e: 2980 raise SPMError("SPMError: %s: %s" % (Exception, e,)) 2981 PortagePlugin.CACHE['portagetree'][root] = mytree 2982 return mytree
2983
2984 - def _get_portage_binarytree(self, root):
2985 2986 cached = PortagePlugin.CACHE['binarytree'].get(root) 2987 if cached is not None: 2988 return cached 2989 2990 pkgdir = root+self.portage.settings['PKGDIR'] 2991 try: 2992 mytree = self.portage.binarytree(root, pkgdir) 2993 except Exception as e: 2994 raise SPMError("SPMError: %s: %s" % (Exception, e,)) 2995 PortagePlugin.CACHE['binarytree'][root] = mytree 2996 return mytree
2997
2998 - def _get_portage_config(self, config_root, root, use_cache = True):
2999 3000 if use_cache: 3001 cached = PortagePlugin.CACHE['config'].get((config_root, root)) 3002 if cached is not None: 3003 return cached 3004 3005 try: 3006 mysettings = self.portage.config(config_root = config_root, 3007 target_root = root, 3008 config_incrementals = self.portage_const.INCREMENTALS) 3009 except Exception as e: 3010 raise SPMError("SPMError: %s: %s" % (Exception, e,)) 3011 if use_cache: 3012 PortagePlugin.CACHE['config'][(config_root, root)] = mysettings 3013 3014 return mysettings
3015
3016 - def _get_package_use_file(self):
3017 return os.path.join(self.portage_const.USER_CONFIG_PATH, 'package.use')
3018
3019 - def _handle_new_useflags(self, atom, useflags, mark):
3020 matched_atom = self.match_package(atom) 3021 if not matched_atom: 3022 return False 3023 use_file = self._get_package_use_file() 3024 3025 if not (os.path.isfile(use_file) and os.access(use_file, os.W_OK)): 3026 return False 3027 f = open(use_file, "rb") 3028 content = [x.strip() for x in f.readlines()] 3029 f.close() 3030 3031 def handle_line(line, useflags): 3032 3033 data = line.split() 3034 if len(data) < 2: 3035 return False, line 3036 3037 myatom = data[0] 3038 if matched_atom != self.match_package(myatom): 3039 return False, line 3040 3041 plus = const_convert_to_rawstring("+") 3042 minus = const_convert_to_rawstring("-") 3043 myatom = const_convert_to_rawstring(myatom) 3044 3045 flags = data[1:] 3046 base_flags = [] 3047 added_flags = [] 3048 for flag in flags: 3049 myflag = flag 3050 if myflag.startswith(plus): 3051 myflag = myflag[1:] 3052 elif myflag.startswith(minus): 3053 myflag = myflag[1:] 3054 if not myflag: 3055 continue 3056 base_flags.append(myflag) 3057 3058 for useflag in useflags: 3059 if mark+useflag in base_flags: 3060 continue 3061 added_flags.append(mark+useflag) 3062 3063 if sys.hexversion >= 0x3000000: 3064 new_line = myatom + b" " + b" ".join(flags+added_flags) 3065 else: 3066 new_line = myatom + " " + " ".join(flags+added_flags) 3067 3068 return True, new_line
3069 3070 3071 atom_found = False 3072 new_content = [] 3073 for line in content: 3074 3075 changed, elaborated_line = handle_line(line, useflags) 3076 if changed: atom_found = True 3077 new_content.append(elaborated_line) 3078 3079 if not atom_found: 3080 if sys.hexversion >= 0x3000000: 3081 myline = atom + b" " + b' '.join([mark+x for x in useflags]) 3082 else: 3083 myline = "%s %s" % (atom, ' '.join([mark+x for x in useflags])) 3084 new_content.append(myline) 3085 3086 3087 f = open(use_file+".tmp", "wb") 3088 newline = const_convert_to_rawstring("\n") 3089 for line in new_content: 3090 f.write(line + newline) 3091 f.flush() 3092 f.close() 3093 os.rename(use_file + ".tmp", use_file) 3094 return True 3095
3096 - def _unset_package_useflags(self, atom, useflags):
3097 matched_atom = self.match_package(atom) 3098 if not matched_atom: 3099 return False 3100 3101 use_file = self._get_package_use_file() 3102 if not (os.path.isfile(use_file) and os.access(use_file, os.W_OK)): 3103 return False 3104 3105 with open(use_file, "rb") as f: 3106 content = [x.strip() for x in f.readlines()] 3107 3108 new_content = [] 3109 for line in content: 3110 3111 data = line.split() 3112 if len(data) < 2: 3113 new_content.append(line) 3114 continue 3115 3116 myatom = data[0] 3117 if matched_atom != self.match_package(myatom): 3118 new_content.append(line) 3119 continue 3120 3121 plus = const_convert_to_rawstring("+") 3122 minus = const_convert_to_rawstring("-") 3123 myatom = const_convert_to_rawstring(myatom) 3124 3125 flags = data[1:] 3126 new_flags = [] 3127 for flag in flags: 3128 myflag = flag 3129 3130 if myflag.startswith(plus): 3131 myflag = myflag[1:] 3132 elif myflag.startswith(minus): 3133 myflag = myflag[1:] 3134 3135 if myflag in useflags: 3136 continue 3137 elif not flag: 3138 continue 3139 3140 new_flags.append(flag) 3141 3142 if new_flags: 3143 if sys.hexversion >= 0x3000000: 3144 new_line = myatom + b" " + b" ".join(new_flags) 3145 else: 3146 new_line = myatom + " " + " ".join(new_flags) 3147 new_content.append(new_line) 3148 3149 newline = const_convert_to_rawstring("\n") 3150 with open(use_file+".tmp", "wb") as f: 3151 for line in new_content: 3152 f.write(line + newline) 3153 f.flush() 3154 3155 os.rename(use_file + ".tmp", use_file) 3156 return True
3157
3158 - def _get_package_use_useflags(self, atom):
3159 3160 data = { 3161 'enabled': set(), 3162 'disabled': set(), 3163 } 3164 3165 matched_atom = self.match_package(atom) 3166 if not matched_atom: 3167 return data 3168 3169 use_file = self._get_package_use_file() 3170 if not (os.path.isfile(use_file) and os.access(use_file, os.W_OK)): 3171 return data 3172 3173 plus = const_convert_to_rawstring("+") 3174 minus = const_convert_to_rawstring("-") 3175 use_data = self.portage_util.grabdict(use_file) 3176 for myatom in use_data: 3177 mymatch = self.match_package(myatom) 3178 if mymatch != matched_atom: 3179 continue 3180 for flag in use_data[myatom]: 3181 if flag.startswith(minus): 3182 myflag = flag[1:] 3183 data['enabled'].discard(myflag) 3184 data['disabled'].add(myflag) 3185 else: 3186 myflag = flag 3187 if myflag.startswith(plus): 3188 myflag = myflag[1:] 3189 data['disabled'].discard(myflag) 3190 data['enabled'].add(myflag) 3191 3192 return data
3193
3194 - def _get_useflags(self):
3195 return self.portage.settings['USE']
3196
3197 - def _get_useflags_force(self):
3198 return self.portage.settings.useforce
3199
3200 - def _get_useflags_mask(self):
3201 return self.portage.settings.usemask
3202
3203 - def _resolve_enabled_useflags(self, iuse_list, use_list):
3204 use = set() 3205 use_mask = self._get_useflags_mask() 3206 use_force = self._get_useflags_force() 3207 plus = const_convert_to_rawstring("+") 3208 minus = const_convert_to_rawstring("-") 3209 for myiuse in iuse_list: 3210 if myiuse[0] in (plus, minus,): 3211 myiuse = myiuse[1:] 3212 if ((myiuse in use_list) or (myiuse in use_force)) and \ 3213 (myiuse not in use_mask): 3214 use.add(myiuse) 3215 return use
3216
3217 - def _calculate_dependencies(self, my_iuse, my_use, my_license, my_depend, 3218 my_rdepend, my_pdepend, my_provide, my_src_uri):
3219 3220 metadata = { 3221 'LICENSE': my_license, 3222 'DEPEND': my_depend, 3223 'PDEPEND': my_pdepend, 3224 'RDEPEND': my_rdepend, 3225 'PROVIDE': my_provide, 3226 'SRC_URI': my_src_uri, 3227 'USE_MASK': sorted(self._get_useflags_mask()), 3228 'USE_FORCE': sorted(self._get_useflags_force()), 3229 } 3230 3231 # generate USE flags metadata 3232 raw_use = my_use.split() 3233 enabled_use = sorted(self._resolve_enabled_useflags( 3234 my_iuse.split(), raw_use)) 3235 3236 metadata['ENABLED_USE'] = enabled_use 3237 use = raw_use + [x for x in metadata['USE_FORCE'] if x not in raw_use] 3238 metadata['USE'] = sorted([const_convert_to_unicode(x) for x in use if \ 3239 x not in metadata['USE_MASK']]) 3240 3241 for k in "LICENSE", "RDEPEND", "DEPEND", "PDEPEND", "PROVIDE", "SRC_URI": 3242 try: 3243 if k == "SRC_URI": 3244 deps = self._src_uri_paren_reduce(metadata[k]) 3245 else: 3246 deps = self._paren_reduce(metadata[k]) 3247 deps = self._use_reduce(deps, uselist = raw_use) 3248 deps = self.paren_normalize(deps) 3249 if k == "LICENSE": 3250 deps = self._paren_license_choose(deps) 3251 else: 3252 deps = self._paren_choose(deps) 3253 if k.endswith("DEPEND"): 3254 deps = self._usedeps_reduce(deps, enabled_use) 3255 deps = ' '.join(deps) 3256 except Exception as e: 3257 entropy.tools.print_traceback() 3258 self.updateProgress( 3259 darkred("%s: %s: %s :: %s") % ( 3260 _("Error calculating dependencies"), 3261 str(Exception), 3262 k, 3263 e, 3264 ), 3265 importance = 1, 3266 type = "error", 3267 header = red(" !!! ") 3268 ) 3269 deps = '' 3270 continue 3271 metadata[k] = deps 3272 return metadata
3273
3274 - def _src_uri_paren_reduce(self, src_uris):
3275 src_uris = self._paren_reduce(src_uris) 3276 newlist = [] 3277 skip_next = False 3278 for src_uri in src_uris: 3279 if skip_next: 3280 skip_next = False 3281 continue 3282 if src_uri == "->": 3283 skip_next = True 3284 continue 3285 newlist.append(src_uri) 3286 return newlist
3287
3288 - def _usedeps_reduce(self, dependencies, enabled_useflags):
3289 newlist = [] 3290 3291 def strip_use(xuse): 3292 myuse = xuse[:] 3293 if myuse[0] == "!": 3294 myuse = myuse[1:] 3295 if myuse[-1] in ("=", "?",): 3296 myuse = myuse[:-1] 3297 return myuse
3298 3299 for dependency in dependencies: 3300 use_deps = entropy.tools.dep_getusedeps(dependency) 3301 if use_deps: 3302 new_use_deps = [] 3303 for use in use_deps: 3304 """ 3305 explicitly support only specific types 3306 """ 3307 if (use[0] == "!") and (use[-1] not in ("=", "?",)): 3308 # this does not exist atm 3309 continue 3310 elif use[-1] == "=": 3311 if use[0] == "!": 3312 # foo[!bar=] means bar? ( foo[-bar] ) !bar? ( foo[bar] ) 3313 s_use = strip_use(use) 3314 if s_use in enabled_useflags: 3315 new_use_deps.append("-%s" % (s_use,)) 3316 else: 3317 new_use_deps.append(s_use) 3318 continue 3319 else: 3320 # foo[bar=] means bar? ( foo[bar] ) !bar? ( foo[-bar] ) 3321 s_use = strip_use(use) 3322 if s_use in enabled_useflags: 3323 new_use_deps.append(s_use) 3324 else: 3325 new_use_deps.append("-%s" % (s_use,)) 3326 continue 3327 elif use[-1] == "?": 3328 if use[0] == "!": 3329 # foo[!bar?] means bar? ( foo ) !bar? ( foo[-bar] ) 3330 s_use = strip_use(use) 3331 if s_use not in enabled_useflags: 3332 new_use_deps.append("-%s" % (s_use,)) 3333 continue 3334 else: 3335 # foo[bar?] means bar? ( foo[bar] ) !bar? ( foo ) 3336 s_use = strip_use(use) 3337 if s_use in enabled_useflags: 3338 new_use_deps.append(s_use) 3339 continue 3340 new_use_deps.append(use) 3341 3342 if new_use_deps: 3343 dependency = "%s[%s]" % ( 3344 entropy.tools.remove_usedeps(dependency), 3345 ','.join(new_use_deps), 3346 ) 3347 else: 3348 dependency = entropy.tools.remove_usedeps(dependency) 3349 3350 newlist.append(dependency) 3351 return newlist 3352
3353 - def _paren_reduce(self, mystr):
3354 """ 3355 3356 # deps.py -- Portage dependency resolution functions 3357 # Copyright 2003-2004 Gentoo Foundation 3358 # Distributed under the terms of the GNU General Public License v2 3359 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $ 3360 3361 Take a string and convert all paren enclosed entities into sublists, optionally 3362 futher splitting the list elements by spaces. 3363 3364 Example usage: 3365 >>> paren_reduce('foobar foo ( bar baz )',1) 3366 ['foobar', 'foo', ['bar', 'baz']] 3367 >>> paren_reduce('foobar foo ( bar baz )',0) 3368 ['foobar foo ', [' bar baz ']] 3369 3370 @param mystr: The string to reduce 3371 @type mystr: String 3372 @rtype: Array 3373 @return: The reduced string in an array 3374 """ 3375 mylist = [] 3376 while mystr: 3377 left_paren = mystr.find("(") 3378 has_left_paren = left_paren != -1 3379 right_paren = mystr.find(")") 3380 has_right_paren = right_paren != -1 3381 if not has_left_paren and not has_right_paren: 3382 freesec = mystr 3383 subsec = None 3384 tail = "" 3385 elif mystr[0] == ")": 3386 return [mylist, mystr[1:]] 3387 elif has_left_paren and not has_right_paren: 3388 raise InvalidDependString( 3389 "InvalidDependString: %s: '%s'" % (_("missing right parenthesis"), mystr,)) 3390 elif has_left_paren and left_paren < right_paren: 3391 freesec, subsec = mystr.split("(", 1) 3392 subsec, tail = self._paren_reduce(subsec) 3393 else: 3394 subsec, tail = mystr.split(")", 1) 3395 subsec = self._strip_empty(subsec.split(" ")) 3396 return [mylist+subsec, tail] 3397 mystr = tail 3398 if freesec: 3399 mylist = mylist + self._strip_empty(freesec.split(" ")) 3400 if subsec is not None: 3401 mylist = mylist + [subsec] 3402 return mylist
3403
3404 - def _strip_empty(self, myarr):
3405 """ 3406 3407 # deps.py -- Portage dependency resolution functions 3408 # Copyright 2003-2004 Gentoo Foundation 3409 # Distributed under the terms of the GNU General Public License v2 3410 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $ 3411 3412 Strip all empty elements from an array 3413 3414 @param myarr: The list of elements 3415 @type myarr: List 3416 @rtype: Array 3417 @return: The array with empty elements removed 3418 """ 3419 for x in range(len(myarr)-1, -1, -1): 3420 if not myarr[x]: 3421 del myarr[x] 3422 return myarr
3423
3424 - def _use_reduce(self, deparray, uselist = None, masklist = None, 3425 matchall = 0, excludeall = None):
3426 """ 3427 3428 # deps.py -- Portage dependency resolution functions 3429 # Copyright 2003-2004 Gentoo Foundation 3430 # Distributed under the terms of the GNU General Public License v2 3431 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $ 3432 3433 Takes a paren_reduce'd array and reduces the use? conditionals out 3434 leaving an array with subarrays 3435 3436 @param deparray: paren_reduce'd list of deps 3437 @type deparray: List 3438 @param uselist: List of use flags 3439 @type uselist: List 3440 @param masklist: List of masked flags 3441 @type masklist: List 3442 @param matchall: Resolve all conditional deps unconditionally. Used by repoman 3443 @type matchall: Integer 3444 @rtype: List 3445 @return: The use reduced depend array 3446 """ 3447 3448 if uselist is None: 3449 uselist = [] 3450 if masklist is None: 3451 masklist = [] 3452 if excludeall is None: 3453 excludeall = [] 3454 3455 # Quick validity checks 3456 for x in range(len(deparray)): 3457 if deparray[x] in ["||", "&&"]: 3458 if len(deparray) - 1 == x or not isinstance(deparray[x+1], list): 3459 mytxt = _("missing atom list in") 3460 raise InvalidDependString(deparray[x]+" "+mytxt+" \""+str(deparray)+"\"") 3461 if deparray and deparray[-1] and deparray[-1][-1] == "?": 3462 mytxt = _("Conditional without target in") 3463 raise InvalidDependString("InvalidDependString: "+mytxt+" \""+str(deparray)+"\"") 3464 3465 # This is just for use by emerge so that it can enable a backward compatibility 3466 # mode in order to gracefully deal with installed packages that have invalid 3467 # atoms or dep syntax. For backward compatibility with api consumers, strict 3468 # behavior will be explicitly enabled as necessary. 3469 _dep_check_strict = False 3470 3471 mydeparray = deparray[:] 3472 rlist = [] 3473 while mydeparray: 3474 head = mydeparray.pop(0) 3475 3476 if isinstance(head, list): 3477 additions = self._use_reduce(head, uselist, masklist, matchall, excludeall) 3478 if additions: 3479 rlist.append(additions) 3480 elif rlist and rlist[-1] == "||": 3481 #XXX: Currently some DEPEND strings have || lists without default atoms. 3482 # raise portage_exception.InvalidDependString("No default atom(s) in \""+paren_enclose(deparray)+"\"") 3483 rlist.append([]) 3484 else: 3485 if head[-1] == "?": # Use reduce next group on fail. 3486 # Pull any other use conditions and the following atom or list into a separate array 3487 newdeparray = [head] 3488 while isinstance(newdeparray[-1], const_get_stringtype()) and newdeparray[-1][-1] == "?": 3489 if mydeparray: 3490 newdeparray.append(mydeparray.pop(0)) 3491 else: 3492 raise ValueError(_("Conditional with no target")) 3493 3494 # Deprecation checks 3495 warned = 0 3496 if len(newdeparray[-1]) == 0: 3497 mytxt = "%s. (%s)" % (_("Empty target in string"), _("Deprecated"),) 3498 self.updateProgress( 3499 darkred("PortagePlugin._use_reduce(): %s" % (mytxt,)), 3500 importance = 0, 3501 type = "error", 3502 header = bold(" !!! ") 3503 ) 3504 warned = 1 3505 if len(newdeparray) != 2: 3506 mytxt = "%s. (%s)" % (_("Nested use flags without parenthesis"), _("Deprecated"),) 3507 self.updateProgress( 3508 darkred("PortagePlugin._use_reduce(): %s" % (mytxt,)), 3509 importance = 0, 3510 type = "error", 3511 header = bold(" !!! ") 3512 ) 3513 warned = 1 3514 if warned: 3515 self.updateProgress( 3516 darkred("PortagePlugin._use_reduce(): "+" ".join(map(str, [head]+newdeparray))), 3517 importance = 0, 3518 type = "error", 3519 header = bold(" !!! ") 3520 ) 3521 3522 # Check that each flag matches 3523 ismatch = True 3524 missing_flag = False 3525 for head in newdeparray[:-1]: 3526 head = head[:-1] 3527 if not head: 3528 missing_flag = True 3529 break 3530 if head.startswith("!"): 3531 head_key = head[1:] 3532 if not head_key: 3533 missing_flag = True 3534 break 3535 if not matchall and head_key in uselist or \ 3536 head_key in excludeall: 3537 ismatch = False 3538 break 3539 elif head not in masklist: 3540 if not matchall and head not in uselist: 3541 ismatch = False 3542 break 3543 else: 3544 ismatch = False 3545 if missing_flag: 3546 mytxt = _("Conditional without flag") 3547 raise InvalidDependString( 3548 "InvalidDependString: "+mytxt+": \"" + \ 3549 str([head+"?", newdeparray[-1]])+"\"") 3550 3551 # If they all match, process the target 3552 if ismatch: 3553 target = newdeparray[-1] 3554 if isinstance(target, list): 3555 additions = self._use_reduce(target, uselist, masklist, matchall, excludeall) 3556 if additions: 3557 rlist.append(additions) 3558 elif not _dep_check_strict: 3559 # The old deprecated behavior. 3560 rlist.append(target) 3561 else: 3562 mytxt = _("Conditional without parenthesis") 3563 raise InvalidDependString( 3564 "InvalidDependString: "+mytxt+": '%s?'" % head) 3565 3566 else: 3567 rlist += [head] 3568 return rlist
3569
3570 - def _paren_choose(self, dep_list):
3571 newlist = [] 3572 do_skip = False 3573 for idx in range(len(dep_list)): 3574 3575 if do_skip: 3576 do_skip = False 3577 continue 3578 3579 item = dep_list[idx] 3580 if item == "||": # or 3581 next_item = dep_list[idx+1] 3582 if not next_item: # || ( asd? ( atom ) dsa? ( atom ) ) => [] if use asd and dsa are disabled 3583 do_skip = True 3584 continue 3585 item = self._dep_or_select(next_item) # must be a list 3586 if not item: 3587 # no matches, transform to string and append, so reagent will fail 3588 newlist.append(str(next_item)) 3589 else: 3590 newlist += item 3591 do_skip = True 3592 elif isinstance(item, list): # and 3593 item = self._dep_and_select(item) 3594 newlist += item 3595 else: 3596 newlist.append(item) 3597 3598 return newlist
3599
3600 - def _dep_and_select(self, and_list):
3601 do_skip = False 3602 newlist = [] 3603 for idx in range(len(and_list)): 3604 3605 if do_skip: 3606 do_skip = False 3607 continue 3608 3609 x = and_list[idx] 3610 if x == "||": 3611 x = self._dep_or_select(and_list[idx+1]) 3612 do_skip = True 3613 if not x: 3614 x = str(and_list[idx+1]) 3615 else: 3616 newlist += x 3617 elif isinstance(x, list): 3618 x = self._dep_and_select(x) 3619 newlist += x 3620 else: 3621 newlist.append(x) 3622 3623 # now verify if all are satisfied 3624 for x in newlist: 3625 match = self.match_installed_package(x) 3626 if not match: 3627 return [] 3628 3629 return newlist
3630
3631 - def _dep_or_select(self, or_list):
3632 do_skip = False 3633 for idx in range(len(or_list)): 3634 if do_skip: 3635 do_skip = False 3636 continue 3637 x = or_list[idx] 3638 if x == "||": # or 3639 x = self._dep_or_select(or_list[idx+1]) 3640 do_skip = True 3641 elif isinstance(x, list): # and 3642 x = self._dep_and_select(x) 3643 if not x: 3644 continue 3645 # found 3646 return x 3647 else: 3648 x = [x] 3649 3650 for y in x: 3651 match = self.match_installed_package(y) 3652 if match: 3653 return [y] 3654 3655 return []
3656
3657 - def _paren_license_choose(self, dep_list):
3658 3659 newlist = set() 3660 for item in dep_list: 3661 3662 if isinstance(item, list): 3663 # match the first 3664 data = set(self._paren_license_choose(item)) 3665 newlist.update(data) 3666 else: 3667 if item not in ["||"]: 3668 newlist.add(item) 3669 3670 return list(newlist)
3671
3672 - def _get_vdb_path(self, root = None):
3673 if root is None: 3674 root = etpConst['systemroot'] + os.path.sep 3675 return os.path.join(root, self.portage_const.VDB_PATH)
3676
3677 - def _load_sets_config(self, settings, trees):
3678 3679 # from portage.const import USER_CONFIG_PATH, GLOBAL_CONFIG_PATH 3680 setconfigpaths = [os.path.join(self.portage_const.GLOBAL_CONFIG_PATH, etpConst['setsconffilename'])] 3681 setconfigpaths.append(os.path.join(settings["PORTDIR"], etpConst['setsconffilename'])) 3682 setconfigpaths += [os.path.join(x, etpConst['setsconffilename']) for x in settings["PORTDIR_OVERLAY"].split()] 3683 setconfigpaths.append(os.path.join(settings["PORTAGE_CONFIGROOT"], 3684 self.portage_const.USER_CONFIG_PATH.lstrip(os.path.sep), etpConst['setsconffilename'])) 3685 return self.portage_sets.SetConfig(setconfigpaths, settings, trees)
3686
3687 - def _get_set_config(self):
3688 # old portage 3689 if self.portage_sets == None: 3690 return 3691 myroot = etpConst['systemroot'] + os.path.sep 3692 return self._load_sets_config( 3693 self.portage.settings, 3694 self.portage.db[myroot] 3695 )
3696
3697 - def _extract_pkg_metadata_generate_extraction_dict(self):
3698 data = { 3699 'pf': { 3700 'path': PortagePlugin.xpak_entries['pf'], 3701 'critical': True, 3702 }, 3703 'chost': { 3704 'path': PortagePlugin.xpak_entries['chost'], 3705 'critical': True, 3706 }, 3707 'description': { 3708 'path': PortagePlugin.xpak_entries['description'], 3709 'critical': False, 3710 }, 3711 'homepage': { 3712 'path': PortagePlugin.xpak_entries['homepage'], 3713 'critical': False, 3714 }, 3715 'slot': { 3716 'path': PortagePlugin.xpak_entries['slot'], 3717 'critical': False, 3718 }, 3719 'cflags': { 3720 'path': PortagePlugin.xpak_entries['cflags'], 3721 'critical': False, 3722 }, 3723 'cxxflags': { 3724 'path': PortagePlugin.xpak_entries['cxxflags'], 3725 'critical': False, 3726 }, 3727 'category': { 3728 'path': PortagePlugin.xpak_entries['category'], 3729 'critical': True, 3730 }, 3731 'rdepend': { 3732 'path': PortagePlugin.xpak_entries['rdepend'], 3733 'critical': False, 3734 }, 3735 'pdepend': { 3736 'path': PortagePlugin.xpak_entries['pdepend'], 3737 'critical': False, 3738 }, 3739 'depend': { 3740 'path': PortagePlugin.xpak_entries['depend'], 3741 'critical': False, 3742 }, 3743 'use': { 3744 'path': PortagePlugin.xpak_entries['use'], 3745 'critical': False, 3746 }, 3747 'iuse': { 3748 'path': PortagePlugin.xpak_entries['iuse'], 3749 'critical': False, 3750 }, 3751 'license': { 3752 'path': PortagePlugin.xpak_entries['license'], 3753 'critical': False, 3754 }, 3755 'provide': { 3756 'path': PortagePlugin.xpak_entries['provide'], 3757 'critical': False, 3758 }, 3759 'sources': { 3760 'path': PortagePlugin.xpak_entries['src_uri'], 3761 'critical': False, 3762 }, 3763 'eclasses': { 3764 'path': PortagePlugin.xpak_entries['inherited'], 3765 'critical': False, 3766 }, 3767 'counter': { 3768 'path': PortagePlugin.xpak_entries['counter'], 3769 'critical': False, 3770 }, 3771 'keywords': { 3772 'path': PortagePlugin.xpak_entries['keywords'], 3773 'critical': False, 3774 }, 3775 'spm_phases': { 3776 'path': PortagePlugin.xpak_entries['defined_phases'], 3777 'critical': False, 3778 }, 3779 'spm_repository': { 3780 'path': PortagePlugin.xpak_entries['repository'], 3781 'critical': False, 3782 }, 3783 } 3784 return data
3785
3786 - def _extract_pkg_metadata_content(self, content_file, package_path):
3787 3788 pkg_content = {} 3789 obj_t = const_convert_to_unicode("obj") 3790 sym_t = const_convert_to_unicode("sym") 3791 dir_t = const_convert_to_unicode("dir") 3792 3793 if os.path.isfile(content_file): 3794 3795 with open(content_file, "rb") as f: 3796 content = [const_convert_to_unicode(x) for x in f.readlines()] 3797 3798 outcontent = set() 3799 for line in content: 3800 line = line.strip().split() 3801 try: 3802 datatype = line[0] 3803 datafile = line[1:] 3804 if datatype == obj_t: 3805 datafile = datafile[:-2] 3806 datafile = ' '.join(datafile) 3807 elif datatype == dir_t: 3808 datafile = ' '.join(datafile) 3809 elif datatype == sym_t: 3810 datafile = datafile[:-3] 3811 datafile = ' '.join(datafile) 3812 else: 3813 myexc = "InvalidData: %s %s. %s." % ( 3814 datafile, 3815 _("not supported"), 3816 _("Probably Portage API has changed"), 3817 ) 3818 raise InvalidData(myexc) 3819 outcontent.add((datafile, datatype)) 3820 except: 3821 pass 3822 3823 outcontent = sorted(outcontent) 3824 for datafile, datatype in outcontent: 3825 pkg_content[datafile] = datatype 3826 3827 else: 3828 3829 # CONTENTS is not generated when a package is emerged with 3830 # portage and the option -B 3831 # we have to unpack the tbz2 and generate content dict 3832 mytempdir = os.path.join(etpConst['packagestmpdir'], 3833 os.path.basename(package_path) + ".inject") 3834 if os.path.isdir(mytempdir): 3835 shutil.rmtree(mytempdir) 3836 if not os.path.isdir(mytempdir): 3837 os.makedirs(mytempdir) 3838 3839 entropy.tools.uncompress_tar_bz2(package_path, extractPath = mytempdir, 3840 catchEmpty = True) 3841 tmpdir_len = len(mytempdir) 3842 for currentdir, subdirs, files in os.walk(mytempdir): 3843 pkg_content[currentdir[tmpdir_len:]] = dir_t 3844 for item in files: 3845 item = currentdir + "/" + item 3846 if os.path.islink(item): 3847 pkg_content[item[tmpdir_len:]] = sym_t 3848 else: 3849 pkg_content[item[tmpdir_len:]] = obj_t 3850 3851 # now remove 3852 shutil.rmtree(mytempdir, True) 3853 try: 3854 os.rmdir(mytempdir) 3855 except (OSError,): 3856 pass 3857 3858 return pkg_content
3859
3860 - def _extract_pkg_metadata_needed(self, needed_file):
3861 3862 pkg_needed = set() 3863 lines = [] 3864 3865 try: 3866 f = open(needed_file, "rb") 3867 lines = [x.strip() for x in f.readlines() if x.strip()] 3868 lines = [const_convert_to_unicode(x) for x in lines] 3869 f.close() 3870 except IOError: 3871 return lines 3872 3873 for line in lines: 3874 needed = line.split() 3875 if len(needed) == 2: 3876 ownlib = needed[0] 3877 ownelf = -1 3878 if os.access(ownlib, os.R_OK): 3879 ownelf = entropy.tools.read_elf_class(ownlib) 3880 for lib in needed[1].split(","): 3881 #if lib.find(".so") != -1: 3882 pkg_needed.add((lib, ownelf)) 3883 3884 return sorted(pkg_needed)
3885
3886 - def _extract_pkg_metadata_provided_libs(self, pkg_dir, content):
3887 3888 provided_libs = set() 3889 ldpaths = entropy.tools.collect_linker_paths() 3890 for obj, ftype in list(content.items()): 3891 3892 if ftype == "dir": 3893 continue 3894 obj_dir, obj_name = os.path.split(obj) 3895 3896 if obj_dir not in ldpaths: 3897 continue 3898 3899 unpack_obj = os.path.join(pkg_dir, obj) 3900 try: 3901 os.stat(unpack_obj) 3902 except OSError: 3903 continue 3904 3905 # do not trust ftype 3906 if os.path.isdir(unpack_obj): 3907 continue 3908 try: 3909 if not entropy.tools.is_elf_file(unpack_obj): 3910 continue 3911 elf_class = entropy.tools.read_elf_class(unpack_obj) 3912 except IOError as err: 3913 self.updateProgress("%s: %s => %s" % ( 3914 _("IOError while reading"), unpack_obj, repr(err),), 3915 type = "warning") 3916 continue 3917 3918 provided_libs.add((obj_name, obj, elf_class,)) 3919 3920 return provided_libs
3921
3922 - def _extract_pkg_metadata_messages(self, log_dir, category, name, version):
3923 3924 pkg_messages = [] 3925 if not os.path.isdir(log_dir): 3926 return pkg_messages 3927 3928 elogfiles = os.listdir(log_dir) 3929 myelogfile = "%s:%s-%s" % (category, name, version,) 3930 foundfiles = [x for x in elogfiles if x.startswith(myelogfile)] 3931 if foundfiles: 3932 elogfile = foundfiles[0] 3933 if len(foundfiles) > 1: 3934 # get the latest 3935 mtimes = [] 3936 for item in foundfiles: mtimes.append((entropy.tools.get_file_unix_mtime(os.path.join(log_dir, item)), item)) 3937 mtimes = sorted(mtimes) 3938 elogfile = mtimes[-1][1] 3939 messages = self._extract_elog(os.path.join(log_dir, elogfile)) 3940 for message in messages: 3941 message = message.replace("emerge", "install") 3942 pkg_messages.append(const_convert_to_unicode(message)) 3943 3944 return pkg_messages
3945
3946 - def _extract_pkg_metadata_license_data(self, licenses_dir, license_string):
3947 3948 pkg_licensedata = {} 3949 if licenses_dir and os.path.isdir(licenses_dir): 3950 licdata = [x.strip() for x in license_string.split() if x.strip() \ 3951 and entropy.tools.is_valid_string(x.strip())] 3952 for mylicense in licdata: 3953 licfile = os.path.join(licenses_dir, mylicense) 3954 if not (os.access(licfile, os.R_OK) and os.path.isfile(licfile)): 3955 continue 3956 if not entropy.tools.istextfile(licfile): 3957 continue 3958 3959 f = open(licfile, "rb") 3960 content = const_convert_to_rawstring('') 3961 line = f.readline() 3962 while line: 3963 content += line 3964 line = f.readline() 3965 try: 3966 3967 try: 3968 pkg_licensedata[mylicense] = \ 3969 const_convert_to_unicode(content) 3970 except UnicodeDecodeError: 3971 pkg_licensedata[mylicense] = \ 3972 const_convert_to_unicode(content, 'utf-8') 3973 3974 except (UnicodeDecodeError, UnicodeEncodeError,): 3975 f.close() 3976 continue # sorry! 3977 3978 f.close() 3979 3980 return pkg_licensedata
3981 3995
3996 - def _extract_pkg_metadata_ebuild_entropy_tag(self, ebuild):
3997 search_tag = PortagePlugin._ebuild_entries['ebuild_pkg_tag_var'] 3998 ebuild_tag = '' 3999 # open in unicode fmt 4000 f = open(ebuild, "r") 4001 tags = [const_convert_to_unicode(x.strip()) for x in f.readlines() \ 4002 if x.strip() and x.strip().startswith(search_tag)] 4003 f.close() 4004 if not tags: 4005 return ebuild_tag 4006 tag = tags[-1] 4007 tag = tag.split("=")[-1].strip('"').strip("'").strip() 4008 return tag
4009