Package entropy :: Module spm

Source Code for Module entropy.spm

   1  # -*- coding: utf-8 -*- 
   2  ''' 
   3      # DESCRIPTION: 
   4      # Entropy Object Oriented Interface 
   5   
   6      Copyright (C) 2007-2009 Fabio Erculiani 
   7   
   8      This program is free software; you can redistribute it and/or modify 
   9      it under the terms of the GNU General Public License as published by 
  10      the Free Software Foundation; either version 2 of the License, or 
  11      (at your option) any later version. 
  12   
  13      This program is distributed in the hope that it will be useful, 
  14      but WITHOUT ANY WARRANTY; without even the implied warranty of 
  15      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  16      GNU General Public License for more details. 
  17   
  18      You should have received a copy of the GNU General Public License 
  19      along with this program; if not, write to the Free Software 
  20      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
  21  ''' 
  22  import os 
  23  import sys 
  24  import shutil 
  25  from entropy.const import etpConst, etpUi 
  26  from entropy.exceptions import * 
  27  from entropy.output import darkred, darkgreen, brown, darkblue, purple, red, bold 
  28  from entropy.i18n import _ 
  29  from entropy.core import SystemSettings 
30 31 -class Spm:
32
33 - def __init__(self, OutputInterface):
34 35 if not hasattr(OutputInterface,'updateProgress'): 36 mytxt = _("OutputInterface does not have an updateProgress method") 37 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,)) 38 elif not callable(OutputInterface.updateProgress): 39 mytxt = _("OutputInterface does not have an updateProgress method") 40 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,)) 41 42 self.spm_backend = etpConst['spm']['backend'] 43 self.valid_backends = etpConst['spm']['available_backends'] 44 if self.spm_backend not in self.valid_backends: 45 mytxt = "%s: %s" % (_("Invalid backend"),self.spm_backend,) 46 raise IncorrectParameter("IncorrectParameter: %s" % (mytxt,)) 47 48 if self.spm_backend == "portage": 49 self.intf = PortagePlugin(OutputInterface)
50 51 @staticmethod
52 - def get_spm_interface():
53 backend = etpConst['spm']['backend'] 54 if backend == "portage": 55 return PortagePlugin
56
57 -class PortagePlugin:
58 59 import entropy.tools as entropyTools 60
61 - class paren_normalize(list):
62 """Take a dependency structure as returned by paren_reduce or use_reduce 63 and generate an equivalent structure that has no redundant lists."""
64 - def __init__(self, src):
65 list.__init__(self) 66 self._zap_parens(src, self)
67
68 - def _zap_parens(self, src, dest, disjunction=False):
69 if not src: 70 return dest 71 i = iter(src) 72 for x in i: 73 if isinstance(x, basestring): 74 if x == '||': 75 x = self._zap_parens(i.next(), [], disjunction=True) 76 if len(x) == 1: 77 dest.append(x[0]) 78 else: 79 dest.append("||") 80 dest.append(x) 81 elif x.endswith("?"): 82 dest.append(x) 83 dest.append(self._zap_parens(i.next(), [])) 84 else: 85 dest.append(x) 86 else: 87 if disjunction: 88 x = self._zap_parens(x, []) 89 if len(x) == 1: 90 dest.append(x[0]) 91 else: 92 dest.append(x) 93 else: 94 self._zap_parens(x, dest) 95 return dest
96
97 - def __init__(self, OutputInterface):
98 99 if not hasattr(OutputInterface,'updateProgress'): 100 mytxt = _("OutputInterface does not have an updateProgress method") 101 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,)) 102 elif not callable(OutputInterface.updateProgress): 103 mytxt = _("OutputInterface does not have an updateProgress method") 104 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,)) 105 106 # interface only needed OutputInterface functions 107 self.updateProgress = OutputInterface.updateProgress 108 self.askQuestion = OutputInterface.askQuestion 109 sys.path.append("/usr/lib/gentoolkit/pym") 110 111 from entropy.misc import LogFile 112 self.LogFile = LogFile 113 114 # importing portage stuff 115 import portage 116 self.portage = portage 117 self.EAPI = 1 118 try: 119 import portage.const as portage_const 120 except ImportError: 121 import portage_const 122 if hasattr(portage_const,"EAPI"): 123 self.EAPI = portage_const.EAPI 124 self.portage_const = portage_const 125 126 from portage.versions import best 127 self.portage_best = best 128 129 try: 130 import portage.util as portage_util 131 except ImportError: 132 import portage_util 133 self.portage_util = portage_util 134 135 try: 136 import portage.sets as portage_sets 137 self.portage_sets = portage_sets 138 except ImportError: 139 self.portage_sets = None 140 141 try: 142 import glsa 143 self.glsa = glsa 144 except ImportError: 145 self.glsa = None 146 147 if hasattr(self.portage,'exception'): 148 self.portage_exception = self.portage.exception 149 else: # portage <2.2 workaround 150 self.portage_exception = Exception 151 152 self.builtin_pkg_sets = [ 153 "system","world","installed","module-rebuild", 154 "security","preserved-rebuild","live-rebuild", 155 "downgrade","unavailable" 156 ]
157
158 - def write_to_log(self, message):
159 spmLog = self.LogFile( 160 level = etpConst['spmloglevel'], 161 filename = etpConst['spmlogfile'], 162 header = "[spm]" 163 ) 164 spmLog.write(message) 165 spmLog.flush() 166 spmLog.close()
167
168 - def write_traceback_to_log(self):
169 spmLog = self.LogFile( 170 level = etpConst['spmloglevel'], 171 filename = etpConst['spmlogfile'], 172 header = "[spm]" 173 ) 174 self.entropyTools.print_traceback(f = spmLog) 175 spmLog.flush() 176 spmLog.close()
177
178 - def list_glsa_packages(self, command = "affected"):
179 180 if not self.glsa: return 181 if command not in ['new','all','affected']: return 182 183 glsaconfig = self.glsa.checkconfig(self.portage.config(clone=self.portage.settings)) 184 completelist = self.glsa.get_glsa_list(glsaconfig["GLSA_DIR"], glsaconfig) 185 186 glsalist = [] 187 if command == "new": 188 checklist = [] 189 if os.access(glsaconfig["CHECKFILE"], os.R_OK): 190 checklist = [line.strip() for line in open(glsaconfig["CHECKFILE"], "r").readlines()] 191 glsalist = [e for e in completelist if e not in checklist] 192 elif command == "all": 193 glsalist = completelist 194 elif command == "affected": 195 # maybe this should be todolist instead 196 for x in completelist: 197 try: 198 myglsa = self.glsa.Glsa(x, glsaconfig) 199 except (self.glsa.GlsaTypeException, self.glsa.GlsaFormatException), e: 200 continue 201 if not myglsa.isVulnerable(): 202 continue 203 glsalist.append(x) 204 205 return glsalist
206
207 - def get_glsa_id_information(self, glsa_id):
208 if not self.glsa: return {} 209 210 glsaconfig = self.glsa.checkconfig(self.portage.config(clone=self.portage.settings)) 211 try: 212 myglsa = self.glsa.Glsa(glsa_id, glsaconfig) 213 except (self.glsa.GlsaTypeException, self.glsa.GlsaFormatException): 214 return {} 215 216 mydict = { 217 'glsa_id': glsa_id, 218 'number': myglsa.nr, 219 'access': myglsa.access, 220 'title': myglsa.title, 221 'synopsis': myglsa.synopsis, 222 'announced': myglsa.announced, 223 'revised': myglsa.revised, 224 'bugs': myglsa.bugs, 225 'description': myglsa.description, 226 'resolution': myglsa.resolution, 227 'impact': myglsa.impact_text, 228 'impacttype': myglsa.impact_type, 229 'affected': myglsa.affected, 230 'background': myglsa.background, 231 'glsatype': myglsa.glsatype, 232 'packages': myglsa.packages, 233 'services': myglsa.services, 234 'product': myglsa.product, 235 'references': myglsa.references, 236 'workaround': myglsa.workaround, 237 } 238 if myglsa.isApplied(): 239 status = "[A]" 240 elif myglsa.isVulnerable(): 241 status = "[N]" 242 else: 243 status = "[U]" 244 mydict['status'] = status 245 246 return mydict.copy()
247
248 - def run_fixpackages(self, myroot = None):
249 if myroot == None: 250 myroot = etpConst['systemroot']+"/" 251 mydb = {} 252 mydb[myroot] = {} 253 mydb[myroot]['vartree'] = self._get_portage_vartree(myroot) 254 mydb[myroot]['porttree'] = self._get_portage_portagetree(myroot) 255 mydb[myroot]['bintree'] = self._get_portage_binarytree(myroot) 256 mydb[myroot]['virtuals'] = self.portage.settings.getvirtuals(myroot) 257 if etpUi['mute']: 258 pid = os.fork() 259 if pid > 0: 260 os.waitpid(pid, 0) 261 else: 262 f = open("/dev/null","w") 263 old_stdout = sys.stdout 264 old_stderr = sys.stderr 265 sys.stdout = f 266 sys.stderr = f 267 self.portage._global_updates(mydb, {}) 268 sys.stdout = old_stdout 269 sys.stderr = old_stderr 270 f.close() 271 os._exit(0) 272 else: 273 self.portage._global_updates(mydb, {}) # always force
274
275 - def get_world_file(self):
276 return os.path.join(etpConst['systemroot'],"/",self.portage_const.WORLD_FILE)
277
278 - def get_third_party_mirrors(self, mirrorname):
279 x = [] 280 if self.portage.thirdpartymirrors.has_key(mirrorname): 281 x = self.portage.thirdpartymirrors[mirrorname] 282 return x
283
284 - def get_spm_setting(self, var):
285 return self.portage.settings[var]
286
288 config_protect = self.portage.settings['CONFIG_PROTECT'] 289 config_protect = config_protect.split() 290 config_protect_mask = self.portage.settings['CONFIG_PROTECT_MASK'] 291 config_protect_mask = config_protect_mask.split() 292 # explode 293 protect = [] 294 for x in config_protect: 295 x = os.path.expandvars(x) 296 protect.append(x) 297 mask = [] 298 for x in config_protect_mask: 299 x = os.path.expandvars(x) 300 mask.append(x) 301 return ' '.join(protect),' '.join(mask)
302
303 - def _get_portage_vartree(self, root):
304 305 if not etpConst['spm']['cache'].has_key('portage'): 306 etpConst['spm']['cache']['portage'] = {} 307 if not etpConst['spm']['cache']['portage'].has_key('vartree'): 308 etpConst['spm']['cache']['portage']['vartree'] = {} 309 310 cached = etpConst['spm']['cache']['portage']['vartree'].get(root) 311 if cached != None: 312 return cached 313 314 try: 315 mytree = self.portage.vartree(root=root) 316 except Exception, e: 317 raise SPMError("SPMError: %s: %s" % (Exception,e,)) 318 etpConst['spm']['cache']['portage']['vartree'][root] = mytree 319 return mytree
320
321 - def _get_portage_portagetree(self, root):
322 323 if not etpConst['spm']['cache'].has_key('portage'): 324 etpConst['spm']['cache']['portage'] = {} 325 if not etpConst['spm']['cache']['portage'].has_key('portagetree'): 326 etpConst['spm']['cache']['portage']['portagetree'] = {} 327 328 cached = etpConst['spm']['cache']['portage']['portagetree'].get(root) 329 if cached != None: 330 return cached 331 332 try: 333 mytree = self.portage.portagetree(root=root) 334 except Exception, e: 335 raise SPMError("SPMError: %s: %s" % (Exception,e,)) 336 etpConst['spm']['cache']['portage']['portagetree'][root] = mytree 337 return mytree
338
339 - def _get_portage_binarytree(self, root):
340 341 if not etpConst['spm']['cache'].has_key('portage'): 342 etpConst['spm']['cache']['portage'] = {} 343 if not etpConst['spm']['cache']['portage'].has_key('binarytree'): 344 etpConst['spm']['cache']['portage']['binarytree'] = {} 345 346 cached = etpConst['spm']['cache']['portage']['binarytree'].get(root) 347 if cached != None: 348 return cached 349 350 pkgdir = root+self.portage.settings['PKGDIR'] 351 try: 352 mytree = self.portage.binarytree(root,pkgdir) 353 except Exception, e: 354 raise SPMError("SPMError: %s: %s" % (Exception,e,)) 355 etpConst['spm']['cache']['portage']['binarytree'][root] = mytree 356 return mytree
357
358 - def _get_portage_config(self, config_root, root, use_cache = True):
359 360 if use_cache: 361 if not etpConst['spm']['cache'].has_key('portage'): 362 etpConst['spm']['cache']['portage'] = {} 363 if not etpConst['spm']['cache']['portage'].has_key('config'): 364 etpConst['spm']['cache']['portage']['config'] = {} 365 366 cached = etpConst['spm']['cache']['portage']['config'].get((config_root,root)) 367 if cached != None: 368 return cached 369 370 try: 371 mysettings = self.portage.config(config_root = config_root, target_root = root, config_incrementals = self.portage_const.INCREMENTALS) 372 except Exception, e: 373 raise SPMError("SPMError: %s: %s" % (Exception,e,)) 374 if use_cache: 375 etpConst['spm']['cache']['portage']['config'][(config_root,root)] = mysettings 376 return mysettings
377 378 # resolve atoms automagically (best, not current!) 379 # sys-libs/application --> sys-libs/application-1.2.3-r1
380 - def get_best_atom(self, atom, match = "bestmatch-visible"):
381 try: 382 return self.portage.portdb.xmatch(match,str(atom)) 383 except ValueError: 384 return None
385 386 # same as above but includes masked ebuilds
387 - def get_best_masked_atom(self, atom):
388 atoms = self.portage.portdb.xmatch("match-all",str(atom)) 389 return self.portage_best(atoms)
390
391 - def get_category_description_data(self, category):
392 from xml.dom import minidom 393 data = {} 394 portdir = self.portage.settings['PORTDIR'] 395 myfile = os.path.join(portdir,category,"metadata.xml") 396 if os.access(myfile,os.R_OK) and os.path.isfile(myfile): 397 doc = minidom.parse(myfile) 398 longdescs = doc.getElementsByTagName("longdescription") 399 for longdesc in longdescs: 400 data[longdesc.getAttribute("lang").strip()] = ' '.join([x.strip() for x in longdesc.firstChild.data.strip().split("\n")]) 401 return data
402
403 - def get_atom_category(self, atom):
404 try: 405 return self.portage.portdb.xmatch("match-all",str(atom))[0].split("/")[0] 406 except: 407 return None
408 409 # Packages in system (in the Portage language -> emerge system, remember?)
410 - def get_atoms_in_system(self):
411 system = self.portage.settings.packages 412 sysoutput = [] 413 for x in system: 414 y = self.get_installed_atoms(x) 415 if (y != None): 416 for z in y: 417 sysoutput.append(z) 418 sysoutput.extend(etpConst['spm']['system_packages']) # add our packages 419 return sysoutput
420
421 - def get_installed_atom(self, atom):
422 mypath = etpConst['systemroot']+"/" 423 mytree = self._get_portage_vartree(mypath) 424 rc = mytree.dep_match(str(atom)) 425 if rc: return rc[-1]
426
427 - def get_package_description(self, atom):
428 if atom.startswith("="): atom = atom[1:] 429 return self.portage.portdb.aux_get(atom,['DESCRIPTION'])[0]
430
431 - def get_package_ebuild_path(self, atom):
432 if atom.startswith("="): atom = atom[1:] 433 return self.portage.portdb.findname(atom)
434
435 - def get_package_changelog(self, atom):
436 if atom.startswith("="): atom = atom[1:] 437 ebuild_path = self.get_package_ebuild_path(atom) 438 if isinstance(ebuild_path,basestring): 439 cp = os.path.join(os.path.dirname(ebuild_path),"ChangeLog") 440 if os.path.isfile(cp) and os.access(cp,os.R_OK): 441 f = open(cp,"r") 442 txt = f.read() 443 f.close() 444 return txt
445
446 - def get_installed_package_description(self, atom):
447 mypath = etpConst['systemroot']+"/" 448 mytree = self._get_portage_vartree(mypath) 449 if atom.startswith("="): atom = atom[1:] 450 rc = mytree.dbapi.aux_get(atom, ["DESCRIPTION"])[0] 451 if rc: return rc
452
453 - def get_package_slot(self, atom):
454 if atom.startswith("="): atom = atom[1:] 455 return self.portage.portdb.aux_get(atom,['SLOT'])[0]
456
457 - def get_installed_package_slot(self, atom):
458 mypath = etpConst['systemroot']+"/" 459 mytree = self._get_portage_vartree(mypath) 460 if atom.startswith("="): atom = atom[1:] 461 rc = mytree.getslot(atom) 462 if rc: return rc
463
464 - def get_installed_atoms(self, atom):
465 mypath = etpConst['systemroot']+"/" 466 mytree = self._get_portage_vartree(mypath) 467 rc = mytree.dep_match(str(atom)) 468 if rc: return rc
469
470 - def search_keys(self, key):
471 key_split = key.split("/") 472 cat = key_split[0] 473 name = key_split[1] 474 cat_dir = os.path.join(self.get_vdb_path(),cat) 475 if not os.path.isdir(cat_dir): 476 return [] 477 return [os.path.join(cat,x) for x in os.listdir(cat_dir) if \ 478 x.startswith(name)]
479 480 # create a .tbz2 file in the specified path
481 - def quickpkg(self, atom, dirpath):
482 483 # getting package info 484 pkgname = atom.split("/")[1] 485 pkgcat = atom.split("/")[0] 486 #pkgfile = pkgname+".tbz2" 487 if not os.path.isdir(dirpath): 488 os.makedirs(dirpath) 489 dirpath += "/"+pkgname+etpConst['packagesext'] 490 dbdir = self.get_vdb_path()+"/"+pkgcat+"/"+pkgname+"/" 491 492 import tarfile 493 import stat 494 trees = self.portage.db["/"] 495 vartree = trees["vartree"] 496 dblnk = self.portage.dblink(pkgcat, pkgname, "/", vartree.settings, treetype="vartree", vartree=vartree) 497 dblnk.lockdb() 498 tar = tarfile.open(dirpath,"w:bz2") 499 500 contents = dblnk.getcontents() 501 paths = sorted(contents.keys()) 502 503 for path in paths: 504 try: 505 exist = os.lstat(path) 506 except OSError: 507 continue # skip file 508 ftype = contents[path][0] 509 lpath = path 510 arcname = path[1:] 511 if 'dir' == ftype and \ 512 not stat.S_ISDIR(exist.st_mode) and \ 513 os.path.isdir(lpath): 514 lpath = os.path.realpath(lpath) 515 tarinfo = tar.gettarinfo(lpath, arcname) 516 517 if stat.S_ISREG(exist.st_mode): 518 tarinfo.type = tarfile.REGTYPE 519 f = open(path) 520 try: 521 tar.addfile(tarinfo, f) 522 finally: 523 f.close() 524 else: 525 tar.addfile(tarinfo) 526 527 tar.close() 528 529 # appending xpak informations 530 import entropy.xpak as xpak 531 tbz2 = xpak.tbz2(dirpath) 532 tbz2.recompose(dbdir) 533 534 dblnk.unlockdb() 535 536 if os.path.isfile(dirpath): 537 return dirpath 538 else: 539 raise FileNotFound("FileNotFound: Spm:quickpkg %s: %s %s" % ( 540 _("error"), 541 dirpath, 542 _("not found"), 543 ) 544 )
545
546 - def get_package_use_file(self):
547 return os.path.join(self.portage_const.USER_CONFIG_PATH,'package.use')
548
549 - def enable_package_useflags(self, atom, useflags):
550 result = self.unset_package_useflags(atom, useflags) 551 if not result: return False 552 return self._handle_new_useflags(atom, useflags, "")
553
554 - def disable_package_useflags(self, atom, useflags):
555 result = self.unset_package_useflags(atom, useflags) 556 if not result: return False 557 return self._handle_new_useflags(atom, useflags, "-")
558
559 - def _handle_new_useflags(self, atom, useflags, mark):
560 matched_atom = self.get_best_atom(atom) 561 if not matched_atom: 562 return False 563 use_file = self.get_package_use_file() 564 565 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)): 566 return False 567 f = open(use_file,"r") 568 content = [x.strip() for x in f.readlines()] 569 f.close() 570 571 def handle_line(line, useflags): 572 573 data = line.split() 574 if len(data) < 2: 575 return False, line 576 577 myatom = data[0] 578 if matched_atom != self.get_best_atom(myatom): 579 return False, line 580 581 flags = data[1:] 582 base_flags = [] 583 added_flags = [] 584 for flag in flags: 585 myflag = flag 586 if myflag.startswith("+"): 587 myflag = myflag[1:] 588 elif myflag.startswith("-"): 589 myflag = myflag[1:] 590 if not myflag: 591 continue 592 base_flags.append(myflag) 593 594 for useflag in useflags: 595 if mark+useflag in base_flags: 596 continue 597 added_flags.append(mark+useflag) 598 599 new_line = "%s %s" % (myatom, ' '.join(flags+added_flags)) 600 return True, new_line
601 602 603 atom_found = False 604 new_content = [] 605 for line in content: 606 607 changed, elaborated_line = handle_line(line, useflags) 608 if changed: atom_found = True 609 new_content.append(elaborated_line) 610 611 if not atom_found: 612 myline = "%s %s" % (atom, ' '.join([mark+x for x in useflags])) 613 new_content.append(myline) 614 615 616 f = open(use_file+".tmp","w") 617 for line in new_content: 618 f.write(line+"\n") 619 f.flush() 620 f.close() 621 shutil.move(use_file+".tmp",use_file) 622 return True
623
624 - def unset_package_useflags(self, atom, useflags):
625 matched_atom = self.get_best_atom(atom) 626 if not matched_atom: 627 return False 628 629 use_file = self.get_package_use_file() 630 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)): 631 return False 632 633 f = open(use_file,"r") 634 content = [x.strip() for x in f.readlines()] 635 f.close() 636 637 new_content = [] 638 for line in content: 639 640 data = line.split() 641 if len(data) < 2: 642 new_content.append(line) 643 continue 644 645 myatom = data[0] 646 if matched_atom != self.get_best_atom(myatom): 647 new_content.append(line) 648 continue 649 650 flags = data[1:] 651 new_flags = [] 652 for flag in flags: 653 myflag = flag 654 655 if myflag.startswith("+"): 656 myflag = myflag[1:] 657 elif myflag.startswith("-"): 658 myflag = myflag[1:] 659 660 if myflag in useflags: 661 continue 662 elif not flag: 663 continue 664 665 new_flags.append(flag) 666 667 if new_flags: 668 new_line = "%s %s" % (myatom, ' '.join(new_flags)) 669 new_content.append(new_line) 670 671 f = open(use_file+".tmp","w") 672 for line in new_content: 673 f.write(line+"\n") 674 f.flush() 675 f.close() 676 shutil.move(use_file+".tmp",use_file) 677 return True
678
679 - def get_package_useflags(self, atom):
680 matched_atom = self.get_best_atom(atom) 681 if not matched_atom: 682 return {} 683 global_useflags = self.get_useflags() 684 use_force = self.get_useflags_force() 685 use_mask = self.get_useflags_mask() 686 package_use_useflags = self.get_package_use_useflags(atom) 687 688 data = {} 689 data['use_force'] = use_force.copy() 690 data['use_mask'] = use_mask.copy() 691 data['global_use'] = global_useflags.split() 692 693 iuse = self.get_package_setting(atom, "IUSE") 694 if not isinstance(iuse,basestring): 695 iuse = '' 696 data['iuse'] = iuse.split()[:] 697 iuse = set() 698 for myiuse in data['iuse']: 699 if myiuse.startswith("+"): 700 myiuse = myiuse[1:] 701 iuse.add(myiuse) 702 703 use = [f for f in data['global_use']+list(package_use_useflags['enabled']) if (f in iuse) and (f not in use_mask) and (f not in package_use_useflags['disabled'])] 704 use_disabled = [f for f in iuse if (f not in data['global_use']) and (f not in use_mask) and (f not in package_use_useflags['enabled'])] 705 data['use'] = use[:] 706 data['use_disabled'] = use_disabled[:] 707 708 matched_slot = self.get_package_slot(matched_atom) 709 try: 710 installed_atom = self.get_installed_atom("%s:%s" % (self.entropyTools.dep_getkey(atom),matched_slot,)) 711 except self.portage_exception: 712 installed_atom = None 713 714 if installed_atom: 715 716 # get its useflags 717 previous_iuse = self.get_installed_package_setting(installed_atom, "IUSE").split() 718 previous_use = self.get_installed_package_setting(installed_atom, "USE").split() 719 720 new_previous_iuse = set() 721 for myuse in previous_iuse: 722 if myuse.startswith("+"): 723 myuse = myuse[1:] 724 new_previous_iuse.add(myuse) 725 previous_iuse = list(new_previous_iuse) 726 727 inst_use = [f for f in previous_iuse if (f in previous_use) and (f not in use_mask)] 728 #inst_use_disabled = [f for f in previous_use if (f not in previous_iuse) and (f not in use_mask)] 729 730 # check removed use 731 use_removed = [] 732 for myuse in inst_use: 733 if myuse not in use: 734 use_removed.append(myuse) 735 736 # use not available 737 use_not_avail = [] 738 for myuse in previous_iuse: 739 if (myuse not in iuse) and (myuse not in use_removed): 740 use_not_avail.append(myuse) 741 742 # check new use 743 t_use = [] 744 for myuse in use: 745 if myuse not in inst_use: 746 myuse = "+%s*" % (myuse,) 747 t_use.append(myuse) 748 use = t_use 749 750 # check disabled use 751 t_use_disabled = [] 752 for myuse in use_disabled: 753 if myuse in inst_use: 754 if myuse in use_removed+use_not_avail: 755 continue 756 myuse = "-%s*" % (myuse,) 757 else: 758 myuse = "-%s" % (myuse,) 759 t_use_disabled.append(myuse) 760 use_disabled = t_use_disabled 761 762 for myuse in use_removed: 763 use_disabled.append("(-%s*)" % (myuse,)) 764 for myuse in use_not_avail: 765 use_disabled.append("(-%s)" % (myuse,)) 766 else: 767 use_disabled = ["-"+x for x in use_disabled] 768 769 data['use_string'] = ' '.join(sorted(use)+sorted([x for x in use_disabled])) 770 data['use_string_colored'] = ' '.join( 771 sorted([darkred(x) for x in use if not x.startswith("+")] + \ 772 [darkgreen(x) for x in use if x.startswith("+")]) + \ 773 sorted([darkblue(x) for x in use_disabled if x.startswith("-")] + \ 774 [brown(x) for x in use_disabled if x.startswith("(") and (x.find("*") == -1)] + \ 775 [purple(x) for x in use_disabled if x.startswith("(") and (x.find("*") != -1)] 776 ) 777 ) 778 return data
779
780 - def get_installed_package_useflags(self, atom):
781 782 matched_atom = self.get_installed_atom(atom) 783 if not matched_atom: 784 return {} 785 786 global_use = self.get_installed_package_setting(matched_atom, "USE") 787 use_mask = self.get_useflags_mask() 788 789 data = {} 790 data['use_mask'] = use_mask.copy() 791 data['global_use'] = global_use.split() 792 793 iuse = self.get_installed_package_setting(matched_atom, "IUSE") 794 if not isinstance(iuse,basestring): iuse = '' 795 data['iuse'] = iuse.split()[:] 796 iuse = set() 797 for myiuse in data['iuse']: 798 if myiuse.startswith("+"): 799 myiuse = myiuse[1:] 800 iuse.add(myiuse) 801 802 use = [f for f in data['global_use'] if (f in iuse) and (f not in use_mask)] 803 use_disabled = [f for f in iuse if (f not in data['global_use']) and (f not in use_mask)] 804 data['use'] = use[:] 805 data['use_disabled'] = use_disabled[:] 806 807 data['use_string'] = ' '.join(sorted(use)+sorted([x for x in use_disabled])) 808 data['use_string_colored'] = ' '.join( 809 sorted([darkred(x) for x in use if not x.startswith("+")] + \ 810 [darkgreen(x) for x in use if x.startswith("+")]) + \ 811 sorted([darkblue(x) for x in use_disabled if x.startswith("-")] + \ 812 [brown(x) for x in use_disabled if x.startswith("(") and (x.find("*") == -1)] + \ 813 [purple(x) for x in use_disabled if x.startswith("(") and (x.find("*") != -1)] 814 ) 815 ) 816 return data
817 818 # package.use
819 - def get_package_use_useflags(self, atom):
820 821 data = { 822 'enabled': set(), 823 'disabled': set(), 824 } 825 826 matched_atom = self.get_best_atom(atom) 827 if not matched_atom: 828 return data 829 830 use_file = self.get_package_use_file() 831 if not (os.path.isfile(use_file) and os.access(use_file,os.W_OK)): 832 return data 833 834 use_data = self.portage_util.grabdict(use_file) 835 for myatom in use_data: 836 mymatch = self.get_best_atom(myatom) 837 if mymatch != matched_atom: 838 continue 839 for flag in use_data[myatom]: 840 if flag.startswith("-"): 841 myflag = flag[1:] 842 data['enabled'].discard(myflag) 843 data['disabled'].add(myflag) 844 else: 845 myflag = flag 846 if myflag.startswith("+"): 847 myflag = myflag[1:] 848 data['disabled'].discard(myflag) 849 data['enabled'].add(myflag) 850 851 return data
852
853 - def get_useflags(self):
854 return self.portage.settings['USE']
855
856 - def get_useflags_force(self):
857 return self.portage.settings.useforce
858
859 - def get_useflags_mask(self):
860 return self.portage.settings.usemask
861
862 - def get_installed_package_setting(self, atom, setting):
863 mypath = etpConst['systemroot']+"/" 864 mytree = self._get_portage_vartree(mypath) 865 if atom.startswith("="): atom = atom[1:] 866 return mytree.dbapi.aux_get(atom, [setting])[0]
867
868 - def get_package_setting(self, atom, setting):
869 if atom.startswith("="): atom = atom[1:] 870 return self.portage.portdb.aux_get(atom,[setting])[0]
871
872 - def query_files(self, atom):
873 mypath = etpConst['systemroot']+"/" 874 mysplit = atom.split("/") 875 content = self.portage.dblink(mysplit[0], mysplit[1], mypath, self.portage.settings).getcontents() 876 return content.keys()
877
878 - def query_belongs(self, filename, like = False):
879 mypath = etpConst['systemroot']+"/" 880 mytree = self._get_portage_vartree(mypath) 881 packages = mytree.dbapi.cpv_all() 882 matches = set() 883 for package in packages: 884 mysplit = package.split("/") 885 content = self.portage.dblink(mysplit[0], mysplit[1], mypath, self.portage.settings).getcontents() 886 if not like: 887 if filename in content: 888 matches.add(package) 889 else: 890 for myfile in content: 891 if myfile.find(filename) != -1: 892 matches.add(package) 893 return matches
894
895 - def query_belongs_multiple(self, filenames, like = False):
896 mypath = etpConst['systemroot']+"/" 897 mytree = self._get_portage_vartree(mypath) 898 packages = mytree.dbapi.cpv_all() 899 matches = {} 900 filenames = filenames.copy() 901 for package in packages: 902 cat, pkgv = package.split("/") 903 content = self.portage.dblink(cat, pkgv, mypath, self.portage.settings).getcontents() 904 if not like: 905 for filename in filenames: 906 if filename in content: 907 myslot = self.get_installed_package_slot(package) 908 if not matches.has_key((package,myslot)): 909 matches[(package,myslot)] = set() 910 matches[(package,myslot)].add(filename) 911 else: 912 for filename in filenames: 913 for myfile in content: 914 if myfile.find(filename) != -1: 915 myslot = self.get_installed_package_slot(package) 916 if not matches.has_key((package,myslot)): 917 matches[(package,myslot)] = set() 918 matches[(package,myslot)].add(filename) 919 return matches
920
921 - def calculate_dependencies(self, my_iuse, my_use, my_license, my_depend, my_rdepend, my_pdepend, my_provide, my_src_uri):
922 metadata = {} 923 metadata['USE'] = my_use 924 metadata['IUSE'] = my_iuse 925 metadata['LICENSE'] = my_license 926 metadata['DEPEND'] = my_depend 927 metadata['PDEPEND'] = my_pdepend 928 metadata['RDEPEND'] = my_rdepend 929 metadata['PROVIDE'] = my_provide 930 metadata['SRC_URI'] = my_src_uri 931 use = metadata['USE'].split() 932 raw_use = use 933 metadata['USE_MASK'] = self.get_useflags_mask() 934 iuse = set() 935 for myiuse in metadata['IUSE'].split(): 936 if myiuse.startswith("+"): 937 myiuse = myiuse[1:] 938 if (myiuse not in use) and ("-"+myiuse not in use): 939 use.append(myiuse) 940 elif myiuse.startswith("-"): 941 myiuse = myiuse[1:] 942 iuse.add(myiuse) 943 use = sorted([f for f in use if f in iuse]) 944 metadata['USE'] = " ".join(use) 945 for k in "LICENSE", "RDEPEND", "DEPEND", "PDEPEND", "PROVIDE", "SRC_URI": 946 try: 947 deps = self.paren_reduce(metadata[k]) 948 deps = self.use_reduce(deps, uselist=raw_use) 949 deps = self.paren_normalize(deps) 950 if k == "LICENSE": 951 deps = self.paren_license_choose(deps) 952 else: 953 deps = self.paren_choose(deps) 954 if k.endswith("DEPEND"): 955 deps = self.usedeps_reduce(deps) 956 deps = ' '.join(deps) 957 except Exception, e: 958 self.entropyTools.print_traceback() 959 self.updateProgress( 960 darkred("%s: %s: %s :: %s") % ( 961 _("Error calculating dependencies"), 962 str(Exception), 963 k, 964 e, 965 ), 966 importance = 1, 967 type = "error", 968 header = red(" !!! ") 969 ) 970 deps = '' 971 continue 972 metadata[k] = deps 973 return metadata
974
975 - def usedeps_reduce(self, dependencies):
976 newlist = [] 977 for dependency in dependencies: 978 use_deps = self.entropyTools.dep_getusedeps(dependency) 979 if use_deps: 980 use_deps = [x for x in use_deps if (x[0] not in ("!",)) and (x[-1] not in ("=","?",))] 981 if use_deps: 982 dependency = "%s[%s]" % (self.entropyTools.remove_usedeps(dependency),','.join(use_deps),) 983 else: 984 dependency = self.entropyTools.remove_usedeps(dependency) 985 newlist.append(dependency) 986 return newlist
987
988 - def paren_reduce(self, mystr):
989 """ 990 991 # deps.py -- Portage dependency resolution functions 992 # Copyright 2003-2004 Gentoo Foundation 993 # Distributed under the terms of the GNU General Public License v2 994 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $ 995 996 Take a string and convert all paren enclosed entities into sublists, optionally 997 futher splitting the list elements by spaces. 998 999 Example usage: 1000 >>> paren_reduce('foobar foo ( bar baz )',1) 1001 ['foobar', 'foo', ['bar', 'baz']] 1002 >>> paren_reduce('foobar foo ( bar baz )',0) 1003 ['foobar foo ', [' bar baz ']] 1004 1005 @param mystr: The string to reduce 1006 @type mystr: String 1007 @rtype: Array 1008 @return: The reduced string in an array 1009 """ 1010 mylist = [] 1011 while mystr: 1012 left_paren = mystr.find("(") 1013 has_left_paren = left_paren != -1 1014 right_paren = mystr.find(")") 1015 has_right_paren = right_paren != -1 1016 if not has_left_paren and not has_right_paren: 1017 freesec = mystr 1018 subsec = None 1019 tail = "" 1020 elif mystr[0] == ")": 1021 return [mylist,mystr[1:]] 1022 elif has_left_paren and not has_right_paren: 1023 raise InvalidDependString( 1024 "InvalidDependString: %s: '%s'" % (_("missing right parenthesis"),mystr,)) 1025 elif has_left_paren and left_paren < right_paren: 1026 freesec,subsec = mystr.split("(",1) 1027 subsec,tail = self.paren_reduce(subsec) 1028 else: 1029 subsec,tail = mystr.split(")",1) 1030 subsec = self.strip_empty(subsec.split(" ")) 1031 return [mylist+subsec,tail] 1032 mystr = tail 1033 if freesec: 1034 mylist = mylist + self.strip_empty(freesec.split(" ")) 1035 if subsec is not None: 1036 mylist = mylist + [subsec] 1037 return mylist
1038
1039 - def strip_empty(self, myarr):
1040 """ 1041 1042 # deps.py -- Portage dependency resolution functions 1043 # Copyright 2003-2004 Gentoo Foundation 1044 # Distributed under the terms of the GNU General Public License v2 1045 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $ 1046 1047 Strip all empty elements from an array 1048 1049 @param myarr: The list of elements 1050 @type myarr: List 1051 @rtype: Array 1052 @return: The array with empty elements removed 1053 """ 1054 for x in range(len(myarr)-1, -1, -1): 1055 if not myarr[x]: 1056 del myarr[x] 1057 return myarr
1058
1059 - def use_reduce(self, deparray, uselist=[], masklist=[], matchall=0, excludeall=[]):
1060 """ 1061 1062 # deps.py -- Portage dependency resolution functions 1063 # Copyright 2003-2004 Gentoo Foundation 1064 # Distributed under the terms of the GNU General Public License v2 1065 # $Id: portage_dep.py 9174 2008-01-11 05:49:02Z zmedico $ 1066 1067 Takes a paren_reduce'd array and reduces the use? conditionals out 1068 leaving an array with subarrays 1069 1070 @param deparray: paren_reduce'd list of deps 1071 @type deparray: List 1072 @param uselist: List of use flags 1073 @type uselist: List 1074 @param masklist: List of masked flags 1075 @type masklist: List 1076 @param matchall: Resolve all conditional deps unconditionally. Used by repoman 1077 @type matchall: Integer 1078 @rtype: List 1079 @return: The use reduced depend array 1080 """ 1081 # Quick validity checks 1082 for x in range(len(deparray)): 1083 if deparray[x] in ["||","&&"]: 1084 if len(deparray) - 1 == x or not isinstance(deparray[x+1], list): 1085 mytxt = _("missing atom list in") 1086 raise InvalidDependString(deparray[x]+" "+mytxt+" \""+str(deparray)+"\"") 1087 if deparray and deparray[-1] and deparray[-1][-1] == "?": 1088 mytxt = _("Conditional without target in") 1089 raise InvalidDependString("InvalidDependString: "+mytxt+" \""+str(deparray)+"\"") 1090 1091 # This is just for use by emerge so that it can enable a backward compatibility 1092 # mode in order to gracefully deal with installed packages that have invalid 1093 # atoms or dep syntax. For backward compatibility with api consumers, strict 1094 # behavior will be explicitly enabled as necessary. 1095 _dep_check_strict = False 1096 1097 mydeparray = deparray[:] 1098 rlist = [] 1099 while mydeparray: 1100 head = mydeparray.pop(0) 1101 1102 if isinstance(head,list): 1103 additions = self.use_reduce(head, uselist, masklist, matchall, excludeall) 1104 if additions: 1105 rlist.append(additions) 1106 elif rlist and rlist[-1] == "||": 1107 #XXX: Currently some DEPEND strings have || lists without default atoms. 1108 # raise portage_exception.InvalidDependString("No default atom(s) in \""+paren_enclose(deparray)+"\"") 1109 rlist.append([]) 1110 else: 1111 if head[-1] == "?": # Use reduce next group on fail. 1112 # Pull any other use conditions and the following atom or list into a separate array 1113 newdeparray = [head] 1114 while isinstance(newdeparray[-1], basestring) and newdeparray[-1][-1] == "?": 1115 if mydeparray: 1116 newdeparray.append(mydeparray.pop(0)) 1117 else: 1118 raise ValueError, _("Conditional with no target") 1119 1120 # Deprecation checks 1121 warned = 0 1122 if len(newdeparray[-1]) == 0: 1123 mytxt = "%s. (%s)" % (_("Empty target in string"),_("Deprecated"),) 1124 self.updateProgress( 1125 darkred("PortagePlugin.use_reduce(): %s" % (mytxt,)), 1126 importance = 0, 1127 type = "error", 1128 header = bold(" !!! ") 1129 ) 1130 warned = 1 1131 if len(newdeparray) != 2: 1132 mytxt = "%s. (%s)" % (_("Nested use flags without parenthesis"),_("Deprecated"),) 1133 self.updateProgress( 1134 darkred("PortagePlugin.use_reduce(): %s" % (mytxt,)), 1135 importance = 0, 1136 type = "error", 1137 header = bold(" !!! ") 1138 ) 1139 warned = 1 1140 if warned: 1141 self.updateProgress( 1142 darkred("PortagePlugin.use_reduce(): "+" ".join(map(str,[head]+newdeparray))), 1143 importance = 0, 1144 type = "error", 1145 header = bold(" !!! ") 1146 ) 1147 1148 # Check that each flag matches 1149 ismatch = True 1150 missing_flag = False 1151 for head in newdeparray[:-1]: 1152 head = head[:-1] 1153 if not head: 1154 missing_flag = True 1155 break 1156 if head.startswith("!"): 1157 head_key = head[1:] 1158 if not head_key: 1159 missing_flag = True 1160 break 1161 if not matchall and head_key in uselist or \ 1162 head_key in excludeall: 1163 ismatch = False 1164 break 1165 elif head not in masklist: 1166 if not matchall and head not in uselist: 1167 ismatch = False 1168 break 1169 else: 1170 ismatch = False 1171 if missing_flag: 1172 mytxt = _("Conditional without flag") 1173 raise InvalidDependString( 1174 "InvalidDependString: "+mytxt+": \"" + \ 1175 str([head+"?", newdeparray[-1]])+"\"") 1176 1177 # If they all match, process the target 1178 if ismatch: 1179 target = newdeparray[-1] 1180 if isinstance(target, list): 1181 additions = self.use_reduce(target, uselist, masklist, matchall, excludeall) 1182 if additions: 1183 rlist.append(additions) 1184 elif not _dep_check_strict: 1185 # The old deprecated behavior. 1186 rlist.append(target) 1187 else: 1188 mytxt = _("Conditional without parenthesis") 1189 raise InvalidDependString( 1190 "InvalidDependString: "+mytxt+": '%s?'" % head) 1191 1192 else: 1193 rlist += [head] 1194 return rlist
1195
1196 - def paren_choose(self, dep_list):
1197 newlist = [] 1198 do_skip = False 1199 for idx in range(len(dep_list)): 1200 1201 if do_skip: 1202 do_skip = False 1203 continue 1204 1205 item = dep_list[idx] 1206 if item == "||": # or 1207 next_item = dep_list[idx+1] 1208 if not next_item: # || ( asd? ( atom ) dsa? ( atom ) ) => [] if use asd and dsa are disabled 1209 do_skip = True 1210 continue 1211 item = self.dep_or_select(next_item) # must be a list 1212 if not item: 1213 # no matches, transform to string and append, so reagent will fail 1214 newlist.append(str(next_item)) 1215 else: 1216 newlist += item 1217 do_skip = True 1218 elif isinstance(item, list): # and 1219 item = self.dep_and_select(item) 1220 newlist += item 1221 else: 1222 newlist.append(item) 1223 1224 return newlist
1225
1226 - def dep_and_select(self, and_list):
1227 do_skip = False 1228 newlist = [] 1229 for idx in range(len(and_list)): 1230 1231 if do_skip: 1232 do_skip = False 1233 continue 1234 1235 x = and_list[idx] 1236 if x == "||": 1237 x = self.dep_or_select(and_list[idx+1]) 1238 do_skip = True 1239 if not x: 1240 x = str(and_list[idx+1]) 1241 else: 1242 newlist += x 1243 elif isinstance(x, list): 1244 x = self.dep_and_select(x) 1245 newlist += x 1246 else: 1247 newlist.append(x) 1248 1249 # now verify if all are satisfied 1250 for x in newlist: 1251 match = self.get_installed_atom(x) 1252 if match == None: 1253 return [] 1254 1255 return newlist
1256
1257 - def dep_or_select(self, or_list):
1258 do_skip = False 1259 for idx in range(len(or_list)): 1260 if do_skip: 1261 do_skip = False 1262 continue 1263 x = or_list[idx] 1264 if x == "||": # or 1265 x = self.dep_or_select(or_list[idx+1]) 1266 do_skip = True 1267 elif isinstance(x, list): # and 1268 x = self.dep_and_select(x) 1269 if not x: 1270 continue 1271 # found 1272 return x 1273 else: 1274 x = [x] 1275 1276 for y in x: 1277 match = self.get_installed_atom(y) 1278 if match != None: 1279 return [y] 1280 1281 return []
1282
1283 - def paren_license_choose(self, dep_list):
1284 1285 newlist = set() 1286 for item in dep_list: 1287 1288 if isinstance(item, list): 1289 # match the first 1290 data = set(self.paren_license_choose(item)) 1291 newlist.update(data) 1292 else: 1293 if item not in ["||"]: 1294 newlist.add(item) 1295 1296 return list(newlist)
1297
1298 - def get_vdb_path(self):
1299 rc = etpConst['systemroot']+"/"+self.portage_const.VDB_PATH 1300 if (not rc.endswith("/")): 1301 return rc+"/" 1302 return rc
1303
1304 - def get_available_packages(self, categories = [], filter_reinstalls = True):
1305 mypath = etpConst['systemroot']+"/" 1306 mysettings = self._get_portage_config("/",mypath) 1307 portdb = self.portage.portdbapi(mysettings["PORTDIR"], mysettings = mysettings) 1308 cps = portdb.cp_all() 1309 visibles = set() 1310 for cp in cps: 1311 if categories and cp.split("/")[0] not in categories: 1312 continue 1313 # get slots 1314 slots = set() 1315 atoms = self.get_best_atom(cp, "match-visible") 1316 if atoms: 1317 for atom in atoms: 1318 slots.add(portdb.aux_get(atom, ["SLOT"])[0]) 1319 for slot in slots: 1320 visibles.add(cp+":"+slot) 1321 del cps 1322 1323 # now match visibles 1324 available = set() 1325 for visible in visibles: 1326 match = self.get_best_atom(visible) 1327 if match == None: 1328 continue 1329 if filter_reinstalls: 1330 installed = self.get_installed_atom(visible) 1331 # if not installed, installed == None 1332 if installed != match: 1333 available.add(match) 1334 else: 1335 available.add(match) 1336 del visibles 1337 1338 return available
1339 1340 # Collect installed packages
1341 - def get_installed_packages(self, dbdir = None, categories = []):
1342 if not dbdir: 1343 appDbDir = self.get_vdb_path() 1344 else: 1345 appDbDir = dbdir 1346 dbDirs = os.listdir(appDbDir) 1347 installedAtoms = set() 1348 for pkgsdir in dbDirs: 1349 if os.path.isdir(appDbDir+pkgsdir): 1350 pkgdir = os.listdir(appDbDir+pkgsdir) 1351 for pdir in pkgdir: 1352 pkgcat = pkgsdir.split("/")[-1] 1353 if categories and (pkgcat not in categories): 1354 continue 1355 pkgatom = pkgcat+"/"+pdir 1356 if pkgatom.find("-MERGING-") == -1: 1357 installedAtoms.add(pkgatom) 1358 return sorted(list(installedAtoms)), len(installedAtoms)
1359
1360 - def get_installed_packages_counter(self, dbdir = None):
1361 if not dbdir: 1362 appDbDir = self.get_vdb_path() 1363 else: 1364 appDbDir = dbdir 1365 installedAtoms = set() 1366 1367 for current_dirpath, subdirs, files in os.walk(appDbDir): 1368 pvs = os.listdir(current_dirpath) 1369 for mypv in pvs: 1370 if mypv.startswith("-MERGING-"): 1371 continue 1372 mypvpath = current_dirpath+"/"+mypv 1373 if not os.path.isdir(mypvpath): 1374 continue 1375 mycounter_file = mypvpath+"/"+etpConst['spm']['xpak_entries']['counter'] 1376 if not os.access(mycounter_file,os.R_OK): 1377 continue 1378 f = open(mycounter_file) 1379 try: 1380 counter = int(f.readline().strip()) 1381 except (IOError, ValueError): 1382 f.close() 1383 continue 1384 installedAtoms.add((os.path.basename(current_dirpath)+"/"+mypv,counter)) 1385 return installedAtoms
1386
1387 - def _load_sets_config(self, settings, trees):
1388 1389 # from portage.const import USER_CONFIG_PATH, GLOBAL_CONFIG_PATH 1390 setconfigpaths = [os.path.join(self.portage_const.GLOBAL_CONFIG_PATH, etpConst['setsconffilename'])] 1391 setconfigpaths.append(os.path.join(settings["PORTDIR"], etpConst['setsconffilename'])) 1392 setconfigpaths += [os.path.join(x, etpConst['setsconffilename']) for x in settings["PORTDIR_OVERLAY"].split()] 1393 setconfigpaths.append(os.path.join(settings["PORTAGE_CONFIGROOT"], 1394 self.portage_const.USER_CONFIG_PATH.lstrip(os.path.sep), etpConst['setsconffilename'])) 1395 return self.portage_sets.SetConfig(setconfigpaths, settings, trees)
1396
1397 - def get_set_config(self):
1398 # old portage 1399 if self.portage_sets == None: return 1400 myroot = etpConst['systemroot']+"/" 1401 return self._load_sets_config( 1402 self.portage.settings, 1403 self.portage.db[myroot] 1404 )
1405
1406 - def get_sets(self, builtin_sets):
1407 config = self.get_set_config() 1408 if config == None: return {} 1409 mysets = config.getSets() 1410 if not builtin_sets: 1411 builtin_pkg_sets = [x for x in self.builtin_pkg_sets if x in mysets] 1412 for pkg_set in builtin_pkg_sets: mysets.pop(pkg_set) 1413 return mysets
1414
1415 - def get_set_atoms(self, pkgset_obj):
1416 config = self.get_set_config() 1417 if config == None: return [] 1418 return config.getSetAtoms(pkgset_obj).copy()
1419
1420 - def get_sets_expanded(self, builtin_sets = True):
1421 config = self.get_set_config() 1422 if config == None: return {} 1423 mysets = {} 1424 sets = config.getSets() 1425 if not builtin_sets: 1426 builtin_pkg_sets = [x for x in self.builtin_pkg_sets if x in sets] 1427 for pkg_set in builtin_pkg_sets: sets.pop(pkg_set) 1428 for myset in sorted(sets): 1429 try: atoms = config.getSetAtoms(myset).copy() 1430 except: continue 1431 mysets[myset] = atoms 1432 return mysets
1433
1434 - def refill_counter(self, dbdir = None):
1435 if not dbdir: 1436 appDbDir = self.get_vdb_path() 1437 else: 1438 appDbDir = dbdir 1439 counters = set() 1440 for catdir in os.listdir(appDbDir): 1441 catdir = appDbDir+catdir 1442 if not os.path.isdir(catdir): 1443 continue 1444 for pkgdir in os.listdir(catdir): 1445 pkgdir = catdir+"/"+pkgdir 1446 if not os.path.isdir(pkgdir): 1447 continue 1448 counterfile = pkgdir+"/"+etpConst['spm']['xpak_entries']['counter'] 1449 if not os.path.isfile(pkgdir+"/"+etpConst['spm']['xpak_entries']['counter']): 1450 continue 1451 try: 1452 f = open(counterfile,"r") 1453 counter = int(f.readline().strip()) 1454 counters.add(counter) 1455 f.close() 1456 except: 1457 continue 1458 if counters: 1459 newcounter = max(counters) 1460 else: 1461 newcounter = 0 1462 if not os.path.isdir(os.path.dirname(etpConst['edbcounter'])): 1463 os.makedirs(os.path.dirname(etpConst['edbcounter'])) 1464 try: 1465 f = open(etpConst['edbcounter'],"w") 1466 except IOError, e: 1467 if e[0] == 21: 1468 shutil.rmtree(etpConst['edbcounter'],True) 1469 try: 1470 os.rmdir(etpConst['edbcounter']) 1471 except: 1472 pass 1473 f = open(etpConst['edbcounter'],"w") 1474 f.write(str(newcounter)) 1475 f.flush() 1476 f.close() 1477 del counters 1478 return newcounter
1479 1480
1481 - def spm_doebuild(self, myebuild, mydo, tree, cpv, portage_tmpdir = None, licenses = [], fork = False):
1482 if fork: 1483 # memory leak: some versions of portage were memleaking here 1484 return self.entropyTools.spawn_function( 1485 self._portage_doebuild, myebuild, 1486 mydo, tree, cpv, 1487 portage_tmpdir, licenses 1488 ) 1489 return self._portage_doebuild(myebuild, mydo, tree, cpv, portage_tmpdir, licenses)
1490
1491 - def _portage_doebuild(self, myebuild, mydo, tree, cpv, portage_tmpdir = None, licenses = []):
1492 # myebuild = path/to/ebuild.ebuild with a valid unpacked xpak metadata 1493 # tree = "bintree" 1494 # cpv = atom 1495 # mydbapi = portage.fakedbapi(settings=portage.settings) 1496 # vartree = portage.vartree(root=myroot) 1497 1498 oldsystderr = sys.stderr 1499 f = open("/dev/null","w") 1500 if not etpUi['debug']: 1501 sys.stderr = f 1502 1503 ### SETUP ENVIRONMENT 1504 # if mute, supress portage output 1505 domute = False 1506 if etpUi['mute']: 1507 domute = True 1508 oldsysstdout = sys.stdout 1509 sys.stdout = f 1510 1511 mypath = etpConst['systemroot']+"/" 1512 os.environ["SKIP_EQUO_SYNC"] = "1" 1513 os.environ["CD_ROOT"] = "/tmp" # workaround for scripts asking for user intervention 1514 os.environ["ROOT"] = mypath 1515 1516 if licenses: 1517 os.environ["ACCEPT_LICENSE"] = str(' '.join(licenses)) # we already do this early 1518 1519 # load metadata 1520 myebuilddir = os.path.dirname(myebuild) 1521 keys = self.portage.auxdbkeys 1522 metadata = {} 1523 1524 for key in keys: 1525 mykeypath = os.path.join(myebuilddir,key) 1526 if os.path.isfile(mykeypath) and os.access(mykeypath,os.R_OK): 1527 f = open(mykeypath,"r") 1528 metadata[key] = f.readline().strip() 1529 f.close() 1530 1531 ### END SETUP ENVIRONMENT 1532 1533 # find config 1534 mysettings = self._get_portage_config("/",mypath) 1535 mysettings['EBUILD_PHASE'] = mydo 1536 mysettings['EAPI'] = "0" 1537 if metadata.has_key('EAPI'): 1538 mysettings['EAPI'] = metadata['EAPI'] 1539 mysettings.backup_changes("EAPI") 1540 1541 try: # this is a >portage-2.1.4_rc11 feature 1542 mysettings._environ_whitelist = set(mysettings._environ_whitelist) 1543 # put our vars into whitelist 1544 mysettings._environ_whitelist.add("SKIP_EQUO_SYNC") 1545 mysettings._environ_whitelist.add("ACCEPT_LICENSE") 1546 mysettings._environ_whitelist.add("CD_ROOT") 1547 mysettings._environ_whitelist.add("ROOT") 1548 mysettings._environ_whitelist = frozenset(mysettings._environ_whitelist) 1549 except: 1550 self.write_traceback_to_log() 1551 1552 cpv = str(cpv) 1553 mysettings.setcpv(cpv) 1554 portage_tmpdir_created = False # for pkg_postrm, pkg_prerm 1555 if portage_tmpdir: 1556 if not os.path.isdir(portage_tmpdir): 1557 os.makedirs(portage_tmpdir) 1558 portage_tmpdir_created = True 1559 mysettings['PORTAGE_TMPDIR'] = str(portage_tmpdir) 1560 mysettings.backup_changes("PORTAGE_TMPDIR") 1561 1562 mydbapi = self.portage.fakedbapi(settings=mysettings) 1563 mydbapi.cpv_inject(cpv, metadata = metadata) 1564 1565 # cached vartree class 1566 vartree = self._get_portage_vartree(mypath) 1567 1568 try: 1569 rc = self.portage.doebuild( 1570 myebuild = str(myebuild), 1571 mydo = str(mydo), 1572 myroot = mypath, 1573 tree = tree, 1574 mysettings = mysettings, 1575 mydbapi = mydbapi, 1576 vartree = vartree, 1577 use_cache = 0 1578 ) 1579 except: 1580 self.write_traceback_to_log() 1581 raise 1582 1583 # if mute, restore old stdout/stderr 1584 if domute: 1585 sys.stdout = oldsysstdout 1586 1587 sys.stderr = oldsystderr 1588 f.close() 1589 1590 if portage_tmpdir_created: 1591 shutil.rmtree(portage_tmpdir,True) 1592 1593 del mydbapi 1594 del metadata 1595 del keys 1596 return rc
1597
1598 - def _extract_pkg_metadata_generate_extraction_dict(self):
1599 data = { 1600 'chost': { 1601 'path': etpConst['spm']['xpak_entries']['chost'], 1602 'critical': True, 1603 }, 1604 'description': { 1605 'path': etpConst['spm']['xpak_entries']['description'], 1606 'critical': False, 1607 }, 1608 'homepage': { 1609 'path': etpConst['spm']['xpak_entries']['homepage'], 1610 'critical': False, 1611 }, 1612 'slot': { 1613 'path': etpConst['spm']['xpak_entries']['slot'], 1614 'critical': False, 1615 }, 1616 'cflags': { 1617 'path': etpConst['spm']['xpak_entries']['cflags'], 1618 'critical': False, 1619 }, 1620 'cxxflags': { 1621 'path': etpConst['spm']['xpak_entries']['cxxflags'], 1622 'critical': False, 1623 }, 1624 'category': { 1625 'path': etpConst['spm']['xpak_entries']['category'], 1626 'critical': True, 1627 }, 1628 'rdepend': { 1629 'path': etpConst['spm']['xpak_entries']['rdepend'], 1630 'critical': False, 1631 }, 1632 'pdepend': { 1633 'path': etpConst['spm']['xpak_entries']['pdepend'], 1634 'critical': False, 1635 }, 1636 'depend': { 1637 'path': etpConst['spm']['xpak_entries']['depend'], 1638 'critical': False, 1639 }, 1640 'use': { 1641 'path': etpConst['spm']['xpak_entries']['use'], 1642 'critical': False, 1643 }, 1644 'iuse': { 1645 'path': etpConst['spm']['xpak_entries']['iuse'], 1646 'critical': False, 1647 }, 1648 'license': { 1649 'path': etpConst['spm']['xpak_entries']['license'], 1650 'critical': False, 1651 }, 1652 'provide': { 1653 'path': etpConst['spm']['xpak_entries']['provide'], 1654 'critical': False, 1655 }, 1656 'sources': { 1657 'path': etpConst['spm']['xpak_entries']['src_uri'], 1658 'critical': False, 1659 }, 1660 'eclasses': { 1661 'path': etpConst['spm']['xpak_entries']['inherited'], 1662 'critical': False, 1663 }, 1664 'counter': { 1665 'path': etpConst['spm']['xpak_entries']['counter'], 1666 'critical': False, 1667 }, 1668 'keywords': { 1669 'path': etpConst['spm']['xpak_entries']['keywords'], 1670 'critical': False, 1671 }, 1672 'spm_phases': { 1673 'path': etpConst['spm']['xpak_entries']['defined_phases'], 1674 'critical': False, 1675 }, 1676 } 1677 return data
1678
1679 - def _extract_pkg_metadata_content(self, content_file, package_path):
1680 1681 pkg_content = {} 1682 1683 if os.path.isfile(content_file): 1684 1685 f = open(content_file,"r") 1686 content = [x.decode('raw_unicode_escape') for x in f.readlines()] 1687 f.close() 1688 outcontent = set() 1689 for line in content: 1690 line = line.strip().split() 1691 try: 1692 datatype = line[0] 1693 datafile = line[1:] 1694 if datatype == 'obj': 1695 datafile = datafile[:-2] 1696 datafile = ' '.join(datafile) 1697 elif datatype == 'dir': 1698 datafile = ' '.join(datafile) 1699 elif datatype == 'sym': 1700 datafile = datafile[:-3] 1701 datafile = ' '.join(datafile) 1702 else: 1703 myexc = "InvalidData: %s %s. %s." % ( 1704 datafile, 1705 _("not supported"), 1706 _("Probably Portage API has changed"), 1707 ) 1708 raise InvalidData(myexc) 1709 outcontent.add((datafile,datatype)) 1710 except: 1711 pass 1712 1713 outcontent = sorted(outcontent) 1714 for datafile, datatype in outcontent: 1715 pkg_content[datafile] = datatype 1716 1717 else: 1718 1719 # CONTENTS is not generated when a package is emerged with portage and the option -B 1720 # we have to unpack the tbz2 and generate content dict 1721 mytempdir = etpConst['packagestmpdir']+"/"+os.path.basename(package_path)+".inject" 1722 if os.path.isdir(mytempdir): 1723 shutil.rmtree(mytempdir) 1724 if not os.path.isdir(mytempdir): 1725 os.makedirs(mytempdir) 1726 1727 self.entropyTools.uncompress_tar_bz2(package_path, extractPath = mytempdir, catchEmpty = True) 1728 tmpdir_len = len(mytempdir) 1729 for currentdir, subdirs, files in os.walk(mytempdir): 1730 pkg_content[currentdir[tmpdir_len:]] = u"dir" 1731 for item in files: 1732 item = currentdir+"/"+item 1733 if os.path.islink(item): 1734 pkg_content[item[tmpdir_len:]] = u"sym" 1735 else: 1736 pkg_content[item[tmpdir_len:]] = u"obj" 1737 1738 # now remove 1739 shutil.rmtree(mytempdir,True) 1740 try: 1741 os.rmdir(mytempdir) 1742 except (OSError,): 1743 pass 1744 1745 return pkg_content
1746
1747 - def _extract_pkg_metadata_needed(self, needed_file):
1748 1749 pkg_needed = set() 1750 lines = [] 1751 1752 try: 1753 f = open(needed_file,"r") 1754 lines = [x.decode('raw_unicode_escape').strip() for x in f.readlines() if x.strip()] 1755 f.close() 1756 except IOError: 1757 return lines 1758 1759 for line in lines: 1760 needed = line.split() 1761 if len(needed) == 2: 1762 ownlib = needed[0] 1763 ownelf = -1 1764 if os.access(ownlib,os.R_OK): 1765 ownelf = self.entropyTools.read_elf_class(ownlib) 1766 for lib in needed[1].split(","): 1767 #if lib.find(".so") != -1: 1768 pkg_needed.add((lib,ownelf)) 1769 1770 return sorted(pkg_needed)
1771
1772 - def _extract_pkg_metadata_needed_paths(self, needed_libs):
1773 1774 data = {} 1775 ldpaths = self.entropyTools.collect_linker_paths() 1776 1777 for needed_lib, elf_class in needed_libs: 1778 for ldpath in ldpaths: 1779 my_lib = os.path.join(ldpath, needed_lib) 1780 if not os.access(my_lib, os.R_OK): 1781 continue 1782 myclass = self.entropyTools.read_elf_class(my_lib) 1783 if myclass != elf_class: 1784 continue 1785 obj = data.setdefault(needed_lib, set()) 1786 obj.add(my_lib) 1787 1788 return data
1789
1790 - def _extract_pkg_metadata_messages(self, log_dir, category, name, version, silent = False):
1791 1792 pkg_messages = [] 1793 1794 if os.path.isdir(log_dir): 1795 1796 elogfiles = os.listdir(log_dir) 1797 myelogfile = "%s:%s-%s" % (category, name, version,) 1798 foundfiles = [x for x in elogfiles if x.startswith(myelogfile)] 1799 if foundfiles: 1800 elogfile = foundfiles[0] 1801 if len(foundfiles) > 1: 1802 # get the latest 1803 mtimes = [] 1804 for item in foundfiles: mtimes.append((self.entropyTools.get_file_unix_mtime(os.path.join(log_dir,item)),item)) 1805 mtimes = sorted(mtimes) 1806 elogfile = mtimes[-1][1] 1807 messages = self.entropyTools.extract_elog(os.path.join(log_dir,elogfile)) 1808 for message in messages: 1809 message = message.replace("emerge","install") 1810 pkg_messages.append(message.decode('raw_unicode_escape')) 1811 1812 elif not silent: 1813 1814 mytxt = " %s, %s" % (_("not set"),_("have you configured make.conf properly?"),) 1815 self.updateProgress( 1816 red(log_dir)+mytxt, 1817 importance = 1, 1818 type = "warning", 1819 header = brown(" * ") 1820 ) 1821 1822 return pkg_messages
1823
1824 - def _extract_pkg_metadata_license_data(self, licenses_dir, license_string):
1825 1826 pkg_licensedata = {} 1827 if licenses_dir and os.path.isdir(licenses_dir): 1828 licdata = [x.strip() for x in license_string.split() if x.strip() and self.entropyTools.is_valid_string(x.strip())] 1829 for mylicense in licdata: 1830 licfile = os.path.join(licenses_dir,mylicense) 1831 if os.access(licfile,os.R_OK): 1832 if self.entropyTools.istextfile(licfile): 1833 f = open(licfile) 1834 content = '' 1835 line = f.readline() 1836 while line: 1837 content += line 1838 line = f.readline() 1839 try: 1840 try: 1841 pkg_licensedata[mylicense] = content.decode('raw_unicode_escape') 1842 except UnicodeDecodeError: 1843 pkg_licensedata[mylicense] = unicode(content,'utf-8') 1844 except (UnicodeDecodeError, UnicodeEncodeError,): 1845 continue # sorry! 1846 f.close() 1847 1848 return pkg_licensedata
1849 1863
1864 - def _extract_pkg_metadata_ebuild_entropy_tag(self, ebuild):
1865 search_tag = etpConst['spm']['ebuild_pkg_tag_var'] 1866 ebuild_tag = '' 1867 f = open(ebuild,"r") 1868 tags = [x.strip().decode('raw_unicode_escape') for x in f.readlines() if x.strip() and x.strip().startswith(search_tag)] 1869 f.close() 1870 if not tags: return ebuild_tag 1871 tag = tags[-1] 1872 tag = tag.split("=")[-1].strip('"').strip("'").strip() 1873 return tag
1874 1875 # This function extracts all the info from a .tbz2 file and returns them
1876 - def extract_pkg_metadata(self, package, silent = False, inject = False):
1877 1878 data = {} 1879 info_package = bold(os.path.basename(package))+": " 1880 system_settings = SystemSettings() 1881 1882 if not silent: 1883 self.updateProgress( 1884 red(info_package+_("Extracting package metadata")+" ..."), 1885 importance = 0, 1886 type = "info", 1887 header = brown(" * "), 1888 back = True 1889 ) 1890 1891 filepath = package 1892 tbz2File = package 1893 package = package.split(etpConst['packagesext'])[0] 1894 package = self.entropyTools.remove_entropy_revision(package) 1895 package = self.entropyTools.remove_tag(package) 1896 # remove entropy category 1897 if package.find(":") != -1: 1898 package = ':'.join(package.split(":")[1:]) 1899 1900 # pkgcat is always == "null" here 1901 pkgcat, pkgname, pkgver, pkgrev = self.entropyTools.catpkgsplit(os.path.basename(package)) 1902 if pkgrev != "r0": pkgver += "-%s" % (pkgrev,) 1903 1904 # Fill Package name and version 1905 data['name'] = pkgname 1906 data['version'] = pkgver 1907 data['digest'] = self.entropyTools.md5sum(tbz2File) 1908 data['signatures'] = { 1909 'sha1': self.entropyTools.sha1(tbz2File), 1910 'sha256': self.entropyTools.sha256(tbz2File), 1911 'sha512': self.entropyTools.sha512(tbz2File), 1912 } 1913 data['datecreation'] = str(self.entropyTools.get_file_unix_mtime(tbz2File)) 1914 data['size'] = str(self.entropyTools.get_file_size(tbz2File)) 1915 1916 tbz2TmpDir = etpConst['packagestmpdir']+"/"+data['name']+"-"+data['version']+"/" 1917 if not os.path.isdir(tbz2TmpDir): 1918 if os.path.lexists(tbz2TmpDir): 1919 os.remove(tbz2TmpDir) 1920 os.makedirs(tbz2TmpDir) 1921 self.entropyTools.extract_xpak(tbz2File,tbz2TmpDir) 1922 1923 data['injected'] = False 1924 if inject: data['injected'] = True 1925 data['branch'] = system_settings['repositories']['branch'] 1926 1927 portage_entries = self._extract_pkg_metadata_generate_extraction_dict() 1928 for item in portage_entries: 1929 value = '' 1930 try: 1931 f = open(os.path.join(tbz2TmpDir,portage_entries[item]['path']),"r") 1932 value = f.readline().strip().decode('raw_unicode_escape') 1933 f.close() 1934 except IOError: 1935 if portage_entries[item]['critical']: 1936 raise 1937 data[item] = value 1938 1939 # setup spm_phases properly 1940 spm_defined_phases_path = os.path.join(tbz2TmpDir, 1941 portage_entries['spm_phases']['path']) 1942 if not os.path.isfile(spm_defined_phases_path): 1943 # force to None, because metadatum can be '', which is valid 1944 data['spm_phases'] = None 1945 1946 # setup vars 1947 # eclasses must be a set as returned by entropy.db.getPackageData 1948 data['eclasses'] = set(data['eclasses'].split()) 1949 try: 1950 data['counter'] = int(data['counter']) 1951 except ValueError: 1952 data['counter'] = -2 # -2 values will be insterted as incremental negative values into the database 1953 data['keywords'] = [x.strip() for x in data['keywords'].split() if x.strip()] 1954 if not data['keywords']: data['keywords'].insert(0,"") # support for packages with no keywords 1955 # keywords must be a set, as returned by 1956 # entropy.db.getPackageData 1957 data['keywords'] = set(data['keywords']) 1958 needed_file = os.path.join(tbz2TmpDir,etpConst['spm']['xpak_entries']['needed']) 1959 data['needed'] = self._extract_pkg_metadata_needed(needed_file) 1960 data['needed_paths'] = self._extract_pkg_metadata_needed_paths(data['needed']) 1961 content_file = os.path.join(tbz2TmpDir,etpConst['spm']['xpak_entries']['contents']) 1962 data['content'] = self._extract_pkg_metadata_content(content_file, filepath) 1963 data['disksize'] = self.entropyTools.sum_file_sizes(data['content']) 1964 1965 # [][][] Kernel dependent packages hook [][][] 1966 data['versiontag'] = '' 1967 kernelstuff = False 1968 kernelstuff_kernel = False 1969 for item in data['content']: 1970 if item.startswith("/lib/modules/"): 1971 kernelstuff = True 1972 # get the version of the modules 1973 kmodver = item.split("/lib/modules/")[1] 1974 kmodver = kmodver.split("/")[0] 1975 1976 lp = kmodver.split("-")[-1] 1977 if lp.startswith("r"): 1978 kname = kmodver.split("-")[-2] 1979 kver = kmodver.split("-")[0]+"-"+kmodver.split("-")[-1] 1980 else: 1981 kname = kmodver.split("-")[-1] 1982 kver = kmodver.split("-")[0] 1983 break 1984 # validate the results above 1985 if kernelstuff: 1986 matchatom = "linux-%s-%s" % (kname,kver,) 1987 if (matchatom == data['name']+"-"+data['version']): 1988 kernelstuff_kernel = True 1989 1990 data['versiontag'] = kmodver 1991 if not kernelstuff_kernel: 1992 data['slot'] = kmodver # if you change this behaviour, 1993 # you must change "reagent update" 1994 # and "equo database gentoosync" consequentially 1995 1996 file_ext = etpConst['spm']['ebuild_file_extension'] 1997 ebuilds_in_path = [x for x in os.listdir(tbz2TmpDir) if x.endswith(".%s" % (file_ext,))] 1998 if not data['versiontag'] and ebuilds_in_path: 1999 # has the user specified a custom package tag inside the ebuild 2000 ebuild_path = os.path.join(tbz2TmpDir,ebuilds_in_path[0]) 2001 data['versiontag'] = self._extract_pkg_metadata_ebuild_entropy_tag(ebuild_path) 2002 2003 2004 data['download'] = etpConst['packagesrelativepath'] + data['branch'] + "/" 2005 data['download'] += self.entropyTools.create_package_filename(data['category'], data['name'], data['version'], data['versiontag']) 2006 2007 2008 data['trigger'] = "" 2009 if os.path.isfile(etpConst['triggersdir']+"/"+data['category']+"/"+data['name']+"/"+etpConst['triggername']): 2010 f = open(etpConst['triggersdir']+"/"+data['category']+"/"+data['name']+"/"+etpConst['triggername'],"rb") 2011 data['trigger'] = f.read() 2012 f.close() 2013 2014 # Get Spm ChangeLog 2015 pkgatom = "%s/%s-%s" % (data['category'],data['name'],data['version'],) 2016 try: 2017 data['changelog'] = unicode(self.get_package_changelog(pkgatom), 2018 'raw_unicode_escape') 2019 except (UnicodeEncodeError, UnicodeDecodeError,), e: 2020 self.updateProgress( 2021 red(info_package) + _("changelog string conversion error") + \ 2022 " " + bold(str(e)), 2023 importance = 0, type = "warning", header = bold(" !!! ") 2024 ) 2025 data['changelog'] = None 2026 except: 2027 data['changelog'] = None 2028 2029 portage_metadata = self.calculate_dependencies( 2030 data['iuse'], data['use'], data['license'], data['depend'], 2031 data['rdepend'], data['pdepend'], data['provide'], data['sources'] 2032 ) 2033 2034 data['provide'] = set(portage_metadata['PROVIDE'].split()) 2035 data['license'] = portage_metadata['LICENSE'] 2036 data['useflags'] = [] 2037 2038 for my_use in data['iuse'].split(): 2039 if my_use[0] in ("-","+",): 2040 my_use = my_use[1:] 2041 2042 if (my_use in portage_metadata['USE']) or \ 2043 (my_use in portage_metadata['USE_MASK']): 2044 data['useflags'].append(my_use) 2045 else: 2046 data['useflags'].append("-"+my_use) 2047 2048 # useflags must be a set, as returned by entropy.db.getPackageData 2049 data['useflags'] = set(data['useflags']) 2050 # sources must be a set, as returned by entropy.db.getPackageData 2051 data['sources'] = set(portage_metadata['SRC_URI'].split()) 2052 data['dependencies'] = {} 2053 for x in portage_metadata['RDEPEND'].split(): 2054 if x.startswith("!") or (x in ("(","||",")","")): 2055 continue 2056 data['dependencies'][x] = etpConst['spm']['(r)depend_id'] 2057 for x in portage_metadata['PDEPEND'].split(): 2058 if x.startswith("!") or (x in ("(","||",")","")): 2059 continue 2060 data['dependencies'][x] = etpConst['spm']['pdepend_id'] 2061 data['conflicts'] = [x[1:] for x in \ 2062 portage_metadata['RDEPEND'].split() + \ 2063 portage_metadata['PDEPEND'].split() if \ 2064 x.startswith("!") and not x in ("(","||",")","")] 2065 2066 if (kernelstuff) and (not kernelstuff_kernel): 2067 # add kname to the dependency 2068 data['dependencies'][u"=sys-kernel/linux-"+kname+"-"+kver+"~-1"] = etpConst['spm']['(r)depend_id'] 2069 2070 # Conflicting tagged packages support 2071 key = data['category']+"/"+data['name'] 2072 confl_data = system_settings['conflicting_tagged_packages'].get(key) 2073 if confl_data != None: 2074 for conflict in confl_data: data['conflicts'].append(conflict) 2075 2076 # conflicts must be a set, which is what is returned 2077 # by entropy.db.getPackageData 2078 data['conflicts'] = set(data['conflicts']) 2079 2080 # Get License text if possible 2081 licenses_dir = os.path.join(self.get_spm_setting('PORTDIR'),'licenses') 2082 data['licensedata'] = self._extract_pkg_metadata_license_data(licenses_dir, data['license']) 2083 data['mirrorlinks'] = self._extract_pkg_metadata_mirror_links(data['sources']) 2084 2085 # write only if it's a systempackage 2086 data['systempackage'] = False 2087 system_packages = [self.entropyTools.dep_getkey(x) for x in self.get_atoms_in_system()] 2088 if data['category']+"/"+data['name'] in system_packages: 2089 data['systempackage'] = True 2090 2091 # write only if it's a systempackage 2092 protect, mask = self.get_config_protect_and_mask() 2093 data['config_protect'] = protect 2094 data['config_protect_mask'] = mask 2095 2096 log_dir = etpConst['logdir']+"/elog" 2097 if not os.path.isdir(log_dir): os.makedirs(log_dir) 2098 data['messages'] = self._extract_pkg_metadata_messages(log_dir, data['category'], data['name'], data['version'], silent = silent) 2099 # etpapi must be int, as returned by entropy.db.getPackageData 2100 data['etpapi'] = int(etpConst['etpapi']) 2101 2102 # removing temporary directory 2103 shutil.rmtree(tbz2TmpDir,True) 2104 if os.path.isdir(tbz2TmpDir): 2105 try: os.remove(tbz2TmpDir) 2106 except OSError: pass 2107 2108 if not silent: 2109 self.updateProgress( 2110 red(info_package+_("Package extraction complete")), importance = 0, 2111 type = "info", header = brown(" * "), back = True 2112 ) 2113 2114 # clear unused metadata 2115 del data['use'], data['iuse'], data['depend'], data['pdepend'], \ 2116 data['rdepend'] 2117 2118 return data
2119