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

Source Code for Module 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  from __future__ import with_statement 
  13  import os 
  14  import sys 
  15  import shutil 
  16  import tempfile 
  17  from entropy.const import etpConst, etpUi 
  18  from entropy.exceptions import FileNotFound, SPMError, InvalidDependString, \ 
  19      InvalidData 
  20  from entropy.output import darkred, darkgreen, brown, darkblue, purple, red, \ 
  21      bold 
  22  from entropy.i18n import _ 
  23  from entropy.core.settings.base import SystemSettings 
  24  from entropy.misc import LogFile 
  25  from entropy.spm.plugins.skel import SpmPlugin 
26 27 -class PortagePackageGroups(dict):
28 """ 29 Entropy Package categories group representation 30 """
31 - def __init__(self):
32 dict.__init__(self) 33 34 data = { 35 'office': { 36 'name': _("Office"), 37 'description': _("Applications used in office environments"), 38 'categories': [u'app-office', u'app-pda', u'app-mobilephone', 39 u'app-cdr', u'app-antivirus', u'app-laptop', u'mail-', 40 ], 41 }, 42 'development': { 43 'name': _("Development"), 44 'description': _("Applications or system libraries"), 45 'categories': [u'dev-', u'sys-devel'], 46 }, 47 'system': { 48 'name': _("System"), 49 'description': _("System applications or libraries"), 50 'categories': [u'sys-'], 51 }, 52 'games': { 53 'name': _("Games"), 54 'description': _("Games, enjoy your spare time"), 55 'categories': [u'games-'], 56 }, 57 'gnome': { 58 'name': _("GNOME Desktop"), 59 'description': \ 60 _("Applications and libraries for the GNOME Desktop"), 61 'categories': [u'gnome-'], 62 }, 63 'kde': { 64 'name': _("KDE Desktop"), 65 'description': \ 66 _("Applications and libraries for the KDE Desktop"), 67 'categories': [u'kde-'], 68 }, 69 'xfce': { 70 'name': _("XFCE Desktop"), 71 'description': \ 72 _("Applications and libraries for the XFCE Desktop"), 73 'categories': [u'xfce-'], 74 }, 75 'lxde': { 76 'name': _("LXDE Desktop"), 77 'description': \ 78 _("Applications and libraries for the LXDE Desktop"), 79 'categories': [u'lxde-'], 80 }, 81 'multimedia': { 82 'name': _("Multimedia"), 83 'description': \ 84 _("Applications and libraries for Multimedia"), 85 'categories': [u'media-'], 86 }, 87 'networking': { 88 'name': _("Networking"), 89 'description': \ 90 _("Applications and libraries for Networking"), 91 'categories': [u'net-', u'www-'], 92 }, 93 'science': { 94 'name': _("Science"), 95 'description': \ 96 _("Scientific applications and libraries"), 97 'categories': [u'sci-'], 98 }, 99 'x11': { 100 'name': _("X11"), 101 'description': \ 102 _("Applications and libraries for X11"), 103 'categories': [u'x11-'], 104 }, 105 } 106 self.update(data)
107
108 -class PortagePlugin(SpmPlugin):
109 110 builtin_pkg_sets = [ 111 "system","world","installed","module-rebuild", 112 "security","preserved-rebuild","live-rebuild", 113 "downgrade","unavailable" 114 ] 115 116 package_phases_map = { 117 'setup': 'setup', 118 'preinstall': 'preinst', 119 'postinstall': 'postinst', 120 'preremove': 'prerm', 121 'postremove': 'postrm', 122 'configure': 'config', 123 } 124 125 PLUGIN_API_VERSION = 0 126 127 SUPPORTED_MATCH_TYPES = [ 128 "bestmatch-visible", "cp-list", "list-visible", "match-all", 129 "match-visible", "minimum-all", "minimum-visible" 130 ] 131
132 - class paren_normalize(list):
133 """Take a dependency structure as returned by paren_reduce or use_reduce 134 and generate an equivalent structure that has no redundant lists."""
135 - def __init__(self, src):
136 list.__init__(self) 137 self._zap_parens(src, self)
138
139 - def _zap_parens(self, src, dest, disjunction=False):
140 if not src: 141 return dest 142 i = iter(src) 143 for x in i: 144 if isinstance(x, basestring): 145 if x == '||': 146 x = self._zap_parens(i.next(), [], disjunction=True) 147 if len(x) == 1: 148 dest.append(x[0]) 149 else: 150 dest.append("||") 151 dest.append(x) 152 elif x.endswith("?"): 153 dest.append(x) 154 dest.append(self._zap_parens(i.next(), [])) 155 else: 156 dest.append(x) 157 else: 158 if disjunction: 159 x = self._zap_parens(x, []) 160 if len(x) == 1: 161 dest.append(x[0]) 162 else: 163 dest.append(x) 164 else: 165 self._zap_parens(x, dest) 166 return dest
167 168 import entropy.tools as entropyTools
169 - def init_singleton(self, OutputInterface):
170 171 mytxt = _("OutputInterface does not have an updateProgress method") 172 if not hasattr(OutputInterface,'updateProgress'): 173 raise AttributeError(mytxt) 174 elif not callable(OutputInterface.updateProgress): 175 raise AttributeError(mytxt) 176 177 # interface only needed OutputInterface functions 178 self.updateProgress = OutputInterface.updateProgress 179 self.askQuestion = OutputInterface.askQuestion 180 sys.path.append("/usr/lib/gentoolkit/pym") 181 182 # importing portage stuff 183 import portage 184 self.portage = portage 185 self.EAPI = 1 186 try: 187 import portage.const as portage_const 188 except ImportError: 189 import portage_const 190 if hasattr(portage_const, "EAPI"): 191 self.EAPI = portage_const.EAPI 192 self.portage_const = portage_const 193 194 from portage.versions import best 195 self._portage_best = best 196 197 try: 198 import portage.util as portage_util 199 except ImportError: 200 import portage_util 201 self.portage_util = portage_util 202 203 try: 204 import portage.sets as portage_sets 205 self.portage_sets = portage_sets 206 except ImportError: 207 self.portage_sets = None 208 209 try: 210 import glsa 211 self.glsa = glsa 212 except ImportError: 213 self.glsa = None 214 215 if hasattr(self.portage,'exception'): 216 self.portage_exception = self.portage.exception 217 else: # portage <2.2 workaround 218 self.portage_exception = Exception
219 220 @staticmethod
221 - def get_package_groups():
222 """ 223 Return package groups available metadata (Spm categories are grouped 224 into macro categories called "groups"). 225 """ 226 return PortagePackageGroups()
227
228 - def package_metadata_keys(self):
229 """ 230 Reimplemented from SpmPlugin class. 231 """ 232 # return what's inside vartree because it's more complete 233 dbapi = self._get_portage_vartree().dbapi 234 if hasattr(dbapi, '_aux_cache_keys'): 235 return list(dbapi._aux_cache_keys) 236 237 sys.stderr.write("PortagePlugin: missing vardb._aux_cache_keys !\n") 238 return ["CHOST", "COUNTER", "DEPEND", "DESCRIPTION", 239 "EAPI", "HOMEPAGE", "IUSE", "KEYWORDS", 240 "LICENSE", "PDEPEND", "PROPERTIES", "PROVIDE", "RDEPEND", 241 "repository", "RESTRICT" , "SLOT", "USE" 242 ]
243
244 - def get_cache_directory(self, root = None):
245 """ 246 Reimplemented from SpmPlugin class. 247 """ 248 if root is None: 249 root = etpConst['systemroot'] + os.path.sep 250 cache_path = self.portage_const.CACHE_PATH.lstrip(os.path.sep) 251 return os.path.join(root, cache_path)
252
253 - def get_package_metadata(self, package, key):
254 """ 255 Reimplemented from SpmPlugin class. 256 """ 257 return self.portage.portdb.aux_get(package, [key])[0]
258
259 - def get_package_changelog(self, package):
260 """ 261 Reimplemented from SpmPlugin class. 262 """ 263 ebuild_path = self.get_package_build_script_path(package) 264 if isinstance(ebuild_path, basestring): 265 266 clog_path = os.path.join(os.path.dirname(ebuild_path), "ChangeLog") 267 if os.access(clog_path, os.R_OK | os.F_OK): 268 with open(clog_path, "r") as clog_f: 269 return clog_f.read()
270
271 - def get_package_build_script_path(self, package):
272 """ 273 Reimplemented from SpmPlugin class. 274 """ 275 return self.portage.portdb.findname(package)
276
277 - def get_installed_package_build_script_path(self, package, root = None):
278 """ 279 Reimplemented from SpmPlugin class. 280 """ 281 return os.path.join(self._get_vdb_path(root = root), package, 282 package.split("/")[-1] + etpConst['spm']['source_build_ext'])
283
284 - def get_installed_package_metadata(self, package, key, root = None):
285 """ 286 Reimplemented from SpmPlugin class. 287 """ 288 if root is None: 289 root = etpConst['systemroot'] + os.path.sep 290 vartree = self._get_portage_vartree(root = root) 291 return vartree.dbapi.aux_get(package, [key])[0]
292
293 - def get_system_packages(self):
294 """ 295 Reimplemented from SpmPlugin class. 296 """ 297 system = [] 298 for package in self.portage.settings.packages: 299 pkgs = self.match_installed_package(package, match_all = True) 300 system.extend(pkgs) 301 system.extend(etpConst['spm']['system_packages']) 302 return system
303
304 - def get_package_categories(self):
305 """ 306 Reimplemented from SpmPlugin class. 307 """ 308 return self._get_portage_config(os.path.sep, os.path.sep).categories
309
310 - def get_package_category_description_metadata(self, category):
311 """ 312 Reimplemented from SpmPlugin class. 313 """ 314 from xml.dom import minidom 315 data = {} 316 portdir = self.portage.settings['PORTDIR'] 317 myfile = os.path.join(portdir,category,"metadata.xml") 318 if os.access(myfile,os.R_OK) and os.path.isfile(myfile): 319 doc = minidom.parse(myfile) 320 longdescs = doc.getElementsByTagName("longdescription") 321 for longdesc in longdescs: 322 data[longdesc.getAttribute("lang").strip()] = \ 323 ' '.join([x.strip() for x in \ 324 longdesc.firstChild.data.strip().split("\n")]) 325 return data
326
327 - def get_security_packages(self, security_property):
328 """ 329 Reimplemented from SpmPlugin class. 330 """ 331 if not self.glsa: 332 return [] 333 if security_property not in ['new','all','affected']: 334 return [] 335 336 glsaconfig = self.glsa.checkconfig( 337 self.portage.config(clone=self.portage.settings)) 338 completelist = self.glsa.get_glsa_list( 339 glsaconfig["GLSA_DIR"], glsaconfig) 340 341 glsalist = [] 342 if security_property == "new": 343 344 checklist = [] 345 if os.access(glsaconfig["CHECKFILE"], os.R_OK | os.F_OK): 346 with open(glsaconfig["CHECKFILE"], "r") as check_f: 347 checklist.extend([x.strip() for x in check_f.readlines()]) 348 glsalist = [x for x in completelist if x not in checklist] 349 350 elif security_property == "all": 351 glsalist = completelist 352 353 elif security_property == "affected": 354 355 # maybe this should be todolist instead 356 for glsa_item in completelist: 357 try: 358 myglsa = self.glsa.Glsa(glsa_item, glsaconfig) 359 except (self.glsa.GlsaTypeException, 360 self.glsa.GlsaFormatException,): 361 continue 362 363 if not myglsa.isVulnerable(): 364 continue 365 366 glsalist.append(glsa_item) 367 368 return glsalist
369
370 - def get_security_advisory_metadata(self, advisory_id):
371 """ 372 Reimplemented from SpmPlugin class. 373 """ 374 if not self.glsa: 375 return {} 376 377 glsaconfig = self.glsa.checkconfig( 378 self.portage.config(clone=self.portage.settings)) 379 try: 380 myglsa = self.glsa.Glsa(advisory_id, glsaconfig) 381 except (self.glsa.GlsaTypeException, self.glsa.GlsaFormatException): 382 return {} 383 384 mydict = { 385 'glsa_id': advisory_id, 386 'number': myglsa.nr, 387 'access': myglsa.access, 388 'title': myglsa.title, 389 'synopsis': myglsa.synopsis, 390 'announced': myglsa.announced, 391 'revised': myglsa.revised, 392 'bugs': myglsa.bugs, 393 'description': myglsa.description, 394 'resolution': myglsa.resolution, 395 'impact': myglsa.impact_text, 396 'impacttype': myglsa.impact_type, 397 'affected': myglsa.affected, 398 'background': myglsa.background, 399 'glsatype': myglsa.glsatype, 400 'packages': myglsa.packages, 401 'services': myglsa.services, 402 'product': myglsa.product, 403 'references': myglsa.references, 404 'workaround': myglsa.workaround, 405 } 406 407 status = "[U]" 408 if myglsa.isApplied(): 409 status = "[A]" 410 elif myglsa.isVulnerable(): 411 status = "[N]" 412 mydict['status'] = status 413 414 return mydict
415
416 - def get_setting(self, key):
417 """ 418 Reimplemented from SpmPlugin class. 419 """ 420 return self.portage.settings[key]
421
422 - def get_user_installed_packages_file(self, root = None):
423 """ 424 Reimplemented from SpmPlugin class. 425 """ 426 world_file = self.portage_const.WORLD_FILE 427 if root is None: 428 root = etpConst['systemroot'] + os.path.sep 429 return os.path.join(root, world_file)
430
431 - def get_merge_protected_paths(self):
432 """ 433 Reimplemented from SpmPlugin class. 434 """ 435 config_protect = self.portage.settings['CONFIG_PROTECT'] 436 return [os.path.expandvars(x) for x in config_protect.split()]
437
439 """ 440 Reimplemented from SpmPlugin class. 441 """ 442 config_protect = self.portage.settings['CONFIG_PROTECT_MASK'] 443 return [os.path.expandvars(x) for x in config_protect.split()]
444
445 - def get_download_mirrors(self, mirror_name):
446 """ 447 Reimplemented from SpmPlugin class. 448 """ 449 mirrors = [] 450 if self.portage.thirdpartymirrors.has_key(mirror_name): 451 mirrors.extend(self.portage.thirdpartymirrors[mirror_name]) 452 return mirrors
453
455 """ 456 Reimplemented from SpmPlugin class. 457 """ 458 root = etpConst['systemroot'] + os.path.sep 459 mydb = {} 460 mydb[root] = {} 461 mydb[root]['vartree'] = self._get_portage_vartree(root) 462 mydb[root]['porttree'] = self._get_portage_portagetree(root) 463 mydb[root]['bintree'] = self._get_portage_binarytree(root) 464 mydb[root]['virtuals'] = self.portage.settings.getvirtuals(root) 465 466 if etpUi['mute']: 467 pid = os.fork() 468 if pid > 0: 469 os.waitpid(pid, 0) 470 else: 471 log = LogFile( 472 level = etpConst['spmloglevel'], 473 filename = etpConst['spmlogfile'], 474 header = "[spm]" 475 ) 476 old_stdout = sys.stdout 477 old_stderr = sys.stderr 478 sys.stdout = log 479 sys.stderr = log 480 481 self.portage._global_updates(mydb, {}) 482 483 sys.stdout = old_stdout 484 sys.stderr = old_stderr 485 log.flush() 486 log.close() 487 os._exit(0) 488 else: 489 self.portage._global_updates(mydb, {}) # always force
490
491 - def match_package(self, package, match_type = None):
492 """ 493 Reimplemented from SpmPlugin class. 494 """ 495 if match_type is None: 496 match_type = "bestmatch-visible" 497 elif match_type not in PortagePlugin.SUPPORTED_MATCH_TYPES: 498 raise KeyError 499 500 return self.portage.portdb.xmatch(match_type, package)
501
502 - def match_installed_package(self, package, match_all = False, root = None):
503 """ 504 Reimplemented from SpmPlugin class. 505 """ 506 if root is None: 507 root = etpConst['systemroot'] + os.path.sep 508 509 vartree = self._get_portage_vartree(root = root) 510 matches = vartree.dep_match(package) or [] 511 512 if match_all: 513 return matches 514 elif matches: 515 return matches[-1] 516 return ''
517
518 - def generate_package(self, package, file_save_path):
519 """ 520 Reimplemented from SpmPlugin class. 521 """ 522 pkgcat, pkgname = package.split("/", 1) 523 if not os.path.isdir(file_save_path): 524 os.makedirs(file_save_path) 525 file_save_path += "/" + pkgname + etpConst['packagesext'] 526 dbdir = os.path.join(self._get_vdb_path(), pkgcat, pkgname) 527 528 import tarfile 529 import stat 530 trees = self.portage.db["/"] 531 vartree = trees["vartree"] 532 dblnk = self.portage.dblink(pkgcat, pkgname, "/", vartree.settings, 533 treetype="vartree", vartree=vartree) 534 dblnk.lockdb() 535 tar = tarfile.open(file_save_path, "w:bz2") 536 537 contents = dblnk.getcontents() 538 paths = sorted(contents.keys()) 539 540 for path in paths: 541 try: 542 exist = os.lstat(path) 543 except OSError: 544 continue # skip file 545 ftype = contents[path][0] 546 lpath = path 547 arcname = path[1:] 548 if 'dir' == ftype and \ 549 not stat.S_ISDIR(exist.st_mode) and \ 550 os.path.isdir(lpath): 551 lpath = os.path.realpath(lpath) 552 tarinfo = tar.gettarinfo(lpath, arcname) 553 554 if stat.S_ISREG(exist.st_mode): 555 tarinfo.mode = stat.S_IMODE(exist.st_mode) 556 tarinfo.type = tarfile.REGTYPE 557 f = open(path) 558 try: 559 tar.addfile(tarinfo, f) 560 finally: 561 f.close() 562 else: 563 tar.addfile(tarinfo) 564 565 tar.close() 566 567 # appending xpak informations 568 import entropy.xpak as xpak 569 tbz2 = xpak.tbz2(file_save_path) 570 tbz2.recompose(dbdir) 571 572 dblnk.unlockdb() 573 574 if os.access(file_save_path, os.F_OK): 575 return file_save_path 576 577 raise SPMError("SPMError: Spm:generate_package %s: %s %s" % ( 578 _("error"), 579 file_save_path, 580 _("not found"), 581 ) 582 )
583
584 - def extract_package_metadata(self, package_file):
585 """ 586 Reimplemented from SpmPlugin class. 587 """ 588 data = {} 589 system_settings = SystemSettings() 590 591 # fill package name and version 592 data['digest'] = self.entropyTools.md5sum(package_file) 593 data['signatures'] = { 594 'sha1': self.entropyTools.sha1(package_file), 595 'sha256': self.entropyTools.sha256(package_file), 596 'sha512': self.entropyTools.sha512(package_file), 597 } 598 data['datecreation'] = str(self.entropyTools.get_file_unix_mtime( 599 package_file)) 600 data['size'] = str(self.entropyTools.get_file_size(package_file)) 601 602 tmp_dir = tempfile.mkdtemp() 603 self.entropyTools.extract_xpak(package_file, tmp_dir) 604 605 # package injection status always false by default 606 # developer can change metadatum after this function 607 data['injected'] = False 608 data['branch'] = system_settings['repositories']['branch'] 609 610 portage_entries = self._extract_pkg_metadata_generate_extraction_dict() 611 for item in portage_entries: 612 613 value = '' 614 try: 615 616 item_path = os.path.join(tmp_dir, portage_entries[item]['path']) 617 with open(item_path, "r") as item_f: 618 value = item_f.readline().strip().decode( 619 'raw_unicode_escape') 620 621 except IOError: 622 if portage_entries[item]['critical']: 623 raise 624 data[item] = value 625 626 627 # workout pf 628 pf_atom = os.path.join(data['category'], data['pf']) 629 pkgcat, pkgname, pkgver, pkgrev = self.entropyTools.catpkgsplit( 630 pf_atom) 631 if pkgrev != "r0": 632 pkgver += "-%s" % (pkgrev,) 633 data['name'] = pkgname 634 data['version'] = pkgver 635 # bye bye pf 636 del data['pf'] 637 638 # setup spm_phases properly 639 spm_defined_phases_path = os.path.join(tmp_dir, 640 portage_entries['spm_phases']['path']) 641 if not os.path.isfile(spm_defined_phases_path): 642 # force to None, because metadatum can be '', which is valid 643 data['spm_phases'] = None 644 645 data['eclasses'] = set(data['eclasses'].split()) 646 try: 647 data['counter'] = int(data['counter']) 648 except ValueError: 649 # -2 values will be insterted as incremental 650 # negative values into the database 651 data['counter'] = -2 652 653 data['keywords'] = [x.strip() for x in data['keywords'].split() \ 654 if x.strip()] 655 if not data['keywords']: 656 # support for packages with no keywords 657 data['keywords'].insert(0, "") 658 659 data['keywords'] = set(data['keywords']) 660 needed_file = os.path.join(tmp_dir, 661 etpConst['spm']['xpak_entries']['needed']) 662 663 data['needed'] = self._extract_pkg_metadata_needed(needed_file) 664 data['needed_paths'] = self._extract_pkg_metadata_needed_paths( 665 data['needed']) 666 667 content_file = os.path.join(tmp_dir, 668 etpConst['spm']['xpak_entries']['contents']) 669 data['content'] = self._extract_pkg_metadata_content(content_file, 670 package_file) 671 data['disksize'] = self.entropyTools.sum_file_sizes(data['content']) 672 673 # [][][] Kernel dependent packages hook [][][] 674 data['versiontag'] = '' 675 kernelstuff = False 676 kernelstuff_kernel = False 677 for item in data['content']: 678 if item.startswith("/lib/modules/"): 679 kernelstuff = True 680 # get the version of the modules 681 kmodver = item.split("/lib/modules/")[1] 682 kmodver = kmodver.split("/")[0] 683 684 lp = kmodver.split("-")[-1] 685 if lp.startswith("r"): 686 kname = kmodver.split("-")[-2] 687 kver = kmodver.split("-")[0]+"-"+kmodver.split("-")[-1] 688 else: 689 kname = kmodver.split("-")[-1] 690 kver = kmodver.split("-")[0] 691 break 692 693 # validate the results above 694 if kernelstuff: 695 matchatom = "linux-%s-%s" % (kname,kver,) 696 if (matchatom == data['name']+"-"+data['version']): 697 kernelstuff_kernel = True 698 699 data['versiontag'] = kmodver 700 if not kernelstuff_kernel: 701 data['slot'] = kmodver # if you change this behaviour, 702 # you must change "reagent update" 703 # and "equo database gentoosync" consequentially 704 705 file_ext = etpConst['spm']['ebuild_file_extension'] 706 ebuilds_in_path = [x for x in os.listdir(tmp_dir) if \ 707 x.endswith(".%s" % (file_ext,))] 708 709 if not data['versiontag'] and ebuilds_in_path: 710 # has the user specified a custom package tag inside the ebuild 711 ebuild_path = os.path.join(tmp_dir, ebuilds_in_path[0]) 712 data['versiontag'] = self._extract_pkg_metadata_ebuild_entropy_tag( 713 ebuild_path) 714 715 data['download'] = etpConst['packagesrelativepath'] + data['branch'] \ 716 + "/" 717 data['download'] += self.entropyTools.create_package_filename( 718 data['category'], data['name'], data['version'], data['versiontag']) 719 720 data['trigger'] = "" 721 trigger_file = os.path.join(etpConst['triggersdir'], data['category'], 722 data['name'], etpConst['triggername']) 723 if os.access(trigger_file, os.F_OK | os.R_OK): 724 with open(trigger_file,"rb") as trig_f: 725 data['trigger'] = trig_f.read() 726 727 # Get Spm ChangeLog 728 pkgatom = "%s/%s-%s" % (data['category'], data['name'], 729 data['version'],) 730 try: 731 data['changelog'] = unicode(self.get_package_changelog(pkgatom), 732 'raw_unicode_escape') 733 except (UnicodeEncodeError, UnicodeDecodeError,), e: 734 sys.stderr.write("%s: %s, %s\n" % ( 735 "changelog string conversion error", e, 736 package_file,) 737 ) 738 data['changelog'] = None 739 except: 740 data['changelog'] = None 741 742 portage_metadata = self._calculate_dependencies( 743 data['iuse'], data['use'], data['license'], data['depend'], 744 data['rdepend'], data['pdepend'], data['provide'], data['sources'] 745 ) 746 747 data['provide'] = set(portage_metadata['PROVIDE'].split()) 748 data['license'] = portage_metadata['LICENSE'] 749 data['useflags'] = [] 750 for my_use in portage_metadata['USE']: 751 if my_use in portage_metadata['USE_MASK']: 752 continue 753 if my_use in portage_metadata['USE_FORCE']: 754 data['useflags'].append(my_use) 755 continue 756 if my_use in portage_metadata['ENABLED_USE']: 757 data['useflags'].append(my_use) 758 else: 759 data['useflags'].append("-"+my_use) 760 761 # useflags must be a set, as returned by entropy.db.getPackageData 762 data['useflags'] = set(data['useflags']) 763 # sources must be a set, as returned by entropy.db.getPackageData 764 data['sources'] = set(portage_metadata['SRC_URI'].split()) 765 data['dependencies'] = {} 766 767 for x in portage_metadata['RDEPEND'].split(): 768 if x.startswith("!") or (x in ("(","||",")","")): 769 continue 770 data['dependencies'][x] = etpConst['spm']['(r)depend_id'] 771 772 for x in portage_metadata['PDEPEND'].split(): 773 if x.startswith("!") or (x in ("(","||",")","")): 774 continue 775 data['dependencies'][x] = etpConst['spm']['pdepend_id'] 776 777 data['conflicts'] = [x.replace("!","") for x in \ 778 portage_metadata['RDEPEND'].split() + \ 779 portage_metadata['PDEPEND'].split() if \ 780 x.startswith("!") and not x in ("(","||",")","")] 781 782 if (kernelstuff) and (not kernelstuff_kernel): 783 # add kname to the dependency 784 kern_dep_key = u"=sys-kernel/linux-"+kname+"-"+kver+"~-1" 785 data['dependencies'][kern_dep_key] = etpConst['spm']['(r)depend_id'] 786 787 # Conflicting tagged packages support 788 # Needs Entropy Client System Settings Plugin, 789 # but since entropy.server loads entropy.client, it's completely 790 # fine as of now. 791 key = data['category'] + "/" + data['name'] 792 plug_data = etpConst['system_settings_plugins_ids'] 793 client_sysset_plg_id = plug_data['client_plugin'] 794 client_data = system_settings.get(client_sysset_plg_id, {}) 795 confl_data = None 796 797 if client_data: 798 repo_data = client_data['repositories'] 799 confl_data = repo_data['conflicting_tagged_packages'].get(key) 800 801 if confl_data: 802 for conflict in confl_data: 803 data['conflicts'].append(conflict) 804 805 # conflicts must be a set, which is what is returned 806 # by entropy.db.getPackageData 807 data['conflicts'] = set(data['conflicts']) 808 809 # Get License text if possible 810 licenses_dir = os.path.join(self.get_setting('PORTDIR'), 'licenses') 811 data['licensedata'] = self._extract_pkg_metadata_license_data( 812 licenses_dir, data['license']) 813 814 data['mirrorlinks'] = self._extract_pkg_metadata_mirror_links( 815 data['sources']) 816 817 # write only if it's a systempackage 818 data['systempackage'] = False 819 system_packages = [self.entropyTools.dep_getkey(x) for x in \ 820 self.get_system_packages()] 821 if data['category'] + "/" + data['name'] in system_packages: 822 data['systempackage'] = True 823 824 # write only if it's a systempackage 825 data['config_protect'] = ' '.join(self.get_merge_protected_paths()) 826 data['config_protect_mask'] = ' '.join( 827 self.get_merge_protected_paths_mask()) 828 829 log_dir = etpConst['logdir']+"/elog" 830 if not os.path.isdir(log_dir): os.makedirs(log_dir) 831 data['messages'] = self._extract_pkg_metadata_messages(log_dir, 832 data['category'], data['name'], data['version']) 833 834 # etpapi must be int, as returned by entropy.db.getPackageData 835 data['etpapi'] = int(etpConst['etpapi']) 836 837 # removing temporary directory 838 shutil.rmtree(tmp_dir, True) 839 if os.path.isdir(tmp_dir): 840 try: 841 os.remove(tmp_dir) 842 except OSError: 843 pass 844 845 # clear unused metadata 846 del data['use'], data['iuse'], data['depend'], data['pdepend'], \ 847 data['rdepend'] 848 849 return data
850
851 - def enable_package_compile_options(self, package, options):
852 """ 853 Reimplemented from SpmPlugin class. 854 """ 855 result = self._unset_package_useflags(package, options) 856 if not result: 857 return False 858 return self._handle_new_useflags(package, options, "")
859
860 - def disable_package_compile_options(self, package, options):
861 """ 862 Reimplemented from SpmPlugin class. 863 """ 864 result = self._unset_package_useflags(package, options) 865 if not result: 866 return False 867 return self._handle_new_useflags(package, options, "-")
868
869 - def get_package_compile_options(self, package):
870 """ 871 Reimplemented from SpmPlugin class. 872 """ 873 matched_atom = self.match_package(package) 874 if not matched_atom: 875 return {} 876 global_useflags = self._get_useflags() 877 use_force = self._get_useflags_force() 878 use_mask = self._get_useflags_mask() 879 package_use_useflags = self._get_package_use_useflags(package) 880 881 data = {} 882 data['use_force'] = use_force.copy() 883 data['use_mask'] = use_mask.copy() 884 data['global_use'] = global_useflags.split() 885 886 iuse = self.get_package_metadata(package, "IUSE") 887 if not isinstance(iuse, basestring): 888 iuse = '' 889 data['iuse'] = iuse.split()[:] 890 iuse = set() 891 for myiuse in data['iuse']: 892 if myiuse.startswith("+"): 893 myiuse = myiuse[1:] 894 iuse.add(myiuse) 895 896 use = [f for f in data['global_use'] + \ 897 list(package_use_useflags['enabled']) if (f in iuse) \ 898 and (f not in use_mask) and \ 899 (f not in package_use_useflags['disabled'])] 900 901 use_disabled = [f for f in iuse if (f not in data['global_use']) \ 902 and (f not in use_mask) and \ 903 (f not in package_use_useflags['enabled'])] 904 905 data['use'] = use[:] 906 data['use_disabled'] = use_disabled[:] 907 908 matched_slot = self.get_package_metadata(matched_atom, "SLOT") 909 try: 910 inst_key = "%s:%s" % ( 911 self.entropyTools.dep_getkey(package), 912 matched_slot, 913 ) 914 installed_atom = self.match_installed_package(inst_key) 915 except self.portage_exception: 916 installed_atom = '' 917 918 if installed_atom: 919 920 # get its useflags 921 previous_iuse = self.get_installed_package_metadata(installed_atom, 922 "IUSE").split() 923 previous_use = self.get_installed_package_metadata(installed_atom, 924 "USE").split() 925 926 new_previous_iuse = set() 927 for myuse in previous_iuse: 928 if myuse.startswith("+"): 929 myuse = myuse[1:] 930 new_previous_iuse.add(myuse) 931 previous_iuse = list(new_previous_iuse) 932 933 inst_use = [f for f in previous_iuse if (f in previous_use) and \ 934 (f not in use_mask)] 935 #inst_use_disabled = [f for f in previous_use if \ 936 # (f not in previous_iuse) and (f not in use_mask)] 937 938 # check removed use 939 use_removed = [] 940 for myuse in inst_use: 941 if myuse not in use: 942 use_removed.append(myuse) 943 944 # use not available 945 use_not_avail = [] 946 for myuse in previous_iuse: 947 if (myuse not in iuse) and (myuse not in use_removed): 948 use_not_avail.append(myuse) 949 950 # check new use 951 t_use = [] 952 for myuse in use: 953 if myuse not in inst_use: 954 myuse = "+%s*" % (myuse,) 955 t_use.append(myuse) 956 use = t_use 957 958 # check disabled use 959 t_use_disabled = [] 960 for myuse in use_disabled: 961 if myuse in inst_use: 962 if myuse in use_removed+use_not_avail: 963 continue 964 myuse = "-%s*" % (myuse,) 965 else: 966 myuse = "-%s" % (myuse,) 967 t_use_disabled.append(myuse) 968 use_disabled = t_use_disabled 969 970 for myuse in use_removed: 971 use_disabled.append("(-%s*)" % (myuse,)) 972 for myuse in use_not_avail: 973 use_disabled.append("(-%s)" % (myuse,)) 974 else: 975 use_disabled = ["-"+x for x in use_disabled] 976 977 data['use_string'] = ' '.join(sorted(use)+sorted([x for x in \ 978 use_disabled])) 979 data['use_string_colored'] = ' '.join( 980 sorted([darkred(x) for x in use if not x.startswith("+")] + \ 981 [darkgreen(x) for x in use if x.startswith("+")]) + \ 982 sorted([darkblue(x) for x in use_disabled if x.startswith("-")] + \ 983 [brown(x) for x in use_disabled if x.startswith("(") and \ 984 (x.find("*") == -1)] + \ 985 [purple(x) for x in use_disabled if x.startswith("(") and \ 986 (x.find("*") != -1)] 987 ) 988 ) 989 990 return data
991
992 - def get_installed_package_compile_options(self, package, root = None):
993 """ 994 Reimplemented from SpmPlugin class. 995 """ 996 matched_atom = self.match_installed_package(package, root = root) 997 if not matched_atom: 998 return {} 999 1000 global_use = self.get_installed_package_metadata(matched_atom, "USE", 1001 root = root) 1002 use_mask = self._get_useflags_mask() 1003 1004 data = {} 1005 data['use_mask'] = use_mask.copy() 1006 data['global_use'] = global_use.split() 1007 1008 iuse = self.get_installed_package_metadata(matched_atom, "IUSE", 1009 root = root) 1010 if not isinstance(iuse, basestring): 1011 iuse = '' 1012 data['iuse'] = iuse.split()[:] 1013 iuse = set() 1014 for myiuse in data['iuse']: 1015 if myiuse.startswith("+"): 1016 myiuse = myiuse[1:] 1017 iuse.add(myiuse) 1018 1019 use = [f for f in data['global_use'] if (f in iuse) and \ 1020 (f not in use_mask)] 1021 use_disabled = [f for f in iuse if (f not in data['global_use']) and \ 1022 (f not in use_mask)] 1023 data['use'] = use[:] 1024 data['use_disabled'] = use_disabled[:] 1025 1026 data['use_string'] = ' '.join(sorted(use)+sorted([x for x in \ 1027 use_disabled])) 1028 data['use_string_colored'] = ' '.join( 1029 sorted([darkred(x) for x in use if not x.startswith("+")] + \ 1030 [darkgreen(x) for x in use if x.startswith("+")]) + \ 1031 sorted([darkblue(x) for x in use_disabled if x.startswith("-")] + \ 1032 [brown(x) for x in use_disabled if x.startswith("(") and \ 1033 (x.find("*") == -1)] + \ 1034 [purple(x) for x in use_disabled if x.startswith("(") and \ 1035 (x.find("*") != -1)] 1036 ) 1037 ) 1038 return data
1039
1040 - def get_installed_package_content(self, package, root = None):
1041 """ 1042 Reimplemented from SpmPlugin class. 1043 """ 1044 if root is None: 1045 root = etpConst['systemroot'] + os.path.sep 1046 mytree = self._get_portage_vartree(root) 1047 1048 cat, pkgv = package.split("/") 1049 return sorted(self.portage.dblink(cat, pkgv, root, 1050 self.portage.settings).getcontents())
1051
1052 - def get_packages(self, categories = None, filter_reinstalls = True):
1053 """ 1054 Reimplemented from SpmPlugin class. 1055 """ 1056 if categories is None: 1057 categories = [] 1058 1059 root = etpConst['systemroot'] + os.path.sep 1060 mysettings = self._get_portage_config(os.path.sep, root) 1061 portdb = self.portage.portdbapi(mysettings["PORTDIR"], 1062 mysettings = mysettings) 1063 1064 cps = portdb.cp_all() 1065 visibles = set() 1066 for cp in cps: 1067 if categories and cp.split("/")[0] not in categories: 1068 continue 1069 1070 # get slots 1071 slots = set() 1072 atoms = self.match_package(cp, match_type = "match-visible") 1073 if atoms: 1074 for atom in atoms: 1075 slots.add(portdb.aux_get(atom, ["SLOT"])[0]) 1076 for slot in slots: 1077 visibles.add(cp+":"+slot) 1078 1079 # now match visibles 1080 available = set() 1081 for visible in visibles: 1082 1083 match = self.match_package(visible) 1084 if not match: 1085 continue 1086 1087 if filter_reinstalls: 1088 installed = self.match_installed_package(visible) 1089 if installed != match: 1090 available.add(match) 1091 else: 1092 available.add(match) 1093 1094 return available
1095
1096 - def get_installed_packages(self, categories = None, root = None):
1097 """ 1098 Reimplemented from SpmPlugin class. 1099 """ 1100 vartree = self._get_portage_vartree(root = root) 1101 packages = vartree.dbapi.cpv_all() 1102 if not categories: 1103 return packages 1104 1105 def catfilter(pkg): 1106 if pkg.split("/", 1)[0] in categories: 1107 return True 1108 return False
1109 1110 return filter(catfilter, packages)
1111
1112 - def get_package_sets(self, builtin_sets):
1113 """ 1114 Reimplemented from SpmPlugin class. 1115 """ 1116 config = self._get_set_config() 1117 if config == None: 1118 return {} 1119 1120 mysets = config.getSets() 1121 if not builtin_sets: 1122 builtin_pkg_sets = [x for x in PortagePlugin.builtin_pkg_sets if \ 1123 x in mysets] 1124 for pkg_set in builtin_pkg_sets: 1125 mysets.pop(pkg_set) 1126 1127 return dict((x, y.getAtoms(),) for x, y in mysets.items())
1128
1129 - def assign_uid_to_installed_package(self, package, root = None):
1130 """ 1131 Reimplemented from SpmPlugin class. 1132 """ 1133 if root is None: 1134 root = etpConst['systemroot'] + os.path.sep 1135 1136 vartree = self._get_portage_vartree(root) 1137 dbbuild = self.get_installed_package_build_script_path(package, 1138 root = root) 1139 1140 counter_dir = os.path.dirname(dbbuild) 1141 counter_name = etpConst['spm']['xpak_entries']['counter'] 1142 counter_path = os.path.join(counter_dir, counter_name) 1143 1144 if not os.access(counter_dir, os.W_OK): 1145 raise SPMError("SPM package directory not found") 1146 1147 with open(counter_path, "w") as count_f: 1148 new_counter = vartree.dbapi.counter_tick(root, mycpv = package) 1149 count_f.write(str(new_counter)) 1150 count_f.flush() 1151 1152 return new_counter
1153
1154 - def search_paths_owners(self, paths, exact_match = True):
1155 """ 1156 Reimplemented from SpmPlugin class. 1157 """ 1158 if not isinstance(paths, (list, set, frozenset, dict, tuple,)): 1159 raise AttributeError("iterable needed") 1160 root = etpConst['systemroot'] + os.path.sep 1161 mytree = self._get_portage_vartree(root) 1162 packages = mytree.dbapi.cpv_all() 1163 matches = {} 1164 1165 for package in packages: 1166 cat, pkgv = package.split("/") 1167 content = self.portage.dblink(cat, pkgv, root, 1168 self.portage.settings).getcontents() 1169 1170 if exact_match: 1171 for filename in paths: 1172 if filename in content: 1173 myslot = self.get_installed_package_metadata(package, 1174 "SLOT") 1175 obj = matches.setdefault((package, myslot,), set()) 1176 obj.add(filename) 1177 else: 1178 for filename in paths: 1179 for myfile in content: 1180 if myfile.find(filename) == -1: 1181 continue 1182 myslot = self.get_installed_package_metadata(package, 1183 "SLOT") 1184 obj = matches.setdefault((package, myslot,), set()) 1185 obj.add(filename) 1186 1187 return matches
1188
1189 - def _portage_doebuild(self, myebuild, mydo, tree, cpv, 1190 portage_tmpdir = None, licenses = None):
1191 # myebuild = path/to/ebuild.ebuild with a valid unpacked xpak metadata 1192 # tree = "bintree" 1193 # cpv = atom 1194 # mydbapi = portage.fakedbapi(settings=portage.settings) 1195 # vartree = portage.vartree(root=myroot) 1196 1197 if licenses is None: 1198 licenses = [] 1199 1200 oldsystderr = sys.stderr 1201 dev_null = open("/dev/null","w") 1202 if not etpUi['debug']: 1203 sys.stderr = dev_null 1204 1205 ### SETUP ENVIRONMENT 1206 # if mute, supress portage output 1207 domute = False 1208 if etpUi['mute']: 1209 domute = True 1210 oldsysstdout = sys.stdout 1211 sys.stdout = dev_null 1212 1213 root = etpConst['systemroot'] + os.path.sep 1214 1215 # old way to avoid loop of deaths for entropy portage hooks 1216 os.environ["SKIP_EQUO_SYNC"] = "1" 1217 1218 # load metadata 1219 myebuilddir = os.path.dirname(myebuild) 1220 keys = self.portage.auxdbkeys 1221 metadata = {} 1222 1223 for key in keys: 1224 mykeypath = os.path.join(myebuilddir,key) 1225 if os.path.isfile(mykeypath) and os.access(mykeypath,os.R_OK): 1226 f = open(mykeypath,"r") 1227 metadata[key] = f.readline().strip() 1228 f.close() 1229 1230 ### END SETUP ENVIRONMENT 1231 1232 # find config 1233 mysettings = self._get_portage_config(os.path.sep, root) 1234 mysettings['EBUILD_PHASE'] = mydo 1235 1236 # crappy, broken, ebuilds, put accept_license eutils call 1237 # in pkg_setup, when environment variables are not setup yet 1238 # WARNING WARNING WARNING: 1239 # if some other hook fails for other reasons, it's because 1240 # it may miss env variable here. 1241 mysettings['LICENSE'] = str(' '.join(licenses)) 1242 if licenses: 1243 # we already do this early 1244 mysettings["ACCEPT_LICENSE"] = mysettings['LICENSE'] 1245 mysettings.backup_changes("ACCEPT_LICENSE") 1246 1247 mysettings['EAPI'] = "0" 1248 if metadata.has_key('EAPI'): 1249 mysettings['EAPI'] = metadata['EAPI'] 1250 1251 # workaround for scripts asking for user intervention 1252 mysettings['ROOT'] = root 1253 mysettings['CD_ROOT'] = "/tmp" 1254 1255 mysettings.backup_changes("EAPI") 1256 mysettings.backup_changes("LICENSE") 1257 mysettings.backup_changes("EBUILD_PHASE") 1258 mysettings.backup_changes("ROOT") 1259 mysettings.backup_changes("CD_ROOT") 1260 1261 try: # this is a >portage-2.1.4_rc11 feature 1262 mysettings._environ_whitelist = set(mysettings._environ_whitelist) 1263 # put our vars into whitelist 1264 mysettings._environ_whitelist.add("SKIP_EQUO_SYNC") 1265 mysettings._environ_whitelist.add("ACCEPT_LICENSE") 1266 mysettings._environ_whitelist.add("CD_ROOT") 1267 mysettings._environ_whitelist.add("ROOT") 1268 mysettings._environ_whitelist = frozenset(mysettings._environ_whitelist) 1269 except (AttributeError,): 1270 self.log_message(self.entropyTools.get_traceback()) 1271 1272 cpv = str(cpv) 1273 mysettings.setcpv(cpv) 1274 portage_tmpdir_created = False # for pkg_postrm, pkg_prerm 1275 1276 if portage_tmpdir is None: 1277 portage_tmpdir = self.entropyTools.get_random_temp_file() 1278 1279 if portage_tmpdir: 1280 if not os.path.isdir(portage_tmpdir): 1281 os.makedirs(portage_tmpdir) 1282 portage_tmpdir_created = True 1283 mysettings['PORTAGE_TMPDIR'] = str(portage_tmpdir) 1284 mysettings.backup_changes("PORTAGE_TMPDIR") 1285 1286 # create FAKE ${PORTDIR} directory and licenses subdir 1287 portdir = os.path.join(portage_tmpdir, "portdir") 1288 portdir_lic = os.path.join(portdir, "licenses") 1289 if not os.path.isdir(portdir): 1290 os.mkdir(portdir) # portage_tmpdir must be available! 1291 # create licenses subdir 1292 if not os.path.isdir(portdir_lic): 1293 os.mkdir(portdir_lic) 1294 1295 # set fake PORTDIR 1296 old_portdir = mysettings["PORTDIR"][:] 1297 mysettings["PORTDIR"] = portdir 1298 mysettings.backup_changes("PORTDIR") 1299 1300 ### WORKAROUND for buggy check_license() in eutils.eclass 1301 ### that looks for file availability before considering 1302 ### ACCEPT_LICENSE 1303 for lic in licenses: 1304 lic_path = os.path.join(portdir_lic, lic) 1305 if not os.access(lic_path, os.F_OK): 1306 lic_f = open(lic_path, "w") 1307 lic_f.close() 1308 1309 mydbapi = self.portage.fakedbapi(settings=mysettings) 1310 mydbapi.cpv_inject(cpv, metadata = metadata) 1311 1312 # cached vartree class 1313 vartree = self._get_portage_vartree(root = root) 1314 1315 try: 1316 rc = self.portage.doebuild( 1317 myebuild = str(myebuild), 1318 mydo = str(mydo), 1319 myroot = root, 1320 tree = tree, 1321 mysettings = mysettings, 1322 mydbapi = mydbapi, 1323 vartree = vartree, 1324 use_cache = 0 1325 ) 1326 except: 1327 self.log_message(self.entropyTools.get_traceback()) 1328 raise 1329 1330 # if mute, restore old stdout/stderr 1331 if domute: 1332 sys.stdout = oldsysstdout 1333 1334 sys.stderr = oldsystderr 1335 dev_null.close() 1336 1337 if portage_tmpdir_created: 1338 shutil.rmtree(portage_tmpdir, True) 1339 1340 # reset PORTDIR back to its old path 1341 # for security ! 1342 mysettings["PORTDIR"] = old_portdir 1343 mysettings.backup_changes("PORTDIR") 1344 1345 del mydbapi 1346 del metadata 1347 del keys 1348 return rc
1349
1350 - def execute_package_phase(self, package, build_script_path, phase_name, 1351 work_dir = None, licenses_accepted = None):
1352 """ 1353 Reimplemented from SpmPlugin class. 1354 """ 1355 if licenses_accepted is None: 1356 licenses_accepted = [] 1357 1358 portage_phase = PortagePlugin.package_phases_map[phase_name] 1359 return self._portage_doebuild(build_script_path, portage_phase, 1360 "bintree", package, work_dir, licenses_accepted)
1361
1362 - def add_installed_package(self, package_metadata):
1363 """ 1364 Reimplemented from SpmPlugin class. 1365 """ 1366 atomsfound = set() 1367 category = package_metadata['category'] 1368 key = category + "/" + package_metadata['name'] 1369 spm_package = key + "-" + package_metadata['version'] 1370 1371 build = self.get_installed_package_build_script_path(spm_package) 1372 pkg_dir = os.path.dirname(build) 1373 cat_dir = os.path.dirname(pkg_dir) 1374 1375 if os.path.isdir(cat_dir): 1376 my_findings = [os.path.join(category, x) for x in \ 1377 os.listdir(cat_dir)] 1378 # filter by key 1379 real_findings = [x for x in my_findings if \ 1380 key == self.entropyTools.dep_getkey(x)] 1381 atomsfound.update(real_findings) 1382 1383 myslot = package_metadata['slot'] 1384 for xatom in atomsfound: 1385 1386 if self.get_installed_package_metadata(xatom, "SLOT") != myslot: 1387 continue 1388 1389 mybuild = self.get_installed_package_build_script_path(xatom) 1390 remove_path = os.path.dirname(mybuild) 1391 shutil.rmtree(remove_path, True) 1392 1393 # we now install it 1394 xpak_rel_path = etpConst['entropyxpakdatarelativepath'] 1395 proposed_xpak_dir = os.path.join(package_metadata['xpakpath'], 1396 xpak_rel_path) 1397 1398 counter = -1 1399 if (package_metadata['xpakstatus'] != None) and \ 1400 os.path.isdir(proposed_xpak_dir) or package_metadata['merge_from']: 1401 1402 copypath = proposed_xpak_dir 1403 if package_metadata['merge_from']: 1404 copypath = package_metadata['xpakdir'] 1405 if not os.path.isdir(copypath): 1406 return 0 1407 1408 if not os.path.isdir(cat_dir): 1409 os.makedirs(cat_dir, 0755) 1410 if os.path.isdir(pkg_dir): 1411 shutil.rmtree(pkg_dir) 1412 1413 try: 1414 shutil.copytree(copypath, pkg_dir) 1415 except (IOError,), e: 1416 mytxt = "%s: %s: %s: %s" % (red(_("QA")), 1417 brown(_("Cannot update Portage database to destination")), 1418 purple(pkg_dir),e,) 1419 self.updateProgress( 1420 mytxt, 1421 importance = 1, 1422 type = "warning", 1423 header = darkred(" ## ") 1424 ) 1425 1426 try: 1427 counter = self.assign_uid_to_installed_package(spm_package) 1428 except SPMError, err: 1429 mytxt = "%s: %s [%s]" % ( 1430 brown(_("SPM uid update error")), pkg_dir, err, 1431 ) 1432 self.updateProgress( 1433 red("QA: ") + mytxt, 1434 importance = 1, 1435 type = "warning", 1436 header = darkred(" ## ") 1437 ) 1438 counter = -1 1439 1440 user_inst_source = etpConst['install_sources']['user'] 1441 if package_metadata['install_source'] != user_inst_source: 1442 # only user selected packages in Portage world file 1443 return counter 1444 1445 myslot = package_metadata['slot'][:] 1446 if (package_metadata['versiontag'] == package_metadata['slot']) \ 1447 and package_metadata['versiontag']: 1448 # usually kernel packages 1449 myslot = "0" 1450 1451 keyslot = key+":"+myslot 1452 world_file = self.get_user_installed_packages_file() 1453 world_dir = os.path.dirname(world_file) 1454 world_atoms = set() 1455 1456 if os.access(world_file, os.R_OK | os.F_OK): 1457 with open(world_file, "r") as world_f: 1458 world_atoms |= set((x.strip() for x in world_f.readlines() if \ 1459 x.strip())) 1460 1461 try: 1462 1463 if keyslot not in world_atoms and \ 1464 os.access(world_dir, os.W_OK) and \ 1465 self.entropyTools.istextfile(world_file): 1466 1467 world_atoms.discard(key) 1468 world_atoms.add(keyslot) 1469 world_file_tmp = world_file+".entropy_inst" 1470 1471 with open(world_file_tmp, "w") as world_f: 1472 for item in sorted(world_atoms): 1473 world_f.write(item + "\n") 1474 world_f.flush() 1475 1476 os.rename(world_file_tmp, world_file) 1477 1478 except (UnicodeDecodeError, UnicodeEncodeError,), e: 1479 1480 mytxt = "%s: %s" % ( 1481 brown(_("Cannot update SPM installed pkgs file")), world_file, 1482 ) 1483 self.updateProgress( 1484 red("QA: ") + mytxt + ": " + unicode(e), 1485 importance = 1, 1486 type = "warning", 1487 header = darkred(" ## ") 1488 ) 1489 1490 return counter
1491
1492 - def remove_installed_package(self, package_metadata):
1493 """ 1494 Reimplemented from SpmPlugin class. 1495 """ 1496 atom = self.entropyTools.remove_tag(package_metadata['removeatom']) 1497 remove_build = self.get_installed_package_build_script_path(atom) 1498 remove_path = os.path.dirname(remove_build) 1499 key = self.entropyTools.dep_getkey(atom) 1500 1501 others_installed = self.match_installed_package(key, match_all = True) 1502 if atom in others_installed: 1503 others_installed.remove(atom) 1504 1505 # Support for tagged packages 1506 slot = package_metadata['slot'] 1507 tag = package_metadata['versiontag'] 1508 if (tag == slot) and tag: 1509 slot = "0" 1510 1511 def do_rm_path_atomic(xpath): 1512 for my_el in os.listdir(xpath): 1513 my_el = os.path.join(xpath, my_el) 1514 try: 1515 os.remove(my_el) 1516 except OSError: 1517 pass 1518 try: 1519 os.rmdir(xpath) 1520 except OSError: 1521 pass
1522 1523 if os.path.isdir(remove_path): 1524 do_rm_path_atomic(remove_path) 1525 1526 # also remove parent directory if empty 1527 category_path = os.path.dirname(remove_path) 1528 if os.path.isdir(category_path): 1529 if not os.listdir(category_path): 1530 try: 1531 os.rmdir(category_path) 1532 except OSError: 1533 pass 1534 1535 if others_installed: 1536 1537 for myatom in others_installed: 1538 myslot = self.get_installed_package_metadata(myatom, "SLOT") 1539 if myslot != slot: 1540 continue 1541 mybuild = self.get_installed_package_build_script_path(myatom) 1542 mydir = os.path.dirname(mybuild) 1543 if not os.path.isdir(mydir): 1544 continue 1545 do_rm_path_atomic(mydir) 1546 1547 return 0 1548 1549 # otherwise update Portage world file 1550 world_file = self.get_user_installed_packages_file() 1551 world_file_tmp = world_file + ".entropy.tmp" 1552 if os.access(world_file, os.W_OK | os.F_OK): 1553 1554 new = open(world_file_tmp,"w") 1555 old = open(world_file,"r") 1556 line = old.readline() 1557 1558 while line: 1559 1560 if line.find(key) != -1: 1561 line = old.readline() 1562 continue 1563 if line.find(key+":"+slot) != -1: 1564 line = old.readline() 1565 continue 1566 new.write(line) 1567 line = old.readline() 1568 1569 new.flush() 1570 new.close() 1571 old.close() 1572 os.rename(world_file_tmp, world_file) 1573 1574 return 0 1575
1576 - def configure_installed_package(self, package_metadata):
1577 """ 1578 Reimplemented from SpmPlugin class. 1579 """ 1580 atom = package_metadata['key'] + "-" + package_metadata['version'] 1581 myebuild = self.get_installed_package_build_script_path(atom) 1582 1583 if not os.access(myebuild, os.R_OK | os.F_OK): 1584 # cannot find ebuild ! ouch! 1585 return 2 1586 1587 try: 1588 rc = self.execute_package_phase(atom, myebuild, 1589 "configure", 1590 licenses_accepted = package_metadata['accept_license'] 1591 ) 1592 if rc == 1: 1593 return 3 1594 1595 except Exception, err: 1596 1597 self.entropyTools.print_traceback() 1598 mytxt = "%s: %s %s." % ( 1599 bold(_("QA")), 1600 brown(_("Cannot run SPM configure phase for")), 1601 bold(str(atom)), 1602 ) 1603 mytxt2 = "%s: %s, %s" % ( 1604 bold(_("Error")), 1605 type(Exception), 1606 err, 1607 ) 1608 for txt in (mytxt, mytxt2,): 1609 self.updateProgress( 1610 txt, 1611 importance = 0, 1612 header = red(" ## ") 1613 ) 1614 return 1 1615 1616 return 0
1617
1618 - def _get_portage_vartree(self, root = None):
1619 1620 if root is None: 1621 root = etpConst['systemroot'] + os.path.sep 1622 1623 if not etpConst['spm']['cache'].has_key('portage'): 1624 etpConst['spm']['cache']['portage'] = {} 1625 if not etpConst['spm']['cache']['portage'].has_key('vartree'): 1626 etpConst['spm']['cache']['portage']['vartree'] = {} 1627 1628 cached = etpConst['spm']['cache']['portage']['vartree'].get(root) 1629 if cached != None: 1630 return cached 1631 1632 try: 1633 mytree = self.portage.vartree(root=root) 1634 except Exception, e: 1635 raise SPMError("SPMError: %s: %s" % (Exception,e,)) 1636 etpConst['spm']['cache']['portage']['vartree'][root] = mytree 1637 return mytree
1638
1639 - def _get_portage_portagetree(self, root):
1640 1641 if not etpConst['spm']['cache'].has_key('portage'): 1642 etpConst['spm']['cache']['portage'] = {} 1643 if not etpConst['spm']['cache']['portage'].has_key('portagetree'): 1644 etpConst['spm']['cache']['portage']['portagetree'] = {} 1645 1646 cached = etpConst['spm']['cache']['portage']['portagetree'].get(root) 1647 if cached != None: 1648 return cached 1649 1650 try: 1651 mytree = self.portage.portagetree(root=root) 1652 except Exception, e: 1653 raise SPMError("SPMError: %s: %s" % (Exception,e,)) 1654 etpConst['spm']['cache']['portage']['portagetree'][root] = mytree 1655 return mytree
1656
1657 - def _get_portage_binarytree(self, root):
1658 1659 if not etpConst['spm']['cache'].has_key('portage'): 1660 etpConst['spm']['cache']['portage'] = {} 1661 if not etpConst['spm']['cache']['portage'].has_key('binarytree'): 1662 etpConst['spm']['cache']['portage']['binarytree'] = {} 1663 1664 cached = etpConst['spm']['cache']['portage']['binarytree'].get(root) 1665 if cached != None: 1666 return cached 1667 1668 pkgdir = root+self.portage.settings['PKGDIR'] 1669 try: 1670 mytree = self.portage.binarytree(root,pkgdir) 1671 except Exception, e: 1672 raise SPMError("SPMError: %s: %s" % (Exception,e,)) 1673 etpConst['spm']['cache']['portage']['binarytree'][root] = mytree 1674 return mytree
1675
1676 - def _get_portage_config(self, config_root, root, use_cache = True):
1677 1678 if use_cache: 1679 if not etpConst['spm']['cache'].has_key('portage'): 1680 etpConst['spm']['cache']['portage'] = {} 1681 if not etpConst['spm']['cache']['portage'].has_key('config'): 1682 etpConst['spm']['cache']['portage']['config'] = {} 1683 1684 cached = etpConst['spm']['cache']['portage']['config'].get((config_root,root)) 1685 if cached != None: 1686 return cached 1687 1688 try: 1689 mysettings = self.portage.config(config_root = config_root, target_root = root, config_incrementals = self.portage_const.INCREMENTALS) 1690 except Exception, e: 1691 raise SPMError("SPMError: %s: %s" % (Exception,e,)) 1692 if use_cache: 1693 etpConst['spm']['cache']['portage']['config'][(config_root,root)] = mysettings 1694 return mysettings
1695
1696 - def _get_package_use_file(self):
1697 return os.path.join(self.portage_const.USER_CONFIG_PATH,'package.use')
1698
1699 - def _handle_new_useflags(self, atom, useflags, mark):
1700 matched_atom = self.match_package(atom) 1701 if not matched_atom: 1702 return False 1703 use_file = self._get_package_use_file() 1704 1705 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)): 1706 return False 1707 f = open(use_file,"r") 1708 content = [x.strip() for x in f.readlines()] 1709 f.close() 1710 1711 def handle_line(line, useflags): 1712 1713 data = line.split() 1714 if len(data) < 2: 1715 return False, line 1716 1717 myatom = data[0] 1718 if matched_atom != self.match_package(myatom): 1719 return False, line 1720 1721 flags = data[1:] 1722 base_flags = [] 1723 added_flags = [] 1724 for flag in flags: 1725 myflag = flag 1726 if myflag.startswith("+"): 1727 myflag = myflag[1:] 1728 elif myflag.startswith("-"): 1729 myflag = myflag[1:] 1730 if not myflag: 1731 continue 1732 base_flags.append(myflag) 1733 1734 for useflag in useflags: 1735 if mark+useflag in base_flags: 1736 continue 1737 added_flags.append(mark+useflag) 1738 1739 new_line = "%s %s" % (myatom, ' '.join(flags+added_flags)) 1740 return True, new_line
1741 1742 1743 atom_found = False 1744 new_content = [] 1745 for line in content: 1746 1747 changed, elaborated_line = handle_line(line, useflags) 1748 if changed: atom_found = True 1749 new_content.append(elaborated_line) 1750 1751 if not atom_found: 1752 myline = "%s %s" % (atom, ' '.join([mark+x for x in useflags])) 1753 new_content.append(myline) 1754 1755 1756 f = open(use_file+".tmp","w") 1757 for line in new_content: 1758 f.write(line+"\n") 1759 f.flush() 1760 f.close() 1761 os.rename(use_file+".tmp", use_file) 1762 return True 1763
1764 - def _unset_package_useflags(self, atom, useflags):
1765 matched_atom = self.match_package(atom) 1766 if not matched_atom: 1767 return False 1768 1769 use_file = self._get_package_use_file() 1770 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)): 1771 return False 1772 1773 with open(use_file, "r") as f: 1774 content = [x.strip() for x in f.readlines()] 1775 1776 new_content = [] 1777 for line in content: 1778 1779 data = line.split() 1780 if len(data) < 2: 1781 new_content.append(line) 1782 continue 1783 1784 myatom = data[0] 1785 if matched_atom != self.match_package(myatom): 1786 new_content.append(line) 1787 continue 1788 1789 flags = data[1:] 1790 new_flags = [] 1791 for flag in flags: 1792 myflag = flag 1793 1794 if myflag.startswith("+"): 1795 myflag = myflag[1:] 1796 elif myflag.startswith("-"): 1797 myflag = myflag[1:] 1798 1799 if myflag in useflags: 1800 continue 1801 elif not flag: 1802 continue 1803 1804 new_flags.append(flag) 1805 1806 if new_flags: 1807 new_line = "%s %s" % (myatom, ' '.join(new_flags)) 1808 new_content.append(new_line) 1809 1810 with open(use_file+".tmp", "w") as f: 1811 for line in new_content: 1812 f.write(line+"\n") 1813 f.flush() 1814 1815 os.rename(use_file+".tmp", use_file) 1816 return True
1817
1818 - def _get_package_use_useflags(self, atom):
1819 1820 data = { 1821 'enabled': set(), 1822 'disabled': set(), 1823 } 1824 1825 matched_atom = self.match_package(atom) 1826 if not matched_atom: 1827 return data 1828 1829 use_file = self._get_package_use_file() 1830 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)): 1831 return data 1832 1833 use_data = self.portage_util.grabdict(use_file) 1834 for myatom in use_data: 1835 mymatch = self.match_package(myatom) 1836 if mymatch != matched_atom: 1837 continue 1838 for flag in use_data[myatom]: 1839 if flag.startswith("-"): 1840 myflag = flag[1:] 1841 data['enabled'].discard(myflag) 1842 data['disabled'].add(myflag) 1843 else: 1844 myflag = flag 1845 if myflag.startswith("+"): 1846 myflag = myflag[1:] 1847 data['disabled'].discard(myflag) 1848 data['enabled'].add(myflag) 1849 1850 return data
1851
1852 - def _get_useflags(self):
1853 return self.portage.settings['USE']
1854
1855 - def _get_useflags_force(self):
1856 return self.portage.settings.useforce
1857
1858 - def _get_useflags_mask(self):
1859 return self.portage.settings.usemask
1860
1861 - def _resolve_enabled_useflags(self, iuse_list, use_list):
1862 use = set() 1863 use_mask = self._get_useflags_mask() 1864 use_force = self._get_useflags_force() 1865 for myiuse in iuse_list: 1866 if myiuse[0] in ("+", "-",): 1867 myiuse = myiuse[1:] 1868 if ((myiuse in use_list) or (myiuse in use_force)) and \ 1869 (myiuse not in use_mask): 1870 use.add(myiuse) 1871 return use
1872
1873 - def _calculate_dependencies(self, my_iuse, my_use, my_license, my_depend, 1874 my_rdepend, my_pdepend, my_provide, my_src_uri):
1875 1876 metadata = { 1877 'LICENSE': my_license, 1878 'DEPEND': my_depend, 1879 'PDEPEND': my_pdepend, 1880 'RDEPEND': my_rdepend, 1881 'PROVIDE': my_provide, 1882 'SRC_URI': my_src_uri, 1883 'USE_MASK': sorted(self._get_useflags_mask()), 1884 'USE_FORCE': sorted(self._get_useflags_force()), 1885 } 1886 1887 # generate USE flags metadata 1888 raw_use = my_use.split() 1889 enabled_use = sorted(self._resolve_enabled_useflags( 1890 my_iuse.split(), raw_use)) 1891 1892 metadata['ENABLED_USE'] = enabled_use 1893 use = raw_use + [x for x in metadata['USE_FORCE'] if x not in raw_use] 1894 metadata['USE'] = sorted([unicode(x) for x in use if x not in \ 1895 metadata['USE_MASK']]) 1896 1897 for k in "LICENSE", "RDEPEND", "DEPEND", "PDEPEND", "PROVIDE", "SRC_URI": 1898 try: 1899 if k == "SRC_URI": 1900 deps = self._src_uri_paren_reduce(metadata[k]) 1901 else: 1902 deps = self._paren_reduce(metadata[k]) 1903 deps = self._use_reduce(deps, uselist = raw_use) 1904 deps = self.paren_normalize(deps) 1905 if k == "LICENSE": 1906 deps = self._paren_license_choose(deps) 1907 else: 1908 deps = self._paren_choose(deps) 1909 if k.endswith("DEPEND"): 1910 deps = self._usedeps_reduce(deps, enabled_use) 1911 deps = ' '.join(deps) 1912 except Exception, e: 1913 self.entropyTools.print_traceback() 1914 self.updateProgress( 1915 darkred("%s: %s: %s :: %s") % ( 1916 _("Error calculating dependencies"), 1917 str(Exception), 1918 k, 1919 e, 1920 ), 1921 importance = 1, 1922 type = "error", 1923 header = red(" !!! ") 1924 ) 1925 deps = '' 1926 continue 1927 metadata[k] = deps 1928 return metadata
1929
1930 - def _src_uri_paren_reduce(self, src_uris):
1931 src_uris = self._paren_reduce(src_uris) 1932 newlist = [] 1933 skip_next = False 1934 for src_uri in src_uris: 1935 if skip_next: 1936 skip_next = False 1937 continue 1938 if src_uri == "->": 1939 skip_next = True 1940 continue 1941 newlist.append(src_uri) 1942 return newlist
1943
1944 - def _usedeps_reduce(self, dependencies, enabled_useflags):
1945 newlist = [] 1946 1947 def strip_use(xuse): 1948 myuse = xuse[:] 1949 if myuse[0] == "!": 1950 myuse = myuse[1:] 1951 if myuse[-1] in ("=","?",): 1952 myuse = myuse[:-1] 1953 return myuse
1954 1955 for dependency in dependencies: 1956 use_deps = self.entropyTools.dep_getusedeps(dependency) 1957 if use_deps: 1958 new_use_deps = [] 1959 for use in use_deps: 1960 """ 1961 explicitly support only specific types 1962 """ 1963 if (use[0] == "!") and (use[-1] not in ("=","?",)): 1964 # this does not exist atm 1965 continue 1966 elif use[-1] == "=": 1967 if use[0] == "!": 1968 # foo[!bar=] means bar? ( foo[-bar] ) !bar? ( foo[bar] ) 1969 s_use = strip_use(use) 1970 if s_use in enabled_useflags: 1971 new_use_deps.append("-%s" % (s_use,)) 1972 else: 1973 new_use_deps.append(s_use) 1974 continue 1975 else: 1976 # foo[bar=] means bar? ( foo[bar] ) !bar? ( foo[-bar] ) 1977 s_use = strip_use(use) 1978 if s_use in enabled_useflags: 1979 new_use_deps.append(s_use) 1980 else: 1981 new_use_deps.append("-%s" % (s_use,)) 1982 continue 1983 elif use[-1] == "?": 1984 if use[0] == "!": 1985 # foo[!bar?] means bar? ( foo ) !bar? ( foo[-bar] ) 1986 s_use = strip_use(use) 1987 if s_use not in enabled_useflags: 1988 new_use_deps.append("-%s" % (s_use,)) 1989 continue 1990 else: 1991 # foo[bar?] means bar? ( foo[bar] ) !bar? ( foo ) 1992 s_use = strip_use(use) 1993 if s_use in enabled_useflags: 1994 new_use_deps.append(s_use) 1995 continue 1996 new_use_deps.append(use) 1997 1998 if new_use_deps: 1999 dependency = "%s[%s]" % ( 2000 self.entropyTools.remove_usedeps(dependency), 2001 ','.join(new_use_deps), 2002 ) 2003 else: 2004 dependency = self.entropyTools.remove_usedeps(dependency) 2005 2006 newlist.append(dependency) 2007 return newlist 2008
2009 - def _paren_reduce(self, mystr):
2010 """ 2011 2012 # deps.py -- Portage dependency resolution functions 2013 # Copyright 2003-2004 Gentoo Foundation 2014 # Distributed under the terms of the GNU General Public License v2 2015 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $ 2016 2017 Take a string and convert all paren enclosed entities into sublists, optionally 2018 futher splitting the list elements by spaces. 2019 2020 Example usage: 2021 >>> paren_reduce('foobar foo ( bar baz )',1) 2022 ['foobar', 'foo', ['bar', 'baz']] 2023 >>> paren_reduce('foobar foo ( bar baz )',0) 2024 ['foobar foo ', [' bar baz ']] 2025 2026 @param mystr: The string to reduce 2027 @type mystr: String 2028 @rtype: Array 2029 @return: The reduced string in an array 2030 """ 2031 mylist = [] 2032 while mystr: 2033 left_paren = mystr.find("(") 2034 has_left_paren = left_paren != -1 2035 right_paren = mystr.find(")") 2036 has_right_paren = right_paren != -1 2037 if not has_left_paren and not has_right_paren: 2038 freesec = mystr 2039 subsec = None 2040 tail = "" 2041 elif mystr[0] == ")": 2042 return [mylist,mystr[1:]] 2043 elif has_left_paren and not has_right_paren: 2044 raise InvalidDependString( 2045 "InvalidDependString: %s: '%s'" % (_("missing right parenthesis"),mystr,)) 2046 elif has_left_paren and left_paren < right_paren: 2047 freesec,subsec = mystr.split("(",1) 2048 subsec,tail = self._paren_reduce(subsec) 2049 else: 2050 subsec,tail = mystr.split(")",1) 2051 subsec = self._strip_empty(subsec.split(" ")) 2052 return [mylist+subsec,tail] 2053 mystr = tail 2054 if freesec: 2055 mylist = mylist + self._strip_empty(freesec.split(" ")) 2056 if subsec is not None: 2057 mylist = mylist + [subsec] 2058 return mylist
2059
2060 - def _strip_empty(self, myarr):
2061 """ 2062 2063 # deps.py -- Portage dependency resolution functions 2064 # Copyright 2003-2004 Gentoo Foundation 2065 # Distributed under the terms of the GNU General Public License v2 2066 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $ 2067 2068 Strip all empty elements from an array 2069 2070 @param myarr: The list of elements 2071 @type myarr: List 2072 @rtype: Array 2073 @return: The array with empty elements removed 2074 """ 2075 for x in range(len(myarr)-1, -1, -1): 2076 if not myarr[x]: 2077 del myarr[x] 2078 return myarr
2079
2080 - def _use_reduce(self, deparray, uselist = None, masklist = None, 2081 matchall = 0, excludeall = None):
2082 """ 2083 2084 # deps.py -- Portage dependency resolution functions 2085 # Copyright 2003-2004 Gentoo Foundation 2086 # Distributed under the terms of the GNU General Public License v2 2087 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $ 2088 2089 Takes a paren_reduce'd array and reduces the use? conditionals out 2090 leaving an array with subarrays 2091 2092 @param deparray: paren_reduce'd list of deps 2093 @type deparray: List 2094 @param uselist: List of use flags 2095 @type uselist: List 2096 @param masklist: List of masked flags 2097 @type masklist: List 2098 @param matchall: Resolve all conditional deps unconditionally. Used by repoman 2099 @type matchall: Integer 2100 @rtype: List 2101 @return: The use reduced depend array 2102 """ 2103 2104 if uselist is None: 2105 uselist = [] 2106 if masklist is None: 2107 masklist = [] 2108 if excludeall is None: 2109 excludeall = [] 2110 2111 # Quick validity checks 2112 for x in range(len(deparray)): 2113 if deparray[x] in ["||","&&"]: 2114 if len(deparray) - 1 == x or not isinstance(deparray[x+1], list): 2115 mytxt = _("missing atom list in") 2116 raise InvalidDependString(deparray[x]+" "+mytxt+" \""+str(deparray)+"\"") 2117 if deparray and deparray[-1] and deparray[-1][-1] == "?": 2118 mytxt = _("Conditional without target in") 2119 raise InvalidDependString("InvalidDependString: "+mytxt+" \""+str(deparray)+"\"") 2120 2121 # This is just for use by emerge so that it can enable a backward compatibility 2122 # mode in order to gracefully deal with installed packages that have invalid 2123 # atoms or dep syntax. For backward compatibility with api consumers, strict 2124 # behavior will be explicitly enabled as necessary. 2125 _dep_check_strict = False 2126 2127 mydeparray = deparray[:] 2128 rlist = [] 2129 while mydeparray: 2130 head = mydeparray.pop(0) 2131 2132 if isinstance(head,list): 2133 additions = self._use_reduce(head, uselist, masklist, matchall, excludeall) 2134 if additions: 2135 rlist.append(additions) 2136 elif rlist and rlist[-1] == "||": 2137 #XXX: Currently some DEPEND strings have || lists without default atoms. 2138 # raise portage_exception.InvalidDependString("No default atom(s) in \""+paren_enclose(deparray)+"\"") 2139 rlist.append([]) 2140 else: 2141 if head[-1] == "?": # Use reduce next group on fail. 2142 # Pull any other use conditions and the following atom or list into a separate array 2143 newdeparray = [head] 2144 while isinstance(newdeparray[-1], basestring) and newdeparray[-1][-1] == "?": 2145 if mydeparray: 2146 newdeparray.append(mydeparray.pop(0)) 2147 else: 2148 raise ValueError, _("Conditional with no target") 2149 2150 # Deprecation checks 2151 warned = 0 2152 if len(newdeparray[-1]) == 0: 2153 mytxt = "%s. (%s)" % (_("Empty target in string"),_("Deprecated"),) 2154 self.updateProgress( 2155 darkred("PortagePlugin._use_reduce(): %s" % (mytxt,)), 2156 importance = 0, 2157 type = "error", 2158 header = bold(" !!! ") 2159 ) 2160 warned = 1 2161 if len(newdeparray) != 2: 2162 mytxt = "%s. (%s)" % (_("Nested use flags without parenthesis"),_("Deprecated"),) 2163 self.updateProgress( 2164 darkred("PortagePlugin._use_reduce(): %s" % (mytxt,)), 2165 importance = 0, 2166 type = "error", 2167 header = bold(" !!! ") 2168 ) 2169 warned = 1 2170 if warned: 2171 self.updateProgress( 2172 darkred("PortagePlugin._use_reduce(): "+" ".join(map(str,[head]+newdeparray))), 2173 importance = 0, 2174 type = "error", 2175 header = bold(" !!! ") 2176 ) 2177 2178 # Check that each flag matches 2179 ismatch = True 2180 missing_flag = False 2181 for head in newdeparray[:-1]: 2182 head = head[:-1] 2183 if not head: 2184 missing_flag = True 2185 break 2186 if head.startswith("!"): 2187 head_key = head[1:] 2188 if not head_key: 2189 missing_flag = True 2190 break 2191 if not matchall and head_key in uselist or \ 2192 head_key in excludeall: 2193 ismatch = False 2194 break 2195 elif head not in masklist: 2196 if not matchall and head not in uselist: 2197 ismatch = False 2198 break 2199 else: 2200 ismatch = False 2201 if missing_flag: 2202 mytxt = _("Conditional without flag") 2203 raise InvalidDependString( 2204 "InvalidDependString: "+mytxt+": \"" + \ 2205 str([head+"?", newdeparray[-1]])+"\"") 2206 2207 # If they all match, process the target 2208 if ismatch: 2209 target = newdeparray[-1] 2210 if isinstance(target, list): 2211 additions = self._use_reduce(target, uselist, masklist, matchall, excludeall) 2212 if additions: 2213 rlist.append(additions) 2214 elif not _dep_check_strict: 2215 # The old deprecated behavior. 2216 rlist.append(target) 2217 else: 2218 mytxt = _("Conditional without parenthesis") 2219 raise InvalidDependString( 2220 "InvalidDependString: "+mytxt+": '%s?'" % head) 2221 2222 else: 2223 rlist += [head] 2224 return rlist
2225
2226 - def _paren_choose(self, dep_list):
2227 newlist = [] 2228 do_skip = False 2229 for idx in range(len(dep_list)): 2230 2231 if do_skip: 2232 do_skip = False 2233 continue 2234 2235 item = dep_list[idx] 2236 if item == "||": # or 2237 next_item = dep_list[idx+1] 2238 if not next_item: # || ( asd? ( atom ) dsa? ( atom ) ) => [] if use asd and dsa are disabled 2239 do_skip = True 2240 continue 2241 item = self._dep_or_select(next_item) # must be a list 2242 if not item: 2243 # no matches, transform to string and append, so reagent will fail 2244 newlist.append(str(next_item)) 2245 else: 2246 newlist += item 2247 do_skip = True 2248 elif isinstance(item, list): # and 2249 item = self._dep_and_select(item) 2250 newlist += item 2251 else: 2252 newlist.append(item) 2253 2254 return newlist
2255
2256 - def _dep_and_select(self, and_list):
2257 do_skip = False 2258 newlist = [] 2259 for idx in range(len(and_list)): 2260 2261 if do_skip: 2262 do_skip = False 2263 continue 2264 2265 x = and_list[idx] 2266 if x == "||": 2267 x = self._dep_or_select(and_list[idx+1]) 2268 do_skip = True 2269 if not x: 2270 x = str(and_list[idx+1]) 2271 else: 2272 newlist += x 2273 elif isinstance(x, list): 2274 x = self._dep_and_select(x) 2275 newlist += x 2276 else: 2277 newlist.append(x) 2278 2279 # now verify if all are satisfied 2280 for x in newlist: 2281 match = self.match_installed_package(x) 2282 if not match: 2283 return [] 2284 2285 return newlist
2286
2287 - def _dep_or_select(self, or_list):
2288 do_skip = False 2289 for idx in range(len(or_list)): 2290 if do_skip: 2291 do_skip = False 2292 continue 2293 x = or_list[idx] 2294 if x == "||": # or 2295 x = self._dep_or_select(or_list[idx+1]) 2296 do_skip = True 2297 elif isinstance(x, list): # and 2298 x = self._dep_and_select(x) 2299 if not x: 2300 continue 2301 # found 2302 return x 2303 else: 2304 x = [x] 2305 2306 for y in x: 2307 match = self.match_installed_package(y) 2308 if match: 2309 return [y] 2310 2311 return []
2312
2313 - def _paren_license_choose(self, dep_list):
2314 2315 newlist = set() 2316 for item in dep_list: 2317 2318 if isinstance(item, list): 2319 # match the first 2320 data = set(self._paren_license_choose(item)) 2321 newlist.update(data) 2322 else: 2323 if item not in ["||"]: 2324 newlist.add(item) 2325 2326 return list(newlist)
2327
2328 - def _get_vdb_path(self, root = None):
2329 if root is None: 2330 root = etpConst['systemroot'] + os.path.sep 2331 return os.path.join(root, self.portage_const.VDB_PATH)
2332
2333 - def _load_sets_config(self, settings, trees):
2334 2335 # from portage.const import USER_CONFIG_PATH, GLOBAL_CONFIG_PATH 2336 setconfigpaths = [os.path.join(self.portage_const.GLOBAL_CONFIG_PATH, etpConst['setsconffilename'])] 2337 setconfigpaths.append(os.path.join(settings["PORTDIR"], etpConst['setsconffilename'])) 2338 setconfigpaths += [os.path.join(x, etpConst['setsconffilename']) for x in settings["PORTDIR_OVERLAY"].split()] 2339 setconfigpaths.append(os.path.join(settings["PORTAGE_CONFIGROOT"], 2340 self.portage_const.USER_CONFIG_PATH.lstrip(os.path.sep), etpConst['setsconffilename'])) 2341 return self.portage_sets.SetConfig(setconfigpaths, settings, trees)
2342
2343 - def _get_set_config(self):
2344 # old portage 2345 if self.portage_sets == None: 2346 return 2347 myroot = etpConst['systemroot'] + os.path.sep 2348 return self._load_sets_config( 2349 self.portage.settings, 2350 self.portage.db[myroot] 2351 )
2352
2353 - def _extract_pkg_metadata_generate_extraction_dict(self):
2354 data = { 2355 'pf': { 2356 'path': etpConst['spm']['xpak_entries']['pf'], 2357 'critical': True, 2358 }, 2359 'chost': { 2360 'path': etpConst['spm']['xpak_entries']['chost'], 2361 'critical': True, 2362 }, 2363 'description': { 2364 'path': etpConst['spm']['xpak_entries']['description'], 2365 'critical': False, 2366 }, 2367 'homepage': { 2368 'path': etpConst['spm']['xpak_entries']['homepage'], 2369 'critical': False, 2370 }, 2371 'slot': { 2372 'path': etpConst['spm']['xpak_entries']['slot'], 2373 'critical': False, 2374 }, 2375 'cflags': { 2376 'path': etpConst['spm']['xpak_entries']['cflags'], 2377 'critical': False, 2378 }, 2379 'cxxflags': { 2380 'path': etpConst['spm']['xpak_entries']['cxxflags'], 2381 'critical': False, 2382 }, 2383 'category': { 2384 'path': etpConst['spm']['xpak_entries']['category'], 2385 'critical': True, 2386 }, 2387 'rdepend': { 2388 'path': etpConst['spm']['xpak_entries']['rdepend'], 2389 'critical': False, 2390 }, 2391 'pdepend': { 2392 'path': etpConst['spm']['xpak_entries']['pdepend'], 2393 'critical': False, 2394 }, 2395 'depend': { 2396 'path': etpConst['spm']['xpak_entries']['depend'], 2397 'critical': False, 2398 }, 2399 'use': { 2400 'path': etpConst['spm']['xpak_entries']['use'], 2401 'critical': False, 2402 }, 2403 'iuse': { 2404 'path': etpConst['spm']['xpak_entries']['iuse'], 2405 'critical': False, 2406 }, 2407 'license': { 2408 'path': etpConst['spm']['xpak_entries']['license'], 2409 'critical': False, 2410 }, 2411 'provide': { 2412 'path': etpConst['spm']['xpak_entries']['provide'], 2413 'critical': False, 2414 }, 2415 'sources': { 2416 'path': etpConst['spm']['xpak_entries']['src_uri'], 2417 'critical': False, 2418 }, 2419 'eclasses': { 2420 'path': etpConst['spm']['xpak_entries']['inherited'], 2421 'critical': False, 2422 }, 2423 'counter': { 2424 'path': etpConst['spm']['xpak_entries']['counter'], 2425 'critical': False, 2426 }, 2427 'keywords': { 2428 'path': etpConst['spm']['xpak_entries']['keywords'], 2429 'critical': False, 2430 }, 2431 'spm_phases': { 2432 'path': etpConst['spm']['xpak_entries']['defined_phases'], 2433 'critical': False, 2434 }, 2435 } 2436 return data
2437
2438 - def _extract_pkg_metadata_content(self, content_file, package_path):
2439 2440 pkg_content = {} 2441 2442 if os.path.isfile(content_file): 2443 2444 f = open(content_file,"r") 2445 content = [x.decode('raw_unicode_escape') for x in f.readlines()] 2446 f.close() 2447 outcontent = set() 2448 for line in content: 2449 line = line.strip().split() 2450 try: 2451 datatype = line[0] 2452 datafile = line[1:] 2453 if datatype == 'obj': 2454 datafile = datafile[:-2] 2455 datafile = ' '.join(datafile) 2456 elif datatype == 'dir': 2457 datafile = ' '.join(datafile) 2458 elif datatype == 'sym': 2459 datafile = datafile[:-3] 2460 datafile = ' '.join(datafile) 2461 else: 2462 myexc = "InvalidData: %s %s. %s." % ( 2463 datafile, 2464 _("not supported"), 2465 _("Probably Portage API has changed"), 2466 ) 2467 raise InvalidData(myexc) 2468 outcontent.add((datafile,datatype)) 2469 except: 2470 pass 2471 2472 outcontent = sorted(outcontent) 2473 for datafile, datatype in outcontent: 2474 pkg_content[datafile] = datatype 2475 2476 else: 2477 2478 # CONTENTS is not generated when a package is emerged with portage and the option -B 2479 # we have to unpack the tbz2 and generate content dict 2480 mytempdir = etpConst['packagestmpdir']+"/"+os.path.basename(package_path)+".inject" 2481 if os.path.isdir(mytempdir): 2482 shutil.rmtree(mytempdir) 2483 if not os.path.isdir(mytempdir): 2484 os.makedirs(mytempdir) 2485 2486 self.entropyTools.uncompress_tar_bz2(package_path, extractPath = mytempdir, catchEmpty = True) 2487 tmpdir_len = len(mytempdir) 2488 for currentdir, subdirs, files in os.walk(mytempdir): 2489 pkg_content[currentdir[tmpdir_len:]] = u"dir" 2490 for item in files: 2491 item = currentdir+"/"+item 2492 if os.path.islink(item): 2493 pkg_content[item[tmpdir_len:]] = u"sym" 2494 else: 2495 pkg_content[item[tmpdir_len:]] = u"obj" 2496 2497 # now remove 2498 shutil.rmtree(mytempdir,True) 2499 try: 2500 os.rmdir(mytempdir) 2501 except (OSError,): 2502 pass 2503 2504 return pkg_content
2505
2506 - def _extract_pkg_metadata_needed(self, needed_file):
2507 2508 pkg_needed = set() 2509 lines = [] 2510 2511 try: 2512 f = open(needed_file,"r") 2513 lines = [x.decode('raw_unicode_escape').strip() for x in f.readlines() if x.strip()] 2514 f.close() 2515 except IOError: 2516 return lines 2517 2518 for line in lines: 2519 needed = line.split() 2520 if len(needed) == 2: 2521 ownlib = needed[0] 2522 ownelf = -1 2523 if os.access(ownlib,os.R_OK): 2524 ownelf = self.entropyTools.read_elf_class(ownlib) 2525 for lib in needed[1].split(","): 2526 #if lib.find(".so") != -1: 2527 pkg_needed.add((lib,ownelf)) 2528 2529 return sorted(pkg_needed)
2530
2531 - def _extract_pkg_metadata_needed_paths(self, needed_libs):
2532 2533 data = {} 2534 ldpaths = self.entropyTools.collect_linker_paths() 2535 2536 for needed_lib, elf_class in needed_libs: 2537 for ldpath in ldpaths: 2538 my_lib = os.path.join(ldpath, needed_lib) 2539 if not os.access(my_lib, os.R_OK): 2540 continue 2541 myclass = self.entropyTools.read_elf_class(my_lib) 2542 if myclass != elf_class: 2543 continue 2544 obj = data.setdefault(needed_lib, set()) 2545 obj.add((my_lib, myclass,)) 2546 2547 return data
2548
2549 - def _extract_pkg_metadata_messages(self, log_dir, category, name, version):
2550 2551 pkg_messages = [] 2552 if not os.path.isdir(log_dir): 2553 return pkg_messages 2554 2555 elogfiles = os.listdir(log_dir) 2556 myelogfile = "%s:%s-%s" % (category, name, version,) 2557 foundfiles = [x for x in elogfiles if x.startswith(myelogfile)] 2558 if foundfiles: 2559 elogfile = foundfiles[0] 2560 if len(foundfiles) > 1: 2561 # get the latest 2562 mtimes = [] 2563 for item in foundfiles: mtimes.append((self.entropyTools.get_file_unix_mtime(os.path.join(log_dir,item)),item)) 2564 mtimes = sorted(mtimes) 2565 elogfile = mtimes[-1][1] 2566 messages = self.entropyTools.extract_elog(os.path.join(log_dir,elogfile)) 2567 for message in messages: 2568 message = message.replace("emerge","install") 2569 pkg_messages.append(message.decode('raw_unicode_escape')) 2570 2571 return pkg_messages
2572
2573 - def _extract_pkg_metadata_license_data(self, licenses_dir, license_string):
2574 2575 pkg_licensedata = {} 2576 if licenses_dir and os.path.isdir(licenses_dir): 2577 licdata = [x.strip() for x in license_string.split() if x.strip() and self.entropyTools.is_valid_string(x.strip())] 2578 for mylicense in licdata: 2579 licfile = os.path.join(licenses_dir,mylicense) 2580 if os.access(licfile,os.R_OK): 2581 if self.entropyTools.istextfile(licfile): 2582 f = open(licfile) 2583 content = '' 2584 line = f.readline() 2585 while line: 2586 content += line 2587 line = f.readline() 2588 try: 2589 try: 2590 pkg_licensedata[mylicense] = content.decode('raw_unicode_escape') 2591 except UnicodeDecodeError: 2592 pkg_licensedata[mylicense] = unicode(content,'utf-8') 2593 except (UnicodeDecodeError, UnicodeEncodeError,): 2594 continue # sorry! 2595 f.close() 2596 2597 return pkg_licensedata
2598 2612
2613 - def _extract_pkg_metadata_ebuild_entropy_tag(self, ebuild):
2614 search_tag = etpConst['spm']['ebuild_pkg_tag_var'] 2615 ebuild_tag = '' 2616 f = open(ebuild,"r") 2617 tags = [x.strip().decode('raw_unicode_escape') for x in f.readlines() if x.strip() and x.strip().startswith(search_tag)] 2618 f.close() 2619 if not tags: return ebuild_tag 2620 tag = tags[-1] 2621 tag = tag.split("=")[-1].strip('"').strip("'").strip() 2622 return tag
2623